Browse Source

moved delayed macros from interp to macro type context (fixed issue with macro caching and macro in macro)

Nicolas Cannasse 12 năm trước cách đây
mục cha
commit
3053db8d64
3 tập tin đã thay đổi với 30 bổ sung23 xóa
  1. 2 8
      interp.ml
  2. 1 0
      typecore.ml
  3. 27 15
      typer.ml

+ 2 - 8
interp.ml

@@ -112,6 +112,7 @@ type extern_api = {
 	define_type : value -> unit;
 	module_dependency : string -> string -> bool -> unit;
 	current_module : unit -> module_def;
+	delayed_macro : int -> (unit -> (unit -> value));
 }
 
 type callstack = {
@@ -144,7 +145,6 @@ type context = {
 	mutable venv : value array;
 	(* context *)
 	mutable curapi : extern_api;
-	mutable delayed : (unit -> (unit -> value)) DynArray.t;
 	(* eval *)
 	mutable locals_map : (string, int) PMap.t;
 	mutable locals_count : int;
@@ -2513,7 +2513,7 @@ let rec eval ctx (e,p) =
 	| ECall ((EConst (Builtin "typewrap"),_),[t]) ->
 		(fun() -> VAbstract (ATDecl (Obj.magic t)))
 	| ECall ((EConst (Builtin "delay_call"),_),[EConst (Int index),_]) ->
-		let f = DynArray.get ctx.delayed index in
+		let f = ctx.curapi.delayed_macro index in
 		let fbuild = ref None in
 		let old = { ctx with gen = ctx.gen } in
 		let compile_delayed_call() =
@@ -3261,11 +3261,6 @@ let load_prim ctx f n =
 	| _ ->
 		exc (VString "Invalid call")
 
-let alloc_delayed ctx f =
-	let pos = DynArray.length ctx.delayed in
-	DynArray.add ctx.delayed f;
-	pos
-
 let create com api =
 	let loader = obj hash [
 		"args",VArray (Array.of_list (List.map (fun s -> VString s) com.args));
@@ -3300,7 +3295,6 @@ let create com api =
 		do_compare = Obj.magic();
 		(* context *)
 		curapi = api;
-		delayed = DynArray.create();
 		loader = VObject loader;
 		exports = VObject { ofields = [||]; oproto = None };
 	} in

+ 1 - 0
typecore.ml

@@ -62,6 +62,7 @@ type typer_globals = {
 	mutable hook_generate : (unit -> unit) list;
 	type_patches : (path, (string * bool, type_patch) Hashtbl.t * type_patch) Hashtbl.t;
 	mutable get_build_infos : unit -> (module_type * Ast.class_field list) option;
+	delayed_macros : (unit -> unit) DynArray.t;
 	(* api *)
 	do_inherit : typer -> Type.tclass -> Ast.pos -> Ast.class_flag -> bool;
 	do_create : Common.context -> typer;

+ 27 - 15
typer.ml

@@ -2854,6 +2854,10 @@ let generate ctx =
 (* ---------------------------------------------------------------------- *)
 (* MACROS *)
 
+let macro_enable_cache = ref false
+let macro_interp_cache = ref None
+let delayed_macro_result = ref ((fun() -> assert false) : unit -> unit -> Interp.value)
+
 let get_type_patch ctx t sub =
 	let new_patch() =
 		{ tp_type = None; tp_remove = false; tp_meta = [] }
@@ -3119,17 +3123,23 @@ let make_macro_api ctx p =
 		Interp.current_module = (fun() ->
 			ctx.m.curmod
 		);
+		Interp.delayed_macro = (fun i ->
+			let ctx2 = (match ctx.g.macros with None -> assert false | Some (_,ctx2) -> ctx2) in
+			let f = (try DynArray.get ctx2.g.delayed_macros i with _ -> failwith "Delayed macro retrieve failure") in
+			f();
+			let ret = !delayed_macro_result in
+			delayed_macro_result := (fun() -> assert false);
+			ret
+		);
 	}
 
-let macro_interp_cache = ref None
-
 let rec init_macro_interp ctx2 mctx =
 	let p = Ast.null_pos in
 	ignore(Typeload.load_module ctx2 (["haxe";"macro"],"Expr") p);
 	ignore(Typeload.load_module ctx2 (["haxe";"macro"],"Type") p);
-	if flush_macro_context mctx ctx2 != mctx then assert false;
+	flush_macro_context mctx ctx2;
 	Interp.init mctx;
-	if not (Common.defined ctx2.com Define.NoMacroCache) then macro_interp_cache := Some mctx
+	if !macro_enable_cache && not (Common.defined ctx2.com Define.NoMacroCache) then macro_interp_cache := Some mctx
 
 and flush_macro_context mctx ctx =
 	finalize ctx;
@@ -3149,8 +3159,7 @@ and flush_macro_context mctx ctx =
 	end else mctx in
 	(* we should maybe ensure that all filters in Main are applied. Not urgent atm *)
 	Interp.add_types mctx types (Codegen.post_process [Codegen.captured_vars ctx.com; Codegen.rename_local_vars ctx.com]);
-	Codegen.post_process_end();
-	mctx
+	Codegen.post_process_end()
 	
 let create_macro_interp ctx ctx2 =
 	let com2 = ctx2.com in
@@ -3224,13 +3233,12 @@ let load_macro ctx cpath f p =
 		| _ -> error "Macro should be called on a class" p
 	) in
 	let meth = (match follow meth.cf_type with TFun (args,ret) -> args,ret,cl,meth | _ -> error "Macro call should be a method" p) in
-	let in_macro = ctx.in_macro in
-	let mctx = if in_macro then mctx else flush_macro_context mctx ctx2 in
+	if not ctx.in_macro then flush_macro_context mctx ctx2;
 	t();
 	let call args =
 		let t = macro_timer ctx (s_type_path cpath ^ "." ^ f) in
 		incr stats.s_macros_called;
-		let r = Interp.call_path mctx ((fst cpath) @ [snd cpath]) f args api in
+		let r = Interp.call_path (Interp.get_ctx()) ((fst cpath) @ [snd cpath]) f args api in
 		t();
 		r
 	in
@@ -3365,12 +3373,15 @@ let type_macro ctx mode cpath f (el:Ast.expr list) p =
 		let ctx = {
 			ctx with locals = ctx.locals;
 		} in
-		let mctx = Interp.get_ctx() in
-		let pos = Interp.alloc_delayed mctx (fun() ->
-			match call() with
-			| None -> (fun() -> raise Interp.Abort)
-			| Some e -> Interp.eval mctx (Genneko.gen_expr mctx.Interp.gen (type_expr ctx e Value))
-		) in
+		let pos = DynArray.length ctx2.g.delayed_macros in
+		DynArray.add ctx2.g.delayed_macros (fun() ->
+			delayed_macro_result := (fun() ->
+				let mctx = Interp.get_ctx() in
+				match call() with
+				| None -> (fun() -> raise Interp.Abort)
+				| Some e -> Interp.eval mctx (Genneko.gen_expr mctx.Interp.gen (type_expr ctx e Value))
+			);
+		);
 		ctx.m.curmod.m_extra.m_time <- -1.; (* disable caching for modules having macro-in-macro *)
 		let e = (EConst (Ident "__dollar__delay_call"),p) in
 		Some (EUntyped (ECall (e,[EConst (Int (string_of_int pos)),p]),p),p)
@@ -3419,6 +3430,7 @@ let rec create com =
 			type_patches = Hashtbl.create 0;
 			delayed = [];
 			debug_delayed = [];
+			delayed_macros = DynArray.create();
 			doinline = not (Common.defined com Define.NoInline || com.display);
 			hook_generate = [];
 			get_build_infos = (fun() -> None);