Browse Source

Recursive callback running (#11049)

* [compiler] run callbacks until there's nothing left

* add test

---------

Co-authored-by: Simon Krajewski <[email protected]>
Rudy Ges 2 years ago
parent
commit
129ce0dad6

+ 3 - 3
src/compiler/compiler.ml

@@ -156,7 +156,7 @@ module Setup = struct
 		Buffer.truncate buffer (Buffer.length buffer - 1);
 		Common.log com (Buffer.contents buffer);
 		Typecore.type_expr_ref := (fun ?(mode=MGet) ctx e with_type -> Typer.type_expr ~mode ctx e with_type);
-		List.iter (fun f -> f ()) (List.rev com.callbacks#get_before_typer_create);
+		com.callbacks#run com.callbacks#get_before_typer_create;
 		(* Native lib pass 1: Register *)
 		let fl = List.map (fun (file,extern) -> NativeLibraryHandler.add_native_lib com file extern) (List.rev native_libs) in
 		(* Native lib pass 2: Initialize *)
@@ -253,7 +253,7 @@ let do_type ctx tctx actx =
 	List.iter (MacroContext.call_init_macro tctx) (List.rev actx.config_macros);
 	com.stage <- CInitMacrosDone;
 	CommonCache.lock_signature com "after_init_macros";
-	List.iter (fun f -> f ()) (List.rev com.callbacks#get_after_init_macros);
+	com.callbacks#run com.callbacks#get_after_init_macros;
 	run_or_diagnose ctx (fun () ->
 		if com.display.dms_kind <> DMNone then DisplayTexpr.check_display_file tctx cs;
 		List.iter (fun cpath -> ignore(tctx.Typecore.g.Typecore.do_load_module tctx cpath null_pos)) (List.rev actx.classes);
@@ -319,7 +319,7 @@ let compile ctx actx =
 		com.stage <- CGenerationDone;
 	end;
 	Sys.catch_break false;
-	List.iter (fun f -> f()) (List.rev com.callbacks#get_after_generation);
+	com.callbacks#run com.callbacks#get_after_generation;
 	if not actx.no_output then begin
 		List.iter (fun c ->
 			let r = run_command ctx c in

+ 21 - 12
src/context/common.ml

@@ -168,39 +168,48 @@ type platform_config = {
 }
 
 class compiler_callbacks = object(self)
-	val mutable before_typer_create = [];
-	val mutable after_init_macros = [];
+	val before_typer_create = ref [];
+	val after_init_macros = ref [];
 	val mutable after_typing = [];
-	val mutable before_save = [];
-	val mutable after_save = [];
-	val mutable after_filters = [];
-	val mutable after_generation = [];
+	val before_save = ref [];
+	val after_save = ref [];
+	val after_filters = ref [];
+	val after_generation = ref [];
 	val mutable null_safety_report = [];
 
 	method add_before_typer_create (f : unit -> unit) : unit =
-		before_typer_create <- f :: before_typer_create
+		before_typer_create := f :: !before_typer_create
 
 	method add_after_init_macros (f : unit -> unit) : unit =
-		after_init_macros <- f :: after_init_macros
+		after_init_macros := f :: !after_init_macros
 
 	method add_after_typing (f : module_type list -> unit) : unit =
 		after_typing <- f :: after_typing
 
 	method add_before_save (f : unit -> unit) : unit =
-		before_save <- f :: before_save
+		before_save := f :: !before_save
 
 	method add_after_save (f : unit -> unit) : unit =
-		after_save <- f :: after_save
+		after_save := f :: !after_save
 
 	method add_after_filters (f : unit -> unit) : unit =
-		after_filters <- f :: after_filters
+		after_filters := f :: !after_filters
 
 	method add_after_generation (f : unit -> unit) : unit =
-		after_generation <- f :: after_generation
+		after_generation := f :: !after_generation
 
 	method add_null_safety_report (f : (string*pos) list -> unit) : unit =
 		null_safety_report <- f :: null_safety_report
 
+	method run r =
+		match !r with
+		| [] ->
+			()
+		| l ->
+			r := [];
+			List.iter (fun f -> f()) (List.rev l);
+			self#run r
+
 	method get_before_typer_create = before_typer_create
 	method get_after_init_macros = after_init_macros
 	method get_after_typing = after_typing

+ 3 - 3
src/filters/filters.ml

@@ -766,7 +766,7 @@ let destruction tctx detail_times main locals =
 		List.iter (fun f -> f t) type_filters
 	) com.types;
 	t();
-	List.iter (fun f -> f()) (List.rev com.callbacks#get_after_filters);
+	com.callbacks#run com.callbacks#get_after_filters;
 	com.stage <- CFilteringDone
 
 let update_cache_dependencies com t =
@@ -1003,7 +1003,7 @@ let run com tctx main =
 	] in
 	List.iter (run_expression_filters (timer_label detail_times ["expr 2"]) tctx filters) new_types;
 	let t = filter_timer detail_times ["callbacks"] in
-	List.iter (fun f -> f()) (List.rev com.callbacks#get_before_save); (* macros onGenerate etc. *)
+	com.callbacks#run com.callbacks#get_before_save; (* macros onGenerate etc. *)
 	t();
 	com.stage <- CSaveStart;
 	let t = filter_timer detail_times ["save state"] in
@@ -1014,6 +1014,6 @@ let run com tctx main =
 	t();
 	com.stage <- CSaveDone;
 	let t = filter_timer detail_times ["callbacks"] in
-	List.iter (fun f -> f()) (List.rev com.callbacks#get_after_save); (* macros onGenerate etc. *)
+	com.callbacks#run com.callbacks#get_after_save; (* macros onGenerate etc. *)
 	t();
 	destruction tctx detail_times main locals

+ 30 - 0
tests/misc/projects/recursive-callbacks/Main.hx

@@ -0,0 +1,30 @@
+#if macro
+import haxe.macro.Context;
+
+function init() {
+	var here = (macro here).pos;
+
+	Context.onAfterInitMacros(() -> {
+		Context.warning("1", here);
+		Context.onAfterInitMacros(() -> {
+			Context.warning("2", here);
+		});
+	});
+
+	Context.onGenerate((_) -> {
+		Context.warning("3", here);
+		Context.onGenerate((_) -> {
+			Context.warning("4", here);
+		});
+	});
+
+	Context.onAfterGenerate(() -> {
+		Context.warning("5", here);
+		Context.onAfterGenerate(() -> {
+			Context.warning("6", here);
+		});
+	});
+}
+#end
+
+function main() {}

+ 2 - 0
tests/misc/projects/recursive-callbacks/compile.hxml

@@ -0,0 +1,2 @@
+--main Main
+--macro Main.init()

+ 7 - 0
tests/misc/projects/recursive-callbacks/compile.hxml.stderr

@@ -0,0 +1,7 @@
+Main.hx:5: characters 20-24 : Warning : 1
+Main.hx:9: lines 9-11 : Warning : This API should only be used from initialization macros.
+Main.hx:5: characters 20-24 : Warning : 2
+Main.hx:5: characters 20-24 : Warning : 3
+Main.hx:5: characters 20-24 : Warning : 4
+Main.hx:5: characters 20-24 : Warning : 5
+Main.hx:5: characters 20-24 : Warning : 6