diff --git a/Makefile.filelist b/Makefile.filelist index f1dee666ee..6917b53d44 100644 --- a/Makefile.filelist +++ b/Makefile.filelist @@ -58,6 +58,7 @@ OTHERS := runtime/runtime.js runtime/weak.js \ runtime/dynlink.js \ runtime/graphics.js \ runtime/nat.js \ + runtime/predefined_exceptions.js COMP_INTF := compiler/compiler.cmi COMP_IMPL := compiler/compiler.cma diff --git a/compiler/.depend b/compiler/.depend index 6738bf39e6..800fb58281 100644 --- a/compiler/.depend +++ b/compiler/.depend @@ -1,51 +1,47 @@ annot_lexer.cmo : annot_parser.cmi annot_lexer.cmi annot_lexer.cmx : annot_parser.cmx annot_lexer.cmi -annot_parser.cmo : primitive.cmi annot_parser.cmi -annot_parser.cmx : primitive.cmx annot_parser.cmi +annot_parser.cmo : jsoo_primitive.cmi annot_parser.cmi +annot_parser.cmx : jsoo_primitive.cmx annot_parser.cmi code.cmo : varPrinter.cmi util.cmi code.cmi code.cmx : varPrinter.cmx util.cmx code.cmi commonArg.cmo : util.cmi option.cmi commonArg.cmi commonArg.cmx : util.cmx option.cmx commonArg.cmi -compile.cmo : util.cmi pseudoFs.cmi pretty_print.cmi parse_bytecode.cmi \ - option.cmi linker.cmi driver.cmi compileArg.cmi commonArg.cmi code.cmi -compile.cmx : util.cmx pseudoFs.cmx pretty_print.cmx parse_bytecode.cmx \ - option.cmx linker.cmx driver.cmx compileArg.cmx commonArg.cmx code.cmx compileArg.cmo : util.cmi source_map.cmi option.cmi driver.cmi \ compiler_version.cmi commonArg.cmi compileArg.cmi compileArg.cmx : util.cmx source_map.cmx option.cmx driver.cmx \ compiler_version.cmx commonArg.cmx compileArg.cmi compiler_version.cmo : compiler_version.cmi compiler_version.cmx : compiler_version.cmi -control.cmo : subst.cmi code.cmi control.cmi -control.cmx : subst.cmx code.cmx control.cmi -deadcode.cmo : util.cmi pure_fun.cmi option.cmi code.cmi deadcode.cmi -deadcode.cmx : util.cmx pure_fun.cmx option.cmx code.cmx deadcode.cmi +control.cmo : code.cmi control.cmi +control.cmx : code.cmx control.cmi dgraph.cmo : dgraph.cmi dgraph.cmx : dgraph.cmi driver.cmo : varPrinter.cmi util.cmi tailcall.cmi specialize_js.cmi \ - specialize.cmi reserved.cmi primitive.cmi pretty_print.cmi phisimpl.cmi \ - parse_bytecode.cmi option.cmi linker.cmi js_traverse.cmi js_output.cmi \ - js_assign.cmi javascript.cmi inline.cmi generate.cmi flow.cmi eval.cmi \ - deadcode.cmi compiler_version.cmi code.cmi driver.cmi + specialize.cmi reserved.cmi pretty_print.cmi phisimpl.cmi \ + parse_bytecode.cmi option.cmi linker.cmi jsoo_primitive.cmi \ + jsoo_deadcode.cmi js_traverse.cmi js_output.cmi js_assign.cmi \ + javascript.cmi inline.cmi generate.cmi flow.cmi eval.cmi \ + compiler_version.cmi code.cmi driver.cmi driver.cmx : varPrinter.cmx util.cmx tailcall.cmx specialize_js.cmx \ - specialize.cmx reserved.cmx primitive.cmx pretty_print.cmx phisimpl.cmx \ - parse_bytecode.cmx option.cmx linker.cmx js_traverse.cmx js_output.cmx \ - js_assign.cmx javascript.cmx inline.cmx generate.cmx flow.cmx eval.cmx \ - deadcode.cmx compiler_version.cmx code.cmx driver.cmi -eval.cmo : primitive.cmi flow.cmi code.cmi eval.cmi -eval.cmx : primitive.cmx flow.cmx code.cmx eval.cmi -flow.cmo : util.cmi subst.cmi primitive.cmi option.cmi dgraph.cmi code.cmi \ - flow.cmi -flow.cmx : util.cmx subst.cmx primitive.cmx option.cmx dgraph.cmx code.cmx \ - flow.cmi + specialize.cmx reserved.cmx pretty_print.cmx phisimpl.cmx \ + parse_bytecode.cmx option.cmx linker.cmx jsoo_primitive.cmx \ + jsoo_deadcode.cmx js_traverse.cmx js_output.cmx js_assign.cmx \ + javascript.cmx inline.cmx generate.cmx flow.cmx eval.cmx \ + compiler_version.cmx code.cmx driver.cmi +eval.cmo : jsoo_primitive.cmi flow.cmi code.cmi eval.cmi +eval.cmx : jsoo_primitive.cmx flow.cmx code.cmx eval.cmi +flow.cmo : util.cmi option.cmi jsoo_subst.cmi jsoo_primitive.cmi dgraph.cmi \ + code.cmi flow.cmi +flow.cmx : util.cmx option.cmx jsoo_subst.cmx jsoo_primitive.cmx dgraph.cmx \ + code.cmx flow.cmi freevars.cmo : util.cmi option.cmi code.cmi freevars.cmi freevars.cmx : util.cmx option.cmx code.cmx freevars.cmi -generate.cmo : util.cmi subst.cmi primitive.cmi parse_js.cmi parse_info.cmi \ - parse_bytecode.cmi option.cmi js_tailcall.cmi js_simpl.cmi javascript.cmi \ - freevars.cmi code.cmi generate.cmi -generate.cmx : util.cmx subst.cmx primitive.cmx parse_js.cmx parse_info.cmx \ - parse_bytecode.cmx option.cmx js_tailcall.cmx js_simpl.cmx javascript.cmx \ - freevars.cmx code.cmx generate.cmi +generate.cmo : util.cmi parse_js.cmi parse_info.cmi parse_bytecode.cmi \ + option.cmi jsoo_subst.cmi jsoo_primitive.cmi js_tailcall.cmi js_simpl.cmi \ + javascript.cmi freevars.cmi code.cmi generate.cmi +generate.cmx : util.cmx parse_js.cmx parse_info.cmx parse_bytecode.cmx \ + option.cmx jsoo_subst.cmx jsoo_primitive.cmx js_tailcall.cmx js_simpl.cmx \ + javascript.cmx freevars.cmx code.cmx generate.cmi inline.cmo : util.cmi option.cmi code.cmi inline.cmi inline.cmx : util.cmx option.cmx code.cmx inline.cmi instr.cmo : util.cmi instr.cmi @@ -76,12 +72,24 @@ js_traverse.cmo : util.cmi javascript.cmi code.cmi js_traverse.cmi js_traverse.cmx : util.cmx javascript.cmx code.cmx js_traverse.cmi json.cmo : pretty_print.cmi javascript.cmi json.cmi json.cmx : pretty_print.cmx javascript.cmx json.cmi -linker.cmo : util.cmi reserved.cmi primitive.cmi parse_js.cmi parse_info.cmi \ - option.cmi js_traverse.cmi js_token.cmi javascript.cmi annot_parser.cmi \ - annot_lexer.cmi linker.cmi -linker.cmx : util.cmx reserved.cmx primitive.cmx parse_js.cmx parse_info.cmx \ - option.cmx js_traverse.cmx js_token.cmx javascript.cmx annot_parser.cmx \ - annot_lexer.cmx linker.cmi +jsoo_compile.cmo : util.cmi pseudoFs.cmi pretty_print.cmi parse_bytecode.cmi \ + option.cmi linker.cmi driver.cmi compileArg.cmi commonArg.cmi code.cmi +jsoo_compile.cmx : util.cmx pseudoFs.cmx pretty_print.cmx parse_bytecode.cmx \ + option.cmx linker.cmx driver.cmx compileArg.cmx commonArg.cmx code.cmx +jsoo_deadcode.cmo : util.cmi pure_fun.cmi option.cmi code.cmi \ + jsoo_deadcode.cmi +jsoo_deadcode.cmx : util.cmx pure_fun.cmx option.cmx code.cmx \ + jsoo_deadcode.cmi +jsoo_primitive.cmo : util.cmi parse_info.cmi jsoo_primitive.cmi +jsoo_primitive.cmx : util.cmx parse_info.cmx jsoo_primitive.cmi +jsoo_subst.cmo : util.cmi code.cmi jsoo_subst.cmi +jsoo_subst.cmx : util.cmx code.cmx jsoo_subst.cmi +linker.cmo : util.cmi reserved.cmi parse_js.cmi parse_info.cmi option.cmi \ + jsoo_primitive.cmi js_traverse.cmi js_token.cmi javascript.cmi \ + annot_parser.cmi annot_lexer.cmi linker.cmi +linker.cmx : util.cmx reserved.cmx parse_js.cmx parse_info.cmx option.cmx \ + jsoo_primitive.cmx js_traverse.cmx js_token.cmx javascript.cmx \ + annot_parser.cmx annot_lexer.cmx linker.cmi minify.cmo : util.cmi pretty_print.cmi parse_js.cmi parse_info.cmi \ option.cmi minifyArg.cmi js_traverse.cmi js_output.cmi js_assign.cmi \ commonArg.cmi code.cmi @@ -96,9 +104,9 @@ myfindlib.cmo : myfindlib.cmx : option.cmo : util.cmi option.cmi option.cmx : util.cmx option.cmi -parse_bytecode.cmo : util.cmi primitive.cmi parse_info.cmi option.cmi \ +parse_bytecode.cmo : util.cmi parse_info.cmi option.cmi jsoo_primitive.cmi \ instr.cmi code.cmi parse_bytecode.cmi -parse_bytecode.cmx : util.cmx primitive.cmx parse_info.cmx option.cmx \ +parse_bytecode.cmx : util.cmx parse_info.cmx option.cmx jsoo_primitive.cmx \ instr.cmx code.cmx parse_bytecode.cmi parse_info.cmo : parse_info.cmi parse_info.cmx : parse_info.cmi @@ -106,32 +114,28 @@ parse_js.cmo : parse_info.cmi js_token.cmi js_parser.cmi js_lexer.cmi \ parse_js.cmi parse_js.cmx : parse_info.cmx js_token.cmx js_parser.cmx js_lexer.cmx \ parse_js.cmi -phisimpl.cmo : util.cmi subst.cmi option.cmi dgraph.cmi code.cmi \ +phisimpl.cmo : util.cmi option.cmi jsoo_subst.cmi dgraph.cmi code.cmi \ phisimpl.cmi -phisimpl.cmx : util.cmx subst.cmx option.cmx dgraph.cmx code.cmx \ +phisimpl.cmx : util.cmx option.cmx jsoo_subst.cmx dgraph.cmx code.cmx \ phisimpl.cmi pretty_print.cmo : pretty_print.cmi pretty_print.cmx : pretty_print.cmi -primitive.cmo : util.cmi parse_info.cmi primitive.cmi -primitive.cmx : util.cmx parse_info.cmx primitive.cmi pseudoFs.cmo : util.cmi code.cmi pseudoFs.cmi pseudoFs.cmx : util.cmx code.cmx pseudoFs.cmi -pure_fun.cmo : primitive.cmi code.cmi pure_fun.cmi -pure_fun.cmx : primitive.cmx code.cmx pure_fun.cmi +pure_fun.cmo : jsoo_primitive.cmi code.cmi pure_fun.cmi +pure_fun.cmx : jsoo_primitive.cmx code.cmx pure_fun.cmi reserved.cmo : util.cmi reserved.cmi reserved.cmx : util.cmx reserved.cmi source_map.cmo : vlq64.cmi source_map.cmi source_map.cmx : vlq64.cmx source_map.cmi specialize.cmo : util.cmi option.cmi flow.cmi code.cmi specialize.cmi specialize.cmx : util.cmx option.cmx flow.cmx code.cmx specialize.cmi -specialize_js.cmo : util.cmi primitive.cmi flow.cmi code.cmi \ +specialize_js.cmo : util.cmi jsoo_primitive.cmi flow.cmi code.cmi \ specialize_js.cmi -specialize_js.cmx : util.cmx primitive.cmx flow.cmx code.cmx \ +specialize_js.cmx : util.cmx jsoo_primitive.cmx flow.cmx code.cmx \ specialize_js.cmi -subst.cmo : util.cmi code.cmi subst.cmi -subst.cmx : util.cmx code.cmx subst.cmi -tailcall.cmo : util.cmi subst.cmi option.cmi code.cmi tailcall.cmi -tailcall.cmx : util.cmx subst.cmx option.cmx code.cmx tailcall.cmi +tailcall.cmo : util.cmi option.cmi jsoo_subst.cmi code.cmi tailcall.cmi +tailcall.cmx : util.cmx option.cmx jsoo_subst.cmx code.cmx tailcall.cmi util.cmo : myfindlib.cmo util.cmi util.cmx : myfindlib.cmx util.cmi varPrinter.cmo : util.cmi reserved.cmi varPrinter.cmi @@ -139,13 +143,12 @@ varPrinter.cmx : util.cmx reserved.cmx varPrinter.cmi vlq64.cmo : vlq64.cmi vlq64.cmx : vlq64.cmi annot_lexer.cmi : annot_parser.cmi -annot_parser.cmi : primitive.cmi +annot_parser.cmi : jsoo_primitive.cmi code.cmi : util.cmi commonArg.cmi : compileArg.cmi : source_map.cmi driver.cmi commonArg.cmi compiler_version.cmi : control.cmi : code.cmi -deadcode.cmi : code.cmi dgraph.cmi : driver.cmi : source_map.cmi pretty_print.cmi parse_bytecode.cmi code.cmi eval.cmi : flow.cmi code.cmi @@ -164,7 +167,10 @@ js_tailcall.cmi : js_traverse.cmi javascript.cmi code.cmi js_token.cmi : parse_info.cmi js_traverse.cmi : util.cmi javascript.cmi code.cmi json.cmi : pretty_print.cmi -linker.cmi : util.cmi primitive.cmi parse_info.cmi javascript.cmi +jsoo_deadcode.cmi : code.cmi +jsoo_primitive.cmi : util.cmi parse_info.cmi +jsoo_subst.cmi : code.cmi +linker.cmi : util.cmi parse_info.cmi jsoo_primitive.cmi javascript.cmi minifyArg.cmi : commonArg.cmi option.cmi : parse_bytecode.cmi : util.cmi parse_info.cmi code.cmi @@ -172,14 +178,12 @@ parse_info.cmi : parse_js.cmi : parse_info.cmi js_token.cmi javascript.cmi phisimpl.cmi : code.cmi pretty_print.cmi : -primitive.cmi : util.cmi parse_info.cmi pseudoFs.cmi : util.cmi code.cmi pure_fun.cmi : code.cmi reserved.cmi : util.cmi source_map.cmi : json.cmi specialize.cmi : flow.cmi code.cmi specialize_js.cmi : flow.cmi code.cmi -subst.cmi : code.cmi tailcall.cmi : code.cmi util.cmi : varPrinter.cmi : util.cmi diff --git a/compiler/Makefile b/compiler/Makefile index 9de0aec018..c96dd0b8ce 100644 --- a/compiler/Makefile +++ b/compiler/Makefile @@ -19,18 +19,18 @@ OBJS=compiler_version.cmx myfindlib.cmx \ util.cmx pretty_print.cmx option.cmx reserved.cmx varPrinter.cmx \ dgraph.cmx code.cmx javascript.cmx json.cmx vlq64.cmx source_map.cmx \ js_output.cmx js_simpl.cmx parse_info.cmx js_token.cmx js_parser.cmx \ - js_lexer.cmx parse_js.cmx primitive.cmx annot_parser.cmx annot_lexer.cmx \ - instr.cmx subst.cmx pure_fun.cmx deadcode.cmx \ + js_lexer.cmx parse_js.cmx jsoo_primitive.cmx annot_parser.cmx annot_lexer.cmx \ + instr.cmx jsoo_subst.cmx pure_fun.cmx jsoo_deadcode.cmx \ flow.cmx specialize.cmx specialize_js.cmx eval.cmx inline.cmx \ tailcall.cmx freevars.cmx phisimpl.cmx \ js_traverse.cmx js_assign.cmx js_tailcall.cmx \ linker.cmx parse_bytecode.cmx generate.cmx driver.cmx \ pseudoFs.cmx -COMPOBJS=$(OBJS) commonArg.cmx compileArg.cmx compile.cmx +COMPOBJS=$(OBJS) commonArg.cmx compileArg.cmx jsoo_compile.cmx OCAMLC=ocamlfind ocamlc -w +A-4-7-9-37-38-41-44-45 OCAMLOPT=ocamlfind ocamlopt -w +A-4-7-9-37-38-41-44-45 -$(COMPILER): compile.$(BEST) +$(COMPILER): jsoo_compile.$(BEST) mv -f $< $@ $(MINIFIER): minify.$(BEST) @@ -45,11 +45,11 @@ man/$(COMPILER).1: $(COMPILER) mkdir -p man ./$(COMPILER) --help=groff >$@ -.INTERMEDIATE: compile.byte compile.opt minify.byte minify.opt +.INTERMEDIATE: jsoo_compile.byte jsoo_compile.opt minify.byte minify.opt -compile.byte: $(COMPOBJS:cmx=cmo) +jsoo_compile.byte: $(COMPOBJS:cmx=cmo) $(OCAMLC) $(SAFESTRING) ${addprefix -package , $(PACKAGES)} -linkpkg -o $@ $^ -compile.opt: $(COMPOBJS) +jsoo_compile.opt: $(COMPOBJS) $(OCAMLOPT) $(SAFESTRING) ${addprefix -package , $(PACKAGES)} -linkpkg -g -o $@ $^ minify.byte: $(OBJS:cmx=cmo) commonArg.cmo minifyArg.cmo minify.cmo @@ -84,16 +84,16 @@ compiler_version.ml.tmp: echo "let git_version = \"${VERSION_GIT}\"" >> $@ %.cmx: %.ml - $(OCAMLOPT) $(SAFESTRING) ${addprefix -package , $(PACKAGES)} -for-pack Compiler -g -c $< + $(OCAMLOPT) -I +compiler-libs $(SAFESTRING) ${addprefix -package , $(PACKAGES)} -for-pack Compiler -g -c $< %.cmo: %.ml - $(OCAMLC) $(SAFESTRING) ${addprefix -package , $(PACKAGES)} -c $< + $(OCAMLC) -I +compiler-libs $(SAFESTRING) ${addprefix -package , $(PACKAGES)} -c $< %.cmi: %.mli - $(OCAMLC) $(SAFESTRING) ${addprefix -package , $(PACKAGES)} -c $< + $(OCAMLC) -I +compiler-libs $(SAFESTRING) ${addprefix -package , $(PACKAGES)} -c $< annot_parser.ml: annot_parser.mli -annot_parser.mli: annot_parser.mly primitive.cmi +annot_parser.mli: annot_parser.mly jsoo_primitive.cmi menhir --infer --explain $< js_parser.ml: js_parser.mli @@ -105,7 +105,7 @@ js_parser.mli: js_parser.mly javascript.cmi js_token.cmi clean: rm -f *.cm[aiox] *.cmxa *.cmxs *.o *.a *.conflicts rm -f lib/*.cm[aiox] lib/*.cmxa lib/*.cmxs lib/*.o lib/*.a - rm -f compile.opt compile.byte minify.opt minify.byte + rm -f *.opt *.byte rm -f $(MINIFIER) $(COMPILER) rm -f compiler_version.ml rm -f annot_lexer.ml annot_parser.ml annot_parser.mli diff --git a/compiler/annot_parser.mly b/compiler/annot_parser.mly index adc03bb8fa..ed2c036b2c 100644 --- a/compiler/annot_parser.mly +++ b/compiler/annot_parser.mly @@ -26,7 +26,7 @@ %token TOTHER %start annot -%type annot +%type annot %% diff --git a/compiler/driver.ml b/compiler/driver.ml index 16b8aed84b..53b2494ce4 100644 --- a/compiler/driver.ml +++ b/compiler/driver.ml @@ -21,6 +21,7 @@ let debug = Option.Debug.find "main" let times = Option.Debug.find "times" +module Primitive = Jsoo_primitive open Util let tailcall p = @@ -29,7 +30,7 @@ let tailcall p = let deadcode' p = if debug () then Format.eprintf "Dead-code...@."; - Deadcode.f p + Jsoo_deadcode.f p let deadcode p = let r,_ = deadcode' p @@ -340,7 +341,7 @@ let output formatter ?source_map js = Js_output.program formatter ?source_map js; if times () then Format.eprintf " write: %a@." Util.Timer.print t -let pack ~standalone ?(toplevel=false) js = +let pack ~wrap_with_fun ?(toplevel=false) js = let module J = Javascript in let t = Util.Timer.make () in if times () @@ -379,7 +380,7 @@ let pack ~standalone ?(toplevel=false) js = ], J.N), [], J.N) in let js = - if standalone then + if not wrap_with_fun then let f = J.EFun (None, [J.S {J.name = global_object; var=None }], use_strict js, J.U) in @@ -423,7 +424,7 @@ let configure formatter p = type profile = Code.program -> Code.program -let f ?(standalone=true) ?(profile=o1) ?toplevel ?linkall ?source_map formatter d = +let f ?(standalone=true) ?(wrap_with_fun=false) ?(profile=o1) ?toplevel ?linkall ?source_map formatter d = configure formatter >> profile >> deadcode' >> @@ -431,7 +432,7 @@ let f ?(standalone=true) ?(profile=o1) ?toplevel ?linkall ?source_map formatter link ~standalone ?linkall >> - pack ~standalone ?toplevel >> + pack ~wrap_with_fun ?toplevel >> coloring >> @@ -441,7 +442,7 @@ let f ?(standalone=true) ?(profile=o1) ?toplevel ?linkall ?source_map formatter let from_string prims s formatter = let (p,d) = Parse_bytecode.from_string prims s in - f ~standalone:false formatter d p + f ~standalone:false ~wrap_with_fun:true formatter d p let profiles = [1,o1; diff --git a/compiler/driver.mli b/compiler/driver.mli index 4730c7b6cf..3c957a66d0 100644 --- a/compiler/driver.mli +++ b/compiler/driver.mli @@ -22,6 +22,7 @@ type profile val f : ?standalone:bool -> + ?wrap_with_fun:bool -> ?profile:profile -> ?toplevel:bool -> ?linkall:bool -> diff --git a/compiler/eval.ml b/compiler/eval.ml index a9779519b3..9225b96751 100644 --- a/compiler/eval.ml +++ b/compiler/eval.ml @@ -17,6 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) +module Primitive = Jsoo_primitive open Code open Flow diff --git a/compiler/flow.ml b/compiler/flow.ml index 61ca64644d..3332c70430 100644 --- a/compiler/flow.ml +++ b/compiler/flow.ml @@ -21,6 +21,8 @@ let debug = Option.Debug.find "flow" let times = Option.Debug.find "times" +module Subst = Jsoo_subst +module Primitive = Jsoo_primitive open Code (****) diff --git a/compiler/generate.ml b/compiler/generate.ml index 04257edc2c..77530ece28 100644 --- a/compiler/generate.ml +++ b/compiler/generate.ml @@ -38,7 +38,8 @@ let times = Option.Debug.find "times" open Code open Util - +module Primitive = Jsoo_primitive +module Subst = Jsoo_subst module J = Javascript (****) @@ -896,24 +897,6 @@ let _ = let varset_disjoint s s' = not (VarSet.exists (fun x -> VarSet.mem x s') s) -let is_ident = - let l = Array.init 256 (fun i -> - let c = Char.chr i in - if (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c = '_' || c = '$' - then 1 - else if (c >= '0' && c <='9') - then 2 - else 0 - ) in - fun s -> - try - for i = 0 to String.length s - 1 do - let code = l.(Char.code(s.[i])) in - if i = 0 then assert (code = 1) else assert (code >= 1) - done; - true - with _ -> false - let rec group_closures_rec closures req = match closures with [] -> @@ -1017,8 +1000,8 @@ and translate_expr ctx queue loc _x e level : _ * J.statement_list = let ((py, cy), queue) = access_queue' ~ctx queue y in (J.EAccess (cx, J.EBin (J.Plus, cy, one)), or_p mutable_p (or_p px py), queue) - | Extern "caml_js_var", [Pc (String nm)] - | Extern ("caml_js_expr"|"caml_pure_js_expr"), [Pc (String nm)] -> + | Extern "caml_js_var", [Pc (String nm | IString nm)] + | Extern ("caml_js_expr"|"caml_pure_js_expr"), [Pc (String nm | IString nm)] -> begin try let lex = Parse_js.lexer_from_string nm in @@ -1050,7 +1033,7 @@ and translate_expr ctx queue loc _x e level : _ * J.statement_list = l ([], mutator_p, queue) in (J.ECall (cf, args, loc), or_p pf prop, queue) - | Extern "%caml_js_opt_meth_call", Pv o :: Pc (String m) :: l -> + | Extern "%caml_js_opt_meth_call", Pv o :: Pc (String m | IString m) :: l -> let ((po, co), queue) = access_queue queue o in let (args, prop, queue) = List.fold_right @@ -1072,18 +1055,18 @@ and translate_expr ctx queue loc _x e level : _ * J.statement_list = in (J.ENew (cc, if args = [] then None else Some args), or_p pc prop, queue) - | Extern "caml_js_get", [Pv o; Pc (String f)] -> + | Extern "caml_js_get", [Pv o; Pc (String f | IString f)] -> let ((po, co), queue) = access_queue queue o in (J.EDot (co, f), or_p po mutable_p, queue) - | Extern "caml_js_set", [Pv o; Pc (String f); v] -> + | Extern "caml_js_set", [Pv o; Pc (String f | IString f); v] -> let ((po, co), queue) = access_queue queue o in let ((pv, cv), queue) = access_queue' ~ctx queue v in (J.EBin (J.Eq, J.EDot (co, f), cv), or_p (or_p po pv) mutator_p, queue) - | Extern "caml_js_delete", [Pv o; Pc (String f)] -> + | Extern "caml_js_delete", [Pv o; Pc (String f | IString f)] -> let ((po, co), queue) = access_queue queue o in (J.EUn(J.Delete, J.EDot (co, f)), or_p po mutator_p, queue) - | Extern "%overrideMod", [Pc (String m);Pc (String f)] -> + | Extern "%overrideMod", [Pc (String m | IString m);Pc (String f | IString f)] -> s_var (Printf.sprintf "caml_%s_%s" m f), const_p,queue | Extern "%overrideMod", _ -> assert false @@ -1092,7 +1075,7 @@ and translate_expr ctx queue loc _x e level : _ * J.statement_list = match l with [] -> (const_p, [], queue) - | Pc (String nm) :: x :: r -> + | Pc (String nm | IString nm) :: x :: r -> let ((prop, cx), queue) = access_queue' ~ctx queue x in let (prop', r', queue) = build_fields queue r in (or_p prop prop', (J.PNS nm, cx) :: r', queue) @@ -1122,7 +1105,7 @@ and translate_expr ctx queue loc _x e level : _ * J.statement_list = | Some f -> f l queue ctx loc | None -> if name.[0] = '%' - then failwith (Printf.sprintf "Unresolved interal primitive: %s" name); + then failwith (Printf.sprintf "Unresolved internal primitive: %s" name); let prim = Share.get_prim s_var name ctx.Ctx.share in let prim_kind = kind (Primitive.kind name) in let (args, prop, queue) = diff --git a/compiler/compile.ml b/compiler/jsoo_compile.ml similarity index 83% rename from compiler/compile.ml rename to compiler/jsoo_compile.ml index ef3919829a..7d73cbe7ce 100644 --- a/compiler/compile.ml +++ b/compiler/jsoo_compile.ml @@ -75,15 +75,15 @@ let f { if source_map <> None || Option.Optim.debuginfo () then `Full else if Option.Optim.pretty () then `Names else `No in - let p, cmis, d = + let p, cmis, d, standalone = match input_file with None -> Parse_bytecode.from_channel ~includes:paths ~toplevel ~debug:need_debug stdin | Some f -> let ch = open_in_bin f in - let p,cmis,d = Parse_bytecode.from_channel ~includes:paths ~toplevel ~debug:need_debug ch in + let res = Parse_bytecode.from_channel ~includes:paths ~toplevel ~debug:need_debug ch in close_in ch; - p, cmis, d + res in let () = if source_map <> None && Parse_bytecode.Debug.is_empty d @@ -107,7 +107,7 @@ let f { | None -> let p = PseudoFs.f p cmis fs_files paths in let fmt = Pretty_print.to_out_channel stdout in - Driver.f ?profile ~toplevel ~linkall ?source_map fmt d p + Driver.f ~standalone ?profile ~toplevel ~linkall ?source_map fmt d p | Some file -> gen_file file (fun chan -> let p = @@ -115,13 +115,13 @@ let f { then PseudoFs.f p cmis fs_files paths else p in let fmt = Pretty_print.to_out_channel chan in - Driver.f ?profile ~toplevel ~linkall ?source_map fmt d p; + Driver.f ~standalone ?profile ~toplevel ~linkall ?source_map fmt d p; ); Util.opt_iter (fun file -> gen_file file (fun chan -> let pfs = PseudoFs.f_empty cmis fs_files paths in let pfs_fmt = Pretty_print.to_out_channel chan in - Driver.f ?profile pfs_fmt d pfs + Driver.f ~standalone ?profile pfs_fmt d pfs ) ) fs_output end; @@ -144,21 +144,21 @@ let _ = prerr_string backtrace; exit 1 | Util.MagicNumber.Bad_magic_number s -> - Format.eprintf "%s: Error: Not an ocaml executable bytecode@." Sys.argv.(0); - Format.eprintf "%s: Error: Invalid magic number %S, expecting %S@." Sys.argv.(0) s Util.MagicNumber.(to_string current); + Format.eprintf "%s: Error: Not an ocaml bytecode file@." Sys.argv.(0); + Format.eprintf "%s: Error: Invalid magic number %S@." Sys.argv.(0) s; exit 1 | Util.MagicNumber.Bad_magic_version h -> - Format.eprintf "%s: Error: Bytecode version missmatch. Got version %S, expecting %S.@." - Sys.argv.(0) - Util.MagicNumber.(to_string h) - Util.MagicNumber.(to_string current); + Format.eprintf "%s: Error: Bytecode version missmatch.@." Sys.argv.(0); + let k = match Util.MagicNumber.kind h with + | (`Cmo | `Cma | `Exe as x) -> x + | `Other _ -> assert false in let comp = - if Util.MagicNumber.(compare h current) < 0 + if Util.MagicNumber.compare h (Util.MagicNumber.current k) < 0 then "an older" else "a newer" in - Format.eprintf "%s: Error: Your program and the js_of_ocaml compiler have to be compiled with the same version of ocaml.@." Sys.argv.(0); + Format.eprintf "%s: Error: Your ocaml bytecode and the js_of_ocaml compiler have to be compiled with the same version of ocaml.@." Sys.argv.(0); Format.eprintf "%s: Error: The Js_of_ocaml compiler has been compiled with ocaml version %s.@." Sys.argv.(0) Sys.ocaml_version; - Format.eprintf "%s: Error: Its seems that your program has been compiled with %s version of ocaml.@." Sys.argv.(0) comp; + Format.eprintf "%s: Error: Its seems that your ocaml bytecode has been compiled with %s version of ocaml.@." Sys.argv.(0) comp; exit 1 | Failure s -> Format.eprintf "%s: Error: %s@." Sys.argv.(0) s; diff --git a/compiler/deadcode.ml b/compiler/jsoo_deadcode.ml similarity index 100% rename from compiler/deadcode.ml rename to compiler/jsoo_deadcode.ml diff --git a/compiler/deadcode.mli b/compiler/jsoo_deadcode.mli similarity index 100% rename from compiler/deadcode.mli rename to compiler/jsoo_deadcode.mli diff --git a/compiler/primitive.ml b/compiler/jsoo_primitive.ml similarity index 100% rename from compiler/primitive.ml rename to compiler/jsoo_primitive.ml diff --git a/compiler/primitive.mli b/compiler/jsoo_primitive.mli similarity index 100% rename from compiler/primitive.mli rename to compiler/jsoo_primitive.mli diff --git a/compiler/subst.ml b/compiler/jsoo_subst.ml similarity index 100% rename from compiler/subst.ml rename to compiler/jsoo_subst.ml diff --git a/compiler/subst.mli b/compiler/jsoo_subst.mli similarity index 100% rename from compiler/subst.mli rename to compiler/jsoo_subst.mli diff --git a/compiler/linker.ml b/compiler/linker.ml index a702c2097d..11885427ae 100644 --- a/compiler/linker.ml +++ b/compiler/linker.ml @@ -20,12 +20,13 @@ open Util +module Primitive = Jsoo_primitive let loc pi = match pi with | Some {Parse_info.src = Some src; line} | Some {Parse_info.name = Some src; line} -> Printf.sprintf "%s:%d" src line - | None + | None | Some _ -> "unknown location" let parse_annot loc s = @@ -101,7 +102,7 @@ let parse_file f = let name = match pi with | {Parse_info.src = Some x; _} | {Parse_info.name = Some x; _} -> x - | _ -> "??" in + | _ -> "??" in error "cannot parse file %S (orig:%S from l:%d, c:%d)@." f name pi.Parse_info.line pi.Parse_info.col) lexs in diff --git a/compiler/linker.mli b/compiler/linker.mli index 35cccd248a..6e5bcbbdce 100644 --- a/compiler/linker.mli +++ b/compiler/linker.mli @@ -19,7 +19,7 @@ *) val parse_file : string -> - ((Parse_info.t option * string * Primitive.kind * Primitive.kind_arg list option) option * (* provide *) + ((Parse_info.t option * string * Jsoo_primitive.kind * Jsoo_primitive.kind_arg list option) option * (* provide *) string list * (* require *) ((int -> int -> bool) * string) list list * (* version constraint *) Javascript.program) list diff --git a/compiler/parse_bytecode.ml b/compiler/parse_bytecode.ml index 84d934a4b0..77ec8445ab 100644 --- a/compiler/parse_bytecode.ml +++ b/compiler/parse_bytecode.ml @@ -20,19 +20,20 @@ open Code open Instr - +module Primitive = Jsoo_primitive let debug_parser = Option.Debug.find "parser" type code = string (* Copied from ocaml/typing/ident.ml *) -module Ident = struct - type t = { stamp: int; name: string; mutable flags: int } +module IdentTable = struct + type 'a tbl = - | Empty + Empty | Node of 'a tbl * 'a data * 'a tbl * int + and 'a data = - { ident: t; + { ident: Ident.t; data: 'a; previous: 'a data option } @@ -42,11 +43,11 @@ module Ident = struct rem | Node (l, v, r, _) -> table_contents_rec sz l - ((sz - v.data, v.ident.name) :: table_contents_rec sz r rem) + ((sz - v.data, v.ident.Ident.name) :: table_contents_rec sz r rem) let table_contents sz t = List.sort (fun (i, _) (j, _) -> compare i j) - (table_contents_rec sz t []) + (table_contents_rec sz (Obj.magic (t : 'a Ident.tbl) : 'a tbl) []) end (* Copied from ocaml/utils/tbl.ml *) module Tbl = struct @@ -74,6 +75,20 @@ module Tbl = struct fold f r (f v d (fold f l accu)) end +let predefined_exceptions = + [ 0, "Out_of_memory" + ; 1, "Sys_error" + ; 2, "Failure" + ; 3, "Invalid_argument" + ; 4, "End_of_file" + ; 5, "Division_by_zero" + ; 6, "Not_found" + ; 7, "Match_failure" + ; 8, "Stack_overflow" + ; 9, "Sys_blocked_io" + ; 10,"Assert_failure" + ; 11,"Undefined_recursive_module" ] + (* Copied from ocaml/bytecomp/symtable.ml *) type 'a numtable = { num_cnt: int; @@ -81,55 +96,6 @@ type 'a numtable = (* Read and manipulate debug section *) module Debug : sig - - (* instruct.ml *) - type compilation_env = - { ce_stack: int Ident.tbl; (* Positions of variables in the stack *) - ce_heap: int Ident.tbl; (* Structure of the heap-allocated env *) - ce_rec: int Ident.tbl } (* Functions bound by the same let rec *) - - (* lexing.ml *) - type position = - { pos_fname: string; - pos_lnum: int; - pos_bol: int; - pos_cnum: int } - - (* location.ml *) - type location = - { loc_start: position; - loc_end: position; - loc_ghost: bool } - - (* instruct.ml *) - type debug_event = - { mutable ev_pos: int; (* Position in bytecode *) - ev_module: string; (* Name of defining module *) - ev_loc: location; (* Location in source file *) - ev_kind: debug_event_kind; (* Before/after event *) - ev_info: debug_event_info; (* Extra information *) - ev_typenv: unit; (* Typing environment *) - ev_typsubst: unit; (* Substitution over types *) - ev_compenv: compilation_env; (* Compilation environment *) - ev_stacksize: int; (* Size of stack frame *) - ev_repr: debug_event_repr } (* Position of the representative *) - - and debug_event_kind = - Event_before - | Event_after of unit - | Event_pseudo - - and debug_event_info = - | Event_function - | Event_return of int - | Event_other - - and debug_event_repr = - | Event_none - | Event_parent of int ref - | Event_child of int ref - - type data val is_empty : data -> bool val propagate : Code.Var.t list -> Code.Var.t list -> unit @@ -139,53 +105,10 @@ module Debug : sig val paths : data -> string list val read : crcs:(string * string option) list -> includes:string list -> in_channel -> data val no_data : unit -> data - val fold : data -> (Code.addr -> debug_event -> 'a -> 'a) -> 'a -> 'a + val fold : data -> (Code.addr -> Instruct.debug_event -> 'a -> 'a) -> 'a -> 'a end = struct - type compilation_env = - { ce_stack: int Ident.tbl; (* Positions of variables in the stack *) - ce_heap: int Ident.tbl; (* Structure of the heap-allocated env *) - ce_rec: int Ident.tbl } (* Functions bound by the same let rec *) - - type position = - { pos_fname: string; - pos_lnum: int; - pos_bol: int; - pos_cnum: int } - - type location = - { loc_start: position; - loc_end: position; - loc_ghost: bool } - - type debug_event = - { mutable ev_pos: int; (* Position in bytecode *) - ev_module: string; (* Name of defining module *) - ev_loc: location; (* Location in source file *) - ev_kind: debug_event_kind; (* Before/after event *) - ev_info: debug_event_info; (* Extra information *) - ev_typenv: unit; (* Typing environment *) - ev_typsubst: unit; (* Substitution over types *) - ev_compenv: compilation_env; (* Compilation environment *) - ev_stacksize: int; (* Size of stack frame *) - ev_repr: debug_event_repr } (* Position of the representative *) - - and debug_event_kind = - | Event_before - | Event_after of unit - | Event_pseudo - - and debug_event_info = - | Event_function - | Event_return of int - | Event_other - - and debug_event_repr = - | Event_none - | Event_parent of int ref - | Event_child of int ref - - + open Instruct type ml_unit = { name : string; crc : string option; @@ -264,7 +187,7 @@ end = struct let find (events_by_pc,_) pc = try let ev = Hashtbl.find events_by_pc pc in - Ident.table_contents ev.ev_stacksize ev.ev_compenv.ce_stack + IdentTable.table_contents ev.ev_stacksize ev.ev_compenv.ce_stack with Not_found -> [] @@ -280,27 +203,29 @@ end = struct Hashtbl.find events_by_pc (pc + 3) in let loc = ev.ev_loc in - if loc.loc_ghost then None else + if loc.Location.loc_ghost then None else let pos = - if after then loc.loc_end else - if before then loc.loc_start else - match ev.ev_kind with Event_after _ -> loc.loc_end | _ -> loc.loc_start in + if after then loc.Location.loc_end else + if before then loc.Location.loc_start else + match ev.ev_kind with + | Event_after _ -> loc.Location.loc_end + | _ -> loc.Location.loc_start in let src = - let uname = Filename.(basename (chop_extension pos.pos_fname)) in + let uname = Filename.(basename (chop_extension pos.Lexing.pos_fname)) in try let unit = Hashtbl.find units uname in try Some (Util.absolute_path - (Util.find_in_path unit.paths pos.pos_fname)) with + (Util.find_in_path unit.paths pos.Lexing.pos_fname)) with | Not_found -> match unit.source with | Some x -> Some (Util.absolute_path x) | None -> raise Not_found - with Not_found -> None (* Some (pos.pos_fname) *) + with Not_found -> None (* Some (pos.Lexing.pos_fname) *) in - Some {Parse_info.name = Some pos.pos_fname; + Some {Parse_info.name = Some pos.Lexing.pos_fname; src; - line=pos.pos_lnum - 1; - col=pos.pos_cnum - pos.pos_bol; + line=pos.Lexing.pos_lnum - 1; + col=pos.Lexing.pos_cnum - pos.Lexing.pos_bol; (* loc.li_end.pos_cnum - loc.li_end.pos_bol *) idx=0; fol=None} @@ -454,6 +379,7 @@ type globals = { mutable vars : Var.t option array; mutable is_const : bool array; mutable is_exported : bool array; + mutable named_value : string option array; mutable override : (Var.t -> Code.instr list -> (Var.t * Code.instr list)) option array; constants : Obj.t array; primitives : string array } @@ -462,6 +388,7 @@ let make_globals size constants primitives = { vars = Array.make size None; is_const = Array.make size false; is_exported = Array.make size false; + named_value = Array.make size None; override = Array.make size None; constants = constants; primitives = primitives } @@ -474,9 +401,9 @@ let resize_globals g size = g.vars <- resize_array g.vars size None; g.is_const <- resize_array g.is_const size false; g.is_exported <- resize_array g.is_exported size true; + g.named_value <- resize_array g.named_value size None; g.override <- resize_array g.override size None - (* State of the VM *) module State = struct @@ -657,10 +584,15 @@ let access_global g i = let register_global ?(force=false) g i rem = if force || g.is_exported.(i) then + let args = + match g.named_value.(i) with + | None -> [] + | Some name -> [Pc (IString name)] in Let (Var.fresh (), Prim (Extern "caml_register_global", - [Pc (Int (Int32.of_int i)) ; - Pv (access_global g i)])) :: rem + (Pc (Int (Int32.of_int i)) :: + Pv (access_global g i) :: + args))) :: rem else rem let get_global state instrs i = @@ -723,7 +655,18 @@ let rec compile_block blocks debug code pc state = and compile infos pc state instrs = if debug_parser () then State.print state; if pc = infos.limit then - (instrs, Branch (pc, State.stack_vars state), state) + begin + (* stop if we reach end_of_code (ie when compiling cmo) *) + if pc = String.length infos.code / 4 + then begin + if debug_parser () then Format.eprintf "Stop@."; + (instrs, Stop, state) + end + else begin + if debug_parser () then Format.eprintf "Branch %d@." pc; + (instrs, Branch (pc, State.stack_vars state), state) + end + end else begin if debug_parser () then Format.eprintf "%4d " pc; @@ -1776,7 +1719,6 @@ let parse_bytecode ?(debug=`No) code globals debug_data = then Debug.fold debug_data (fun pc _ blocks -> Blocks.add blocks pc) blocks else blocks in compile_block blocks debug_data code 0 state; - let blocks = AddrMap.mapi (fun _ (state, instr, last) -> @@ -1869,8 +1811,6 @@ let read_toc ic = let pos_trailer = in_channel_length ic - 16 in seek_in ic pos_trailer; let num_sections = input_binary_int ic in - let header = really_input_string ic Util.MagicNumber.size in - Util.MagicNumber.assert_current header; seek_in ic (pos_trailer - 8 * num_sections); let section_table = ref [] in for _i = 1 to num_sections do @@ -1880,7 +1820,7 @@ let read_toc ic = done; !section_table -let from_channel ?(includes=[]) ?(toplevel=false) ?(debug=`No) ic = +let exe_from_channel ?(includes=[]) ?(toplevel=false) ?(debug=`No) ic = let toc = read_toc ic in @@ -1949,17 +1889,16 @@ let from_channel ?(includes=[]) ?(toplevel=false) ?(debug=`No) ic = let p = parse_bytecode ~debug code globals debug_data in (* register predefined exception *) - let body = ref [] in - for i = 0 to 11 do (* see ocaml/byterun/fail.h *) - body := register_global ~force:true globals i !body; + let body = List.fold_left (fun body (i,_name) -> + let body = register_global ~force:true globals i body in globals.is_exported.(i) <- false; - done; + body) [] predefined_exceptions in let body = Util.array_fold_right_i (fun i _ l -> match globals.vars.(i) with Some x when globals.is_const.(i) -> let l = register_global globals i l in Let (x, Constant (Constants.parse globals.constants.(i))) :: l - | _ -> l) globals.constants !body in + | _ -> l) globals.constants body in let body = @@ -1991,7 +1930,7 @@ let from_channel ?(includes=[]) ?(toplevel=false) ?(debug=`No) ic = if toplevel && Option.Optim.include_cmis () then Tbl.fold (fun id _num acc -> if id.Ident.flags = 1 - then Util.StringSet.add id.Ident.name acc + then Util.StringSet.add id.Ident.name acc else acc) symbols.num_tbl Util.StringSet.empty else Util.StringSet.empty in prepend p body, cmis, debug_data @@ -2013,3 +1952,184 @@ let from_bytes primitives (code : code) = let from_string primitives (code : string) = from_bytes primitives code + +module Reloc = struct + + let gen_patch_int buff pos n = + Bytes.set buff (pos + 0) (Char.unsafe_chr n); + Bytes.set buff (pos + 1) (Char.unsafe_chr (n asr 8)); + Bytes.set buff (pos + 2) (Char.unsafe_chr (n asr 16)); + Bytes.set buff (pos + 3) (Char.unsafe_chr (n asr 24)) + + type t = { + mutable pos : int; + mutable constants : Obj.t list; + names : (string, int) Hashtbl.t; + primitives : (string, int) Hashtbl.t; + } + + let create () = + let constants = [] in + { pos = List.length constants; + constants; + names = Hashtbl.create 17; + primitives = Hashtbl.create 17 + } + + let step1 t compunit code = + let open Cmo_format in + List.iter (fun name -> Hashtbl.add t.primitives name (Hashtbl.length t.primitives)) compunit.cu_primitives; + let slot_for_literal sc = + t.constants <- Util.obj_of_const sc :: t.constants; + let pos = t.pos in + t.pos <- succ t.pos; + pos in + let num_of_prim name = + try Hashtbl.find t.primitives name with + | Not_found -> + let i = Hashtbl.length t.primitives in + Hashtbl.add t.primitives name i; + i in + List.iter (function + | (Reloc_literal sc, pos) -> + gen_patch_int code pos (slot_for_literal sc) + | (Reloc_primitive name, pos) -> + gen_patch_int code pos (num_of_prim name) + | _ -> ()) compunit.cu_reloc + + let step2 t compunit code = + let open Cmo_format in + let next { Ident.name; _} = + try Hashtbl.find t.names name with + | Not_found -> + let x = t.pos in + t.pos <- succ t.pos; + Hashtbl.add t.names name x; + x in + let slot_for_getglobal id = next id in + let slot_for_setglobal id = next id in + + List.iter (function + | (Reloc_getglobal id, pos) -> + gen_patch_int code pos (slot_for_getglobal id) + | (Reloc_setglobal id, pos) -> + gen_patch_int code pos (slot_for_setglobal id) + | _ -> ()) compunit.cu_reloc + + let primitives t = + let l = Hashtbl.length t.primitives in + let a = Array.make l "" in + Hashtbl.iter (fun name i -> a.(i) <- name) t.primitives; + a + + let constants t = Array.of_list (List.rev t.constants) + + let make_globals t = + let primitives = primitives t in + let constants = constants t in + let globals = make_globals (Array.length constants) constants primitives in + resize_globals globals t.pos; + Hashtbl.iter (fun name i -> + globals.named_value.(i) <- Some name; + ) t.names; + (* Initialize module override mechanism *) + List.iter (fun (name, v) -> + try + let i = Hashtbl.find t.names name in + globals.override.(i) <- Some v; + if debug_parser () then Format.eprintf "overriding global %s@." name + with Not_found -> () + ) override_global; + globals + + +end + +let from_compilation_units ~includes:_ ~debug:_ l = + let reloc = Reloc.create () in + List.iter (fun (compunit, code) -> Reloc.step1 reloc compunit code) l; + List.iter (fun (compunit, code) -> Reloc.step2 reloc compunit code) l; + let globals = Reloc.make_globals reloc in + begin match Util.Version.v with + | `V3 -> + (* We fix the bytecode to replace max_int/min_int *) + List.iter (fun (u,code) -> + if u.Cmo_format.cu_name = "Pervasives" then begin + fix_min_max_int code + end) l + | `V4_02 -> () + end; + let code = + let l = List.map (fun (_,c) -> Bytes.to_string c) l in + String.concat "" l in + let debug_data = Debug.no_data () in + let prog = parse_bytecode code globals debug_data in + let gdata = Var.fresh () in + let body = Util.array_fold_right_i (fun i var l -> + match var with + | Some x when globals.is_const.(i) -> + begin match globals.named_value.(i) with + | None -> + let l = register_global globals i l in + Let (x, Constant (Constants.parse globals.constants.(i))) :: l + | Some name -> + Let (x, Prim (Extern "caml_js_get",[Pv gdata; Pc (IString name)])) :: l + end + | _ -> l) globals.vars [] in + let body = Let (gdata, Prim (Extern "caml_get_global_data", [])) :: body in + prepend prog body,Util.StringSet.empty, debug_data + +let from_channel ?(includes=[]) ?(toplevel=false) ?(debug=`No) ic = + let format = + try + let header = really_input_string ic Util.MagicNumber.size in + `Pre (Util.MagicNumber.of_string header) + with _ -> + let pos_magic = in_channel_length ic - 12 in + seek_in ic pos_magic; + let header = really_input_string ic Util.MagicNumber.size in + `Post (Util.MagicNumber.of_string header) + in + match format with + | `Pre magic -> + begin match Util.MagicNumber.kind magic with + | `Cmo -> + if magic <> Util.MagicNumber.current_cmo + then raise Util.MagicNumber.(Bad_magic_version magic); + let compunit_pos = input_binary_int ic in + seek_in ic compunit_pos; + let compunit = (input_value ic : Cmo_format.compilation_unit) in + seek_in ic compunit.Cmo_format.cu_pos; + let code = Bytes.create compunit.Cmo_format.cu_codesize in + really_input ic code 0 compunit.Cmo_format.cu_codesize; + close_in ic; + let a,b,c = from_compilation_units ~includes ~debug [compunit, code] in + a,b,c,false + | `Cma -> + if magic <> Util.MagicNumber.current_cma + then raise Util.MagicNumber.(Bad_magic_version magic); + let pos_toc = input_binary_int ic in (* Go to table of contents *) + seek_in ic pos_toc; + let lib = (input_value ic : Cmo_format.library) in + let units = List.map (fun compunit -> + seek_in ic compunit.Cmo_format.cu_pos; + let code = Bytes.create compunit.Cmo_format.cu_codesize in + really_input ic code 0 compunit.Cmo_format.cu_codesize; + compunit, code) + lib.Cmo_format.lib_units in + close_in ic; + let a,b,c = from_compilation_units ~includes ~debug units in + a,b,c,false + | _ -> + raise Util.MagicNumber.(Bad_magic_number (to_string magic)) + end + | `Post magic -> + begin match Util.MagicNumber.kind magic with + | `Exe -> + if magic <> Util.MagicNumber.current_exe + then raise Util.MagicNumber.(Bad_magic_version magic); + let a,b,c = exe_from_channel ~includes ~toplevel ~debug ic in + a,b,c,true + | _ -> + raise Util.MagicNumber.(Bad_magic_number (to_string magic)) + end diff --git a/compiler/parse_bytecode.mli b/compiler/parse_bytecode.mli index 11a2fde4be..329f88bf1a 100644 --- a/compiler/parse_bytecode.mli +++ b/compiler/parse_bytecode.mli @@ -29,6 +29,6 @@ end val from_channel : ?includes: string list -> ?toplevel:bool -> ?debug:[`Full | `Names | `No] -> in_channel -> - Code.program * Util.StringSet.t * Debug.data + Code.program * Util.StringSet.t * Debug.data * bool val from_string : string array -> string -> Code.program * Debug.data diff --git a/compiler/phisimpl.ml b/compiler/phisimpl.ml index c02645fac1..6cb80e2e31 100644 --- a/compiler/phisimpl.ml +++ b/compiler/phisimpl.ml @@ -20,6 +20,7 @@ let times = Option.Debug.find "times" +module Subst = Jsoo_subst open Code (****) diff --git a/compiler/pure_fun.ml b/compiler/pure_fun.ml index 201c660d33..bc90c09dc3 100644 --- a/compiler/pure_fun.ml +++ b/compiler/pure_fun.ml @@ -19,7 +19,7 @@ *) open Code - +module Primitive = Jsoo_primitive (****) let pure_expr pure_funs e = diff --git a/compiler/specialize_js.ml b/compiler/specialize_js.ml index eee7660fd3..58a4fb5c8e 100644 --- a/compiler/specialize_js.ml +++ b/compiler/specialize_js.ml @@ -21,6 +21,7 @@ open Code open Flow +module Primitive = Jsoo_primitive let specialize_instr info i rem = match i with diff --git a/compiler/tailcall.ml b/compiler/tailcall.ml index fcc3f54885..ceb36f69be 100644 --- a/compiler/tailcall.ml +++ b/compiler/tailcall.ml @@ -19,7 +19,7 @@ *) let times = Option.Debug.find "times" - +module Subst = Jsoo_subst open Code (* FIX: it should be possible to deal with tail-recursion in exception diff --git a/compiler/util.ml b/compiler/util.cppo.ml similarity index 86% rename from compiler/util.ml rename to compiler/util.cppo.ml index 2909fbc370..b2fb9db510 100644 --- a/compiler/util.ml +++ b/compiler/util.cppo.ml @@ -271,7 +271,7 @@ module MagicNumber = struct let size = 12 - let _kind_of_string = function + let kind_of_string = function | "Caml1999X" -> "exe" | "Caml1999I" -> "cmi" | "Caml1999O" -> "cmo" @@ -290,29 +290,46 @@ module MagicNumber = struct then raise Not_found; let kind = String.sub s 0 9 in let v = String.sub s 9 3 in + let _ = kind_of_string kind in kind, int_of_string v with _ -> raise (Bad_magic_number s) + let kind (s,_) = + match kind_of_string s with + | "exe" -> `Exe + | "cmo" -> `Cmo + | "cma" -> `Cma + | other -> `Other other + let to_string (k,v) = Printf.sprintf "%s%03d" k v let compare (p1,n1) (p2,n2) = if p1 <> p2 then raise Not_found; compare n1 n2 - let current = + let current_exe = let v = match Version.v with | `V3 -> 8 | `V4_02 -> 11 in ("Caml1999X",v) - let assert_current h': unit = - let (t',v') as h = of_string h' in - let t,v = current in - if t <> t' - then raise_ (Bad_magic_number h') - else if v <> v' - then raise_ (Bad_magic_version h) - else () + let current_cmo = + let v = match Version.v with + | `V3 -> 7 + | `V4_02 -> 10 in + ("Caml1999O", v) + + let current_cma = + let v = match Version.v with + | `V3 -> 8 + | `V4_02 -> 11 in + ("Caml1999A", v) + + let current = function + | `Exe -> current_exe + | `Cmo -> current_cmo + | `Cma -> current_cma + end @@ -334,3 +351,31 @@ let normalize_argv ?(warn_=false) a = warn "[Warning] long options with a single '-' are now deprecated.\ Please use '--' for the following options: %s@." (String.concat ", " !bad); a + +let rec obj_of_const = + let open Lambda in + let open Asttypes in + function + | Const_base (Const_int i) -> Obj.repr i + | Const_base (Const_char c) -> Obj.repr c +#if OCAML_VERSION < (4,02,0) + | Const_base (Const_string s) -> Obj.repr s +#else + | Const_base (Const_string (s,_)) -> Obj.repr s +#endif + | Const_base (Const_float s) -> Obj.repr (float_of_string s) + | Const_base (Const_int32 i) -> Obj.repr i + | Const_base (Const_int64 i) -> Obj.repr i + | Const_base (Const_nativeint i) -> Obj.repr i + | Const_immstring s -> Obj.repr s + | Const_float_array sl -> + let l = List.map float_of_string sl in + Obj.repr (Array.of_list l) + | Const_pointer i -> + Obj.repr i + | Const_block (tag,l) -> + let b = Obj.new_block tag (List.length l) in + List.iteri (fun i x -> + Obj.set_field b i (obj_of_const x) + ) l; + b diff --git a/compiler/util.mli b/compiler/util.mli index 512f08be68..b12123adfd 100644 --- a/compiler/util.mli +++ b/compiler/util.mli @@ -83,6 +83,11 @@ module MagicNumber : sig val compare : t -> t -> int val of_string : string -> t val to_string : t -> string - val current : t - val assert_current : string -> unit + val kind : t -> [ `Cmo | `Cma | `Exe | `Other of string] + val current_exe : t + val current_cmo : t + val current_cma : t + val current : [ `Cmo | `Cma | `Exe ] -> t end + +val obj_of_const : Lambda.structured_constant -> Obj.t diff --git a/runtime/fs.js b/runtime/fs.js index c325e1fe4d..d654d18db3 100644 --- a/runtime/fs.js +++ b/runtime/fs.js @@ -22,11 +22,6 @@ //Provides: caml_current_dir var caml_current_dir = "/"; -//Provides: caml_root_dir -//Requires: MlDir -var caml_root_dir = new MlDir(); -caml_root_dir.mk("",new MlDir()); - //Provides: MlDir function MlDir(){ this.content={};} MlDir.prototype = { @@ -49,7 +44,10 @@ MlFile.prototype = { truncate:function(){ this.data = caml_create_string(0) } } - +//Provides: caml_root_dir +//Requires: MlDir +var caml_root_dir = new MlDir(); +caml_root_dir.mk("",new MlDir()); //Provides: caml_sys_getcwd //Requires: caml_current_dir, caml_new_string diff --git a/runtime/predefined_exceptions.js b/runtime/predefined_exceptions.js new file mode 100644 index 0000000000..88021dcbba --- /dev/null +++ b/runtime/predefined_exceptions.js @@ -0,0 +1,21 @@ +//Requires: caml_global_data, caml_new_string +var predefined_exceptions = + [ {index:0, name:"Out_of_memory"}, + {index:1, name:"Sys_error"}, + {index:2, name:"Failure"}, + {index:3, name:"Invalid_argument"}, + {index:4, name:"End_of_file"}, + {index:5, name:"Division_by_zero"}, + {index:6, name:"Not_found"}, + {index:7, name:"Match_failure"}, + {index:8, name:"Stack_overflow"}, + {index:9, name:"Sys_blocked_io"}, + {index:10,name:"Assert_failure"}, + {index:11,name:"Undefined_recursive_module"}] + +for(var i = 0; i < predefined_exceptions.length; i++){ + var info = predefined_exceptions[i]; + var exn = [248, caml_new_string(info.name), - info.index]; + caml_global_data[info.index + 1] = exn; + caml_global_data[info.name] = exn; +} diff --git a/runtime/stdlib.js b/runtime/stdlib.js index 0d38852f72..d2e4e93369 100644 --- a/runtime/stdlib.js +++ b/runtime/stdlib.js @@ -93,7 +93,10 @@ var caml_global_data = [0]; //Provides: caml_register_global(const,shallow) //Requires: caml_global_data -function caml_register_global (n, v) { caml_global_data[n + 1] = v; } +function caml_register_global (n, v, name_opt) { + caml_global_data[n + 1] = v; + if(name_opt) caml_global_data[name_opt] = v; +} //Provides: caml_get_global_data mutable //Requires: caml_global_data