Skip to content
Snippets Groups Projects
main.ml 4.44 KiB
Newer Older
  • Learn to ignore specific revisions
  • charguer's avatar
    charguer committed
    
    
    open Params
    
    charguer's avatar
    gen
    charguer committed
    open Format
    open Mytools
    
    
    charguer's avatar
    charguer committed
    (*
       Remark: field name attributes for builtins (eg: ::) are defined in attributes.ml
       Remark: field name attributes should not be "type" or "tag".
    *)
    
    
    
    charguer's avatar
    gen
    charguer committed
    (*#########################################################################*)
    
    let ppf = Format.std_formatter
    
    (* err_formatter *)
    
    
    (*#########################################################################*)
    
    
    charguer's avatar
    charguer committed
    
    
    let tool_name = "ml2js"
    
    let init_path () =
      Config.load_path :=
        "stdlib_ml" :: List.rev (Config.standard_library :: !Clflags.include_dirs);
      Env.reset_cache ()
    
    (** Return the initial environment in which compilation proceeds. *)
    let initial_env () =
      try
        let env = Env.initial_unsafe_string in
        Env.open_pers_signature "Stdlib" env
      with Not_found ->
        Misc.fatal_error "cannot open stdlib"
    
    
    Thomas Wood's avatar
    Thomas Wood committed
    (** Analysis of an implementation file.
     *  ppf: error printer
     *  sourcefile: path/filename of source file
     *  oprefix: output file name prefix (possibly manually set with -o)
     **)
    let process_implementation_file ppf sourcefile oprefix =
    
      init_path ();
      let modulename = Compenv.module_of_filename ppf sourcefile oprefix in
      Env.set_unit_name modulename;
      let env = initial_env () in
      try
        let parsetree = Pparse.parse_implementation ~tool_name ppf sourcefile in
        if !Clflags.dump_source then fprintf ppf "%a@." Pprintast.structure parsetree;
        let typing = Typemod.type_implementation sourcefile oprefix modulename env parsetree in
        (parsetree, typing, modulename)
      with e ->
        Location.report_exception ppf e;
        exit 2
    
    
    charguer's avatar
    gen
    charguer committed
    let _ =
       (*---------------------------------------------------*)
       (* parsing of command line *)
    
       let files = ref [] in
    
    Thomas Wood's avatar
    Thomas Wood committed
         [ ("-I", Arg.String (add_to_list Clflags.include_dirs), "includes a directory where to look for interface files");
           ("-o", Arg.String (fun s -> Clflags.output_name := Some s), "set the output file");
    
           ("-debug", Arg.Set debug, "trace the various steps");
    
           ("-dsource", Arg.Set Clflags.dump_source, "dump source after ppx");
    
    charguer's avatar
    charguer committed
           ("-ppx", Arg.String (add_to_list Clflags.all_ppx (* TODO Compenv.first_ppx *) ), "load ppx");
    
    Alan Schmitt's avatar
    Alan Schmitt committed
           ("-mode", Arg.String (fun s -> set_current_mode s), "current mode: unlog, log, or token")
    
         ]
         (fun f -> files := f :: !files)
    
    charguer's avatar
    gen
    charguer committed
         ("usage: [-I dir] [..other options..] file.ml");
    
    charguer's avatar
    charguer committed
    
    
    
    charguer's avatar
    charguer committed
       files := List.rev !files;
    
    charguer's avatar
    gen
    charguer committed
       if List.length !files <> 1 then
          failwith "Expects one argument: the filename of the ML source file";
       let sourcefile = List.hd !files in
    
    Thomas Wood's avatar
    Thomas Wood committed
    
    
    charguer's avatar
    gen
    charguer committed
       if not (Filename.check_suffix sourcefile ".ml") then
         failwith "The file name must be of the form *.ml";
    
    Thomas Wood's avatar
    Thomas Wood committed
    
       let sourcebase = Filename.basename sourcefile in   (* Input file basename, for logging *)
       let oprefix = Compenv.output_prefix sourcefile in (* Output filename prefix, inc. path *)
       let output_filename = oprefix ^ (get_mode_extension !current_mode) in
       let mlloc_output = oprefix ^ ".mlloc.js" in
    
    charguer's avatar
    charguer committed
       (*---------------------------------------------------*)
       (* set flags *)
    
    
    charguer's avatar
    charguer committed
       if !current_mode <> Mode_cmi
          then Clflags.dont_write_files := true;
    
    
    charguer's avatar
    charguer committed
       (* TODO: does not work because we don't have easy access to the fully qualified path of constructors
       if !current_mode <> Mode_unlogged 
          then generate_qualified_names := true;
       *)
    
    
    charguer's avatar
    charguer committed
    
       (*---------------------------------------------------*)
       (* generation of the mlloc file that binds tokens to positions *)
    
       let generate_mlloc_file () =
          let outchannel = open_out mlloc_output in
    
    Thomas Wood's avatar
    Thomas Wood committed
          let put = output_endline outchannel in
    
    charguer's avatar
    charguer committed
          put "   lineof_temp = [];";
    
    charguer's avatar
    charguer committed
          Js_of_ast.(
             ~~ Hashtbl.iter token_locs (fun key (pos_start,pos_stop) ->
               put (Printf.sprintf "   lineof_temp[%d] = [%d,%d,%d,%d];" 
                      key pos_start.pos_line pos_start.pos_col  
                          pos_stop.pos_line  pos_stop.pos_col);
             ));
    
    Thomas Wood's avatar
    Thomas Wood committed
          put (Printf.sprintf "lineof_data[\"%s\"] = lineof_temp;" sourcebase);
    
    charguer's avatar
    charguer committed
          close_out outchannel;
    
    Thomas Wood's avatar
    Thomas Wood committed
          Printf.printf "Wrote %s\n" mlloc_output;
    
    charguer's avatar
    charguer committed
          in
    
    
    charguer's avatar
    gen
    charguer committed
       (*---------------------------------------------------*)
       (* "reading and typing source file" *)
    
    Thomas Wood's avatar
    Thomas Wood committed
       let (parsetree, (typedtree,_), module_name) = process_implementation_file ppf sourcefile oprefix in
       if !current_mode <> Mode_cmi then begin
         let out = Js_of_ast.to_javascript sourcebase module_name typedtree in
         file_put_contents output_filename out;
         if !current_mode = (Mode_unlogged TokenTrue) 
           then generate_mlloc_file()
       end;
       Printf.printf "Wrote %s\n" output_filename