Browse Source

add Context.onAfterGenerate to register macros that run after code generation

Simon Krajewski 11 years ago
parent
commit
7468828a00
6 changed files with 44 additions and 5 deletions
  1. 5 0
      common.ml
  2. 1 0
      doc/CHANGES.txt
  3. 11 0
      interp.ml
  4. 7 4
      main.ml
  5. 13 1
      std/haxe/macro/Context.hx
  6. 7 0
      typer.ml

+ 5 - 0
common.ml

@@ -126,6 +126,7 @@ type context = {
 	mutable warning : string -> pos -> unit;
 	mutable load_extern_type : (path -> pos -> (string * Ast.package) option) list; (* allow finding types which are not in sources *)
 	mutable filters : (unit -> unit) list;
+	mutable final_filters : (unit -> unit) list;
 	mutable defines_signature : string option;
 	mutable print : string -> unit;
 	mutable get_macros : unit -> context option;
@@ -641,6 +642,7 @@ let create v args =
 		file = "";
 		types = [];
 		filters = [];
+		final_filters = [];
 		modules = [];
 		main = None;
 		flash_version = 10.;
@@ -814,6 +816,9 @@ let platform ctx p = ctx.platform = p
 let add_filter ctx f =
 	ctx.filters <- f :: ctx.filters
 
+let add_final_filter ctx f =
+	ctx.final_filters <- f :: ctx.final_filters
+
 let find_file ctx f =
 	let rec loop = function
 		| [] -> raise Not_found

+ 1 - 0
doc/CHANGES.txt

@@ -27,6 +27,7 @@
 	js : always use JSON extern (compile with -D old-browser to disable)
 	cpp : improved side-effect detection
 	cs : added -net-lib
+	macro : add Context.onAfterGenerate
 	macro : allowed $v{(c:Float|Int|String)}
 	macro : resolve error line number in external files
 	macro : rewrote macros used as static extension

+ 11 - 0
interp.ml

@@ -100,6 +100,7 @@ type extern_api = {
 	get_type : string -> Type.t option;
 	get_module : string -> Type.t list;
 	on_generate : (Type.t list -> unit) -> unit;
+	after_generate : (unit -> unit) -> unit;
 	on_type_not_found : (string -> value) -> unit;
 	parse_string : string -> Ast.pos -> bool -> Ast.expr;
 	typeof : Ast.expr -> Type.t;
@@ -2139,6 +2140,16 @@ let macro_lib =
 				VNull
 			| _ -> error()
 		);
+		"after_generate", Fun1 (fun f ->
+			match f with
+			| VFunction (Fun0 _) ->
+				let ctx = get_ctx() in
+				ctx.curapi.after_generate (fun () ->
+					ignore(catch_errors ctx (fun() -> ctx.do_call VNull f [] null_pos));
+				);
+				VNull
+			| _ -> error()
+		);
 		"on_type_not_found", Fun1 (fun f ->
 			match f with
 			| VFunction (Fun1 _) ->

+ 7 - 4
main.ml

@@ -1422,10 +1422,13 @@ try
 		);
 	end;
 	Sys.catch_break false;
-	if not !no_output then List.iter (fun c ->
-		let r = run_command ctx c in
-		if r <> 0 then failwith ("Command failed with error " ^ string_of_int r)
-	) (List.rev !cmds)
+	if not !no_output then begin
+		List.iter (fun f -> f()) (List.rev com.final_filters);
+		List.iter (fun c ->
+			let r = run_command ctx c in
+			if r <> 0 then failwith ("Command failed with error " ^ string_of_int r)
+		) (List.rev !cmds)
+	end
 with
 	| Abort ->
 		()

+ 13 - 1
std/haxe/macro/Context.hx

@@ -260,7 +260,19 @@ class Context {
 	public static function onGenerate( callback : Array<Type> -> Void ) {
 		load("on_generate",1)(callback);
 	}
-
+	
+	/**
+		Adds a callback function `callback` which is invoked after the compiler
+		generation phase.
+		
+		Compilation has completed at this point and cannot be influenced
+		anymore. However, contextual information is still available.
+	**/
+	@:require(haxe_ver >= 3.01)
+	public static function onAfterGenerate( callback : Void -> Void ) {
+		load("after_generate",1)(callback);
+	}
+	
 	/**
 		Adds a callback function `callback` which is invoked when a type name
 		cannot be resolved.

+ 7 - 0
typer.ml

@@ -3608,6 +3608,13 @@ let make_macro_api ctx p =
 				t()
 			)
 		);
+		Interp.after_generate = (fun f ->
+			Common.add_final_filter ctx.com (fun() ->
+				let t = macro_timer ctx "afterGenerate" in
+				f();
+				t()
+			)
+		);
 		Interp.on_type_not_found = (fun f ->
 			ctx.com.load_extern_type <- ctx.com.load_extern_type @ [fun path p ->
 				match f (s_type_path path) with