diff --git a/jscomp/bin/ocaml_pack.ml b/jscomp/bin/ocaml_pack.ml index 35bca9a0bce..283136722e8 100644 --- a/jscomp/bin/ocaml_pack.ml +++ b/jscomp/bin/ocaml_pack.ml @@ -1,4 +1,4 @@ -(** Bundled by ocaml_pack 06/17-13:23 *) +(** Bundled by ocaml_pack 06/17-14:07 *) module Ext_bytes : sig #1 "ext_bytes.mli" (* Copyright (C) 2015-2016 Bloomberg Finance L.P. diff --git a/jscomp/ext/hash_set.mli b/jscomp/ext/hash_set.mli index d867503b3f2..56d1e586075 100644 --- a/jscomp/ext/hash_set.mli +++ b/jscomp/ext/hash_set.mli @@ -48,3 +48,5 @@ val mem : 'a hashset -> 'a -> bool val iter : ('a -> unit) -> 'a hashset -> unit val elements : 'a hashset -> 'a list + +val length : 'a hashset -> int diff --git a/jscomp/js_main.ml b/jscomp/js_main.ml index a1679f4f450..9c78905bf7e 100644 --- a/jscomp/js_main.ml +++ b/jscomp/js_main.ml @@ -46,6 +46,7 @@ let process_implementation_file ppf name = let opref = output_prefix name in Js_implementation.implementation ppf name opref + let process_file ppf name = if Filename.check_suffix name ".ml" || Filename.check_suffix name ".mlt" then begin @@ -71,6 +72,22 @@ let impl filename = let intf filename = readenv ppf Before_compile; process_interface_file ppf filename;; +let batch_files : Ast_extract.info Hash_set.hashset = Hash_set.create 31 + +let collect_file name = + if Filename.check_suffix name ".ml" + || Filename.check_suffix name ".mlt" then + Hash_set.add batch_files + { source_file = name ; + ast = Ml (Pparse.parse_implementation ~tool_name:"bsc" ppf name) } + else if Filename.check_suffix name !Config.interface_suffix then + begin + Hash_set.add batch_files + { source_file = name ; + ast = Mli (Pparse.parse_interface ~tool_name:"bsc" ppf name) } + end + + let show_config () = Config.print_config stdout; exit 0; @@ -310,10 +327,6 @@ let add_include_path s = Ext_pervasives.failwithf ~loc:__LOC__ "%s is not a directory" s -let batch_files = ref [] - -let collect_file file = - batch_files := file :: !batch_files let buckle_script_flags = ("-bs-npm-output-path", Arg.String Js_config.set_npm_package_path, @@ -441,7 +454,9 @@ let main () = try readenv ppf Before_args; Arg.parse buckle_script_flags anonymous usage; - List.iter (prerr_endline ) !batch_files; + ( if Hash_set.length batch_files > 0 then + let stck = Ast_extract.prepare batch_files in + Stack.iter (prerr_endline ) stck); exit 0 with x -> Location.report_exception ppf x; diff --git a/jscomp/syntax/ast_extract.ml b/jscomp/syntax/ast_extract.ml new file mode 100644 index 00000000000..03a12c4abb5 --- /dev/null +++ b/jscomp/syntax/ast_extract.ml @@ -0,0 +1,130 @@ +(* Copyright (C) 2015-2016 Bloomberg Finance L.P. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * In addition to the permissions granted to you by the LGPL, you may combine + * or link a "work that uses the Library" with a publicly distributed version + * of this file to produce a combined library or application, then distribute + * that combined work under the terms of your choosing, with no requirement + * to comply with the obligations normally placed on you by section 4 of the + * LGPL version 3 (or the corresponding section of a later version of the LGPL + * should you choose to use a later version). + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) + + +module C = Stack + + +let read_parse_and_extract ast extract_function = + Depend.free_structure_names := Depend.StringSet.empty; + (let bound_vars = Depend.StringSet.empty in + List.iter + (fun modname -> + Depend.open_module bound_vars (Longident.Lident modname)) + (!Clflags.open_modules); + extract_function bound_vars ast; + !Depend.free_structure_names) + + + + +type ast = + | Ml of Parsetree.structure + | Mli of Parsetree.signature + +type info = + { source_file : string ; + ast : ast + } + +let file_dependencies (files : (info * Depend.StringSet.t) list ref) + ({source_file; ast} as v) = + let extracted_deps = + read_parse_and_extract ast + ( match ast with + | Ml ast -> fun set _ -> Depend.add_implementation set ast + | Mli ast -> fun set _ -> Depend.add_signature set ast ) in + files := (v, extracted_deps) :: !files + + +let normalize file = + let modname = String.capitalize + (Filename.chop_extension @@ Filename.basename file) in + modname + +let merge (files : (info * Depend.StringSet.t) list ) : + (string, Depend.StringSet.t) Hashtbl.t + = + let tbl = Hashtbl.create 31 in + + let domain = + Depend.StringSet.of_list + (List.map (fun ({ source_file },_)-> normalize source_file) files) in + List.iter + (fun ({source_file = file; _}, deps) -> + let modname = String.capitalize + (Filename.chop_extension @@ Filename.basename file) in + match Hashtbl.find tbl modname with + | new_deps -> + Hashtbl.replace tbl modname + (Depend.StringSet.inter domain + (Depend.StringSet.union deps new_deps)) + | exception Not_found -> + Hashtbl.add tbl modname (Depend.StringSet.inter deps domain) + ) files ; + tbl + + +let sort_files_by_dependencies files + = + let h = merge files in + let worklist = Stack.create () in + let ()= + Hashtbl.iter (fun key _ -> Stack.push key worklist ) h in + let result = C.create () in + let visited = Hashtbl.create 31 in + + while not @@ Stack.is_empty worklist do + let current = Stack.top worklist in + if Hashtbl.mem visited current then + ignore @@ Stack.pop worklist + else + match Depend.StringSet.elements (Hashtbl.find h current) with + | depends -> + let really_depends = + List.filter + (fun x -> (Hashtbl.mem h x && (not (Hashtbl.mem visited x )))) + depends in + begin match really_depends with + |[] -> + begin + let v = Stack.pop worklist in + Hashtbl.add visited v () ; + C.push current result + end + | _ -> + List.iter (fun x -> Stack.push x worklist) really_depends + end + | exception Not_found -> assert false + done; + result +;; + + + +let prepare ast_table = + let files = ref [] in + Hash_set.iter (file_dependencies files) ast_table; + sort_files_by_dependencies (!files) + diff --git a/jscomp/syntax/ast_extract.mli b/jscomp/syntax/ast_extract.mli new file mode 100644 index 00000000000..78fc3991c3a --- /dev/null +++ b/jscomp/syntax/ast_extract.mli @@ -0,0 +1,39 @@ +(* Copyright (C) 2015-2016 Bloomberg Finance L.P. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * In addition to the permissions granted to you by the LGPL, you may combine + * or link a "work that uses the Library" with a publicly distributed version + * of this file to produce a combined library or application, then distribute + * that combined work under the terms of your choosing, with no requirement + * to comply with the obligations normally placed on you by section 4 of the + * LGPL version 3 (or the corresponding section of a later version of the LGPL + * should you choose to use a later version). + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) + + +type ast = + | Ml of Parsetree.structure + | Mli of Parsetree.signature + +type info = + { source_file : string ; + ast : ast + } + + + + + +val prepare : info Hash_set.hashset -> string Stack.t diff --git a/jscomp/syntax/syntax.mllib b/jscomp/syntax/syntax.mllib index 5d498273bd4..f43b0912efc 100644 --- a/jscomp/syntax/syntax.mllib +++ b/jscomp/syntax/syntax.mllib @@ -3,4 +3,5 @@ ast_payload ppx_entry ast_literal ast_comb -depend \ No newline at end of file +depend +ast_extract \ No newline at end of file