Project

General

Profile

Download (7.19 KB) Statistics
| Branch: | Tag: | Revision:
1
(********************************************************************)
2
(*                                                                  *)
3
(*  The LustreC compiler toolset   /  The LustreC Development Team  *)
4
(*  Copyright 2012 -    --   ONERA - CNRS - INPT                    *)
5
(*                                                                  *)
6
(*  LustreC is free software, distributed WITHOUT ANY WARRANTY      *)
7
(*  under the terms of the GNU Lesser General Public License        *)
8
(*  version 2.1.                                                    *)
9
(*                                                                  *)
10
(********************************************************************)
11

    
12
(* This module is used for the lustre test generator *)
13

    
14
open Format
15
open Log
16

    
17
open Utils
18
open Compiler_common
19

    
20
let usage = "Usage: lustret [options] \x1b[4msource file\x1b[0m"
21

    
22
let extensions = [".lus"]
23

    
24
let pp_trace trace_filename mutation_list = 
25
  let trace_file = open_out trace_filename in
26
  let trace_fmt = formatter_of_out_channel trace_file in
27
  Format.fprintf trace_fmt "@[<v 2>{@ %a@ }@]"
28
    (fprintf_list
29
       ~sep:",@ "
30
       (fun fmt (mutation, mutation_loc, mutant_name) ->
31
	 Format.fprintf fmt "\"%s\": { @[<v 0>%a,@ %a@ }@]" 
32
	   mutant_name
33
	   Mutation.print_directive_json mutation
34
	   Mutation.print_loc_json mutation_loc
35
       ))
36
    mutation_list;
37
  Format.fprintf trace_fmt "@.@?" 
38
  
39
  
40
let testgen_source dirname basename extension =
41
  let source_name = dirname ^ "/" ^ basename ^ extension in
42

    
43
  Log.report ~level:1 (fun fmt -> fprintf fmt "@[<v>");
44

    
45
  (* Parsing source *)
46
  let prog = parse source_name extension in
47
  let params = Backends.get_normalization_params () in
48
  let prog, _ =
49
    try
50
      Compiler_stages.stage1 params prog dirname basename extension 
51
    with Compiler_stages.StopPhase1 prog -> (
52
        if !Options.print_nodes then (
53
          Format.printf "%a@.@?" Printers.pp_node_list prog;
54
          exit 0
55
        )
56
        else
57
          assert false
58
      )
59
  in
60
  
61
  (* Two cases
62
     - generation of coverage conditions
63
     - generation of mutants: a number of mutated lustre files 
64
  *)
65
  
66
  if !Options.gen_mcdc then (
67
    let prog_mcdc = PathConditions.mcdc prog in
68
    (* We re-type the fresh equations *)
69
    (*let _ = Modules.load ~is_header:false prog_mcdc in*)
70
    let _ = type_decls !Global.type_env prog_mcdc in
71
    
72
    let destname = !Options.dest_dir ^ "/" ^ basename in
73
    let source_file = destname ^ ".mcdc" in (* Could be changed *)
74

    
75
    (* Modified Lustre is produced in fresh .lus file *)
76
    let source_lus = source_file ^ ".lus" in
77
    let source_out = open_out source_lus in
78
    let fmt = formatter_of_out_channel source_out in
79
    Printers.pp_prog fmt prog_mcdc;
80
    Format.fprintf fmt "@.@?";
81

    
82
    (* Prog is 
83
       (1) cleaned from initial equations TODO
84
       (2) produced as EMF
85
    *)
86
    Options.output := "emf";
87
    let params = Backends.get_normalization_params () in
88
    let prog_mcdc = Normalization.normalize_prog params prog_mcdc in
89
    let prog_mcdc, machine_code = Compiler_stages.stage2 params prog_mcdc in
90
    let source_emf = source_file ^ ".emf" in 
91
    let source_out = open_out source_emf in
92
    let fmt = formatter_of_out_channel source_out in
93
    EMF_backend.translate fmt basename prog_mcdc machine_code;
94

    
95
    exit 0
96
  ) ;
97

    
98
  
99
  (* generate mutants *)
100
  let mutants = Mutation.mutate !Options.nb_mutants prog in
101
  
102
  (* Print generated mutants in target directory. *)
103
  let cpt = ref 0 in
104
  let mutation_list =
105
    List.map (fun (mutation, mutation_loc, mutant) ->
106
    (* Debugging code *)
107
    (* if List.mem !cpt [238;371;601;799;875;998] then *)
108
    (*   Format.eprintf "Mutant %i: %a -> %a" !cpt Printers.pp_expr orig_e Printers.pp_expr new_e  *)
109
    (* ; *)
110
      incr cpt;
111
      let mutant_basename = (Filename.basename basename)^ ".mutant.n" ^ (string_of_int !cpt) ^ extension  in
112
      let mutant_filename = 
113
	match !Options.dest_dir with
114
	| "" -> (* Mutants are generated in source directory *)
115
	   basename^ ".mutant.n" ^ (string_of_int !cpt) ^ extension 
116
      | dir ->  (* Mutants are generated in target directory *)
117
	 dir ^ "/" ^ mutant_basename 
118
    in
119
    let mutant_out = (
120
      try 
121
	open_out mutant_filename 
122
      with
123
	Sys_error _ -> Format.eprintf "Unable to open file %s for writing.@." mutant_filename; exit 1
124
    )
125
    in
126
    let mutant_fmt = formatter_of_out_channel mutant_out in
127
    report ~level:1 (fun fmt -> fprintf fmt ".. generating mutant %s: %a@,@?"
128
      mutant_filename
129
      Mutation.print_directive mutation
130
    );
131
    Format.fprintf mutant_fmt "%a@." Printers.pp_prog mutant;
132
    mutation, mutation_loc, mutant_basename
133
    )
134
      mutants
135
  in
136
  Log.report ~level:1 (fun fmt -> fprintf fmt ".. done @ @]@.");
137
  
138
  (* Printing traceability *)
139
  let trace_filename = 
140
    match !Options.dest_dir with
141
    | "" -> (* Mutant report is generated in source directory *)
142
       basename^ ".mutation.json" 
143
    | dir ->  (* Mutants are generated in target directory *)
144
       dir ^ "/" ^ (Filename.basename basename)^ ".mutation.json"
145
  in
146
  pp_trace trace_filename mutation_list;
147

    
148
  (* Printing the CMakeLists.txt file *)
149
  let cmakelists = 
150
    (if !Options.dest_dir = "" then "" else !Options.dest_dir ^ "/") ^ "CMakeLists.txt"
151
  in
152
  let cmake_file = open_out cmakelists in
153
  let cmake_fmt = formatter_of_out_channel cmake_file in
154
  Format.fprintf cmake_fmt "cmake_minimum_required(VERSION 3.5)@.";
155
  Format.fprintf cmake_fmt "include(\"%s/helpful_functions.cmake\")@." Version.testgen_path;
156
  Format.fprintf cmake_fmt "include(\"%s/FindLustre.cmake\")@." Version.testgen_path;
157
  Format.fprintf cmake_fmt "LUSTREFILES(LFILES ${CMAKE_CURRENT_SOURCE_DIR} )@.";
158
  Format.fprintf cmake_fmt "@[<v 2>FOREACH(lus_file ${LFILES})@ ";
159
  Format.fprintf cmake_fmt "get_lustre_name_ext(${lus_file} L E)@ ";
160
  Format.fprintf cmake_fmt "Lustre_Compile(@[<v 0>@ ";
161
  if !Options.main_node <> "" then Format.fprintf cmake_fmt "NODE \"%s_mutant\"@ " !Options.main_node;
162
  Format.fprintf cmake_fmt "LIBNAME \"${L}_%s_mutant\"@ " !Options.main_node;
163
  Format.fprintf cmake_fmt "LUS_FILES \"${lus_file}\")@]@]@.";
164
  Format.fprintf cmake_fmt "ENDFOREACH()@.@?";
165
  
166
  
167
  (* We stop the process here *)
168
  exit 0
169
    
170
let testgen dirname basename extension =
171
  match extension with
172
  | ".lus"   -> testgen_source dirname basename extension
173
  | _        -> assert false
174

    
175
let anonymous filename =
176
  let ok_ext, ext = List.fold_left
177
    (fun (ok, ext) ext' ->
178
      if not ok && Filename.check_suffix filename ext' then
179
	true, ext'
180
      else
181
	ok, ext)
182
    (false, "") extensions in
183
  if ok_ext then
184
    let dirname = Filename.dirname filename in
185
    let basename = Filename.chop_suffix (Filename.basename filename) ext in
186
    testgen dirname basename ext
187
  else
188
    raise (Arg.Bad ("Can only compile *.lus files"))
189

    
190
let _ =
191
  Global.initialize ();
192
  Corelang.add_internal_funs ();
193
  try
194
    Printexc.record_backtrace true;
195

    
196
    let options = Options_management.lustret_options
197

    
198
    in
199
    
200
    Arg.parse options anonymous usage
201
  with
202
  | Parse.Error _
203
  | Types.Error (_,_) | Clocks.Error (_,_)
204
  | Error.Error _ (*| Task_set.Error _*)
205
  | Causality.Error _ -> exit 1
206
  | Sys_error msg -> (eprintf "Failure: %s@." msg)
207
  | exc -> (track_exception (); raise exc)
208

    
209
(* Local Variables: *)
210
(* compile-command:"make -C .." *)
211
(* End: *)
(36-36/63)