(** Time-stamp: <modified the 13/05/2008 (at 09:47) by Erwan Jahier> *) (** Here follows a description of the different modules used by this lus2lic compiler. (1) First of all, the Lustre files are parsed, lexer.mll parser.mly parserUtils.ml lxm.mli/ml which results into a parse tree containing raw source expressions. syntaxTree.ml -> should rather be called rawSyntaxTab.ml ? syntaxTreedump.ml (2) Then, we perform reference checking at module level + model expansion. syntaxTab.mli/ml syntaxTabUtil.ml/mli expandPack.mli/ml symbolTab.mli/ml (type/const/node) syntaxTab is a kind of layer above syntaxTree to make things easier afterwards. (3) Finally, the compilation (type checking+const/type evaluation) is performed. compile.ml lazyCompiler.mli/ml evalConst.mli/ml evalType.mli/ml compiledData.ml Some misc (eponymous) modules are used along the way. errors.ml verbose.mli/ml version.ml ident.ml *) open Verbose open SyntaxTree open SyntaxTreeCore open Lxm open Errors open Parsing open Format open Global let usage_msg = "usage: "^(Version.tool)^" [options] <lustre files> | "^(Version.tool)^" -help" (*--------------------------------------------------------- Les args sont des variables GLOBALES ---------------------------------------------------------*) let print_version = function (x: unit) -> ( print_string (Version.str ^ "\n") ) let rec set_infile = function (x:string) -> ( if ( _lus2lic_ARGS.main_node = "main" ) then ( (* default node name = file name *) try _lus2lic_ARGS.main_node <- Filename.chop_extension (Filename.basename x) with _ -> print_string ("*** '" ^ x ^ "': Bad file name\n"); exit 1 ); _lus2lic_ARGS.infiles <- _lus2lic_ARGS.infiles@[x] ) and arg_list = [ ( "-version", Arg.Unit(function x -> print_version () ; exit 0), " print the current version then exit" ); ( "-o", Arg.String(function x -> _lus2lic_ARGS.outfile <- x), " <file name> set the output file name" ); ( "-n", Arg.String(function x -> _lus2lic_ARGS.main_node <- x), " <node> set the main node" ); ( "--compile-all-items", Arg.Unit (function x -> _lus2lic_ARGS.compile_all_items <- true), " compile all items of the program" ); ( "-v", Arg.Unit (function vl -> Verbose.set_level 1 ), " set verbose mode on (i.e., verbose level = 1)" ); ( "-vl", Arg.Int(function vl -> Verbose.set_level vl ), " <int> set verbose level" ) ] and parse_args () = ( Arg.parse arg_list (* liste des options *) set_infile (* arg par defaut = fichier d'entree *) usage_msg (* message d'erreur *) ; () ) let test_lex ( lexbuf ) = ( let tk = ref (Lexer.lexer lexbuf) in ( while !tk <> Parser.TK_EOF do match (Lexer.token_code !tk) with ( co , lxm ) -> printf "%s : %15s = \"%s\"\n" (Lxm.position lxm) co (Lxm.str lxm) ; tk := (Lexer.lexer lexbuf) done ) ) (* Retourne un parse_tree *) let lus_load lexbuf = ( (Parser.sxLusFile Lexer.lexer lexbuf) ) (* Dump d'un packbody *) let dump_body (pkg: SyntaxTree.packbody) = ( let os = Format.formatter_of_out_channel stdout in SyntaxTreeDump.packbody os pkg ) (* Dump d'un name-space, pack ou modele ... *) let dump_ns (ns: SyntaxTree.pack_or_model) = ( let os = Format.formatter_of_out_channel stdout in match ns with NSPack pf -> ( (* Verbose.printf (lazy ("DUMP PACKDEF\n")); *) SyntaxTreeDump.packinfo os pf ) | NSModel mf -> ( (* Verbose.printf (lazy ("DUMP MODDEF\n")); *) SyntaxTreeDump.modelinfo os mf ) ) (* Lance le parser et renvoie la liste name-spaces d'entr�e. Dans le cas d'un fichier sans package, on lui donne comme nom le basename de infile. *) type maybe_packed = | Packed of SyntaxTree.pack_or_model list | Unpacked of SyntaxTree.pack_or_model let (get_source_list : string list -> SyntaxTree.pack_or_model list) = fun infile_list -> let (get_one_source : string -> maybe_packed) = fun infile -> let inchannel = open_in infile in let lexbuf = Lexing.from_channel inchannel in Verbose.print_string ~level:3 ("Opening file " ^ infile ^ "\n"); _lus2lic_ARGS.current_file <- infile; match (lus_load lexbuf) with | PRPackBody pbdy -> let nme = try Filename.chop_extension (Filename.basename infile) with _ -> print_string ("*** '"^infile^"': Bad file name\n"); exit 1 in let pi = SyntaxTree.give_pack_this_name (Ident.pack_name_of_string nme) pbdy in Unpacked (NSPack (Lxm.flagit pi (Lxm.dummy nme))) | PRPack_or_models nsl -> Packed nsl in let (get_remaining_source_list : maybe_packed -> string -> maybe_packed) = fun acc infile -> match acc, get_one_source infile with | Unpacked _, _ | _, Unpacked _ -> print_string ("old-style (un-packaged) lustre files can " ^ " not be mixed with packages, nor be " ^ " defined in more than 1 file."); exit 1 | Packed l1, Packed l2 -> Packed (l1@l2) in let pack_list = assert (infile_list <> []); List.fold_left get_remaining_source_list (get_one_source (List.hd infile_list)) (List.tl infile_list) in match pack_list with | Packed l -> l | Unpacked pack -> [pack] let my_exit i = close_out !Global.oc; if Sys.file_exists _lus2lic_ARGS.outfile then Sys.remove _lus2lic_ARGS.outfile; exit i let main = ( (* Compile.init_appli () ; *) parse_args () ; if (_lus2lic_ARGS.infiles = []) then ( Arg.usage arg_list usage_msg ; exit 1 ) ; try ( let nsl = get_source_list _lus2lic_ARGS.infiles in let main_node = Ident.idref_of_string _lus2lic_ARGS.main_node in if _lus2lic_ARGS.outfile <> "" then Global.oc := open_out _lus2lic_ARGS.outfile; Compile.doit nsl main_node; close_out !Global.oc ) with Sys_error(s) -> prerr_string (s^"\n"); my_exit 1 | Global_error s -> print_global_error s ; my_exit 1 | Parse_error -> print_compile_error (Lxm.last_made ()) "syntax error"; my_exit 1 | Compile_error(lxm,msg) -> print_compile_error lxm msg ; my_exit 1 | Assert_failure (file, line, col) -> prerr_string ( "\n*** oops: an internal error occurred in file "^ file ^ ", line " ^ (string_of_int line) ^ ", column " ^ (string_of_int col) ^ "\n*** when compiling lustre program" ^ (if List.length _lus2lic_ARGS.infiles > 1 then "s " else " ") ^ (String.concat ", " _lus2lic_ARGS.infiles) ^ "\n") ; my_exit 2 (* | Compile_node_error(nkey,lxm,msg) -> ( *) (* print_compile_node_error nkey lxm msg ; *) (* exit 1 *) (* ) *) (* | Global_node_error(nkey,msg) -> ( *) (* print_global_node_error nkey msg ; *) (* exit 1 *) (* ) *) )