Bläddra i källkod

added Context.registerModuleDependency

Nicolas Cannasse 13 år sedan
förälder
incheckning
1ad775a0e7
4 ändrade filer med 44 tillägg och 4 borttagningar
  1. 8 0
      interp.ml
  2. 5 2
      main.ml
  3. 9 0
      std/haxe/macro/Context.hx
  4. 22 2
      typer.ml

+ 8 - 0
interp.ml

@@ -100,6 +100,7 @@ type extern_api = {
 	get_local_type : unit -> t option;
 	get_build_fields : unit -> value;
 	define_type : value -> unit;
+	module_dependency : string -> string -> unit;
 }
 
 type callstack = {
@@ -1956,6 +1957,13 @@ let macro_lib =
 			| _ ->
 				error()
 		);
+		"module_dependency", Fun2 (fun m file ->
+			match m, file with
+			| VString m, VString file ->
+				(get_ctx()).curapi.module_dependency m file;
+				VNull
+			| _ -> error()
+		);
 	]
 
 (* ---------------------------------------------------------------------- *)

+ 5 - 2
main.ml

@@ -410,6 +410,9 @@ and wait_loop boot_com host port =
 			| _ -> ()
 		) m.Type.m_types
 	in
+	let is_fake_module m =
+		fst m.Type.m_path = ["$DEP"]
+	in
 	let modules_added = Hashtbl.create 0 in
 	Typeload.type_module_hook := (fun (ctx:Typecore.typer) mpath p ->
 		let com2 = ctx.Typecore.com in
@@ -427,7 +430,7 @@ and wait_loop boot_com host port =
 			Hashtbl.add modules_checked m.Type.m_path ok;
 			try
 				let time, m = Hashtbl.find cache.c_modules (m.Type.m_path,sign) in
-				if m.Type.m_file <> Common.get_full_path (Typeload.resolve_module_file com2 m.Type.m_path (ref[]) p) then raise Not_found;
+				if not (is_fake_module m) && m.Type.m_file <> Common.get_full_path (Typeload.resolve_module_file com2 m.Type.m_path (ref[]) p) then raise Not_found;
 				if file_time m.Type.m_file <> time then raise Not_found;
 				PMap.iter (fun m2 _ -> if not (check m2) then begin dep := Some m2; raise Not_found end) !(m.Type.m_deps);
 				true
@@ -478,7 +481,7 @@ and wait_loop boot_com host port =
 		let rec cache_context com =
 			if not com.dead_code_elimination then begin
 				List.iter (cache_module (get_signature com)) com.modules;
-				if verbose then print_endline ("Cached " ^ string_of_int (List.length com.modules) ^ " modules");				
+				if verbose then print_endline ("Cached " ^ string_of_int (List.length com.modules) ^ " modules");
 			end;
 			match com.get_macros() with
 			| None -> ()

+ 9 - 0
std/haxe/macro/Context.hx

@@ -191,6 +191,15 @@ class Context {
 		load("define_type", 1)(t);
 	}
 
+
+	/**
+		Manually add a dependency between a module and a third party file :
+		make sure the module gets recompiled (if it was cached) in case the extern file has been modified as well.
+	**/
+	public static function registerModuleDependency( modulePath : String, externFile : String ) {
+		load("module_dependency", 2)(untyped modulePath.__s,untyped externFile.__s);
+	}
+
 	static function load( f, nargs ) : Dynamic {
 		#if macro
 		return neko.Lib.load("macro", f, nargs);

+ 22 - 2
typer.ml

@@ -2158,7 +2158,7 @@ let generate ctx =
 		) c.cl_statics
 
 	in
-	let sorted_modules = List.sort (fun m1 m2 -> compare m1.m_path m2.m_path) (Hashtbl.fold (fun _ m acc -> m :: acc) ctx.g.modules []) in	
+	let sorted_modules = List.sort (fun m1 m2 -> compare m1.m_path m2.m_path) (Hashtbl.fold (fun _ m acc -> m :: acc) ctx.g.modules []) in
 	List.iter (fun m -> List.iter loop m.m_types) sorted_modules;
 	get_main ctx, List.rev !types, sorted_modules
 
@@ -2235,6 +2235,8 @@ let typing_timer ctx f =
 			t();
 			raise e
 
+let fake_modules = Hashtbl.create 0
+
 let make_macro_api ctx p =
 	let make_instance = function
 		| TClassDecl c -> TInst (c,List.map snd c.cl_types)
@@ -2256,7 +2258,7 @@ let make_macro_api ctx p =
 		Interp.get_module = (fun s ->
 			typing_timer ctx (fun() ->
 				let path = parse_path s in
-				List.map make_instance (Typeload.load_module ctx path p).m_types
+				Typeload.load_module ctx path p
 			)
 		);
 		Interp.on_generate = (fun f ->
@@ -2373,6 +2375,24 @@ let make_macro_api ctx p =
 			let m, tdef, pos = (try Interp.decode_type_def v with Interp.Invalid_expr -> Interp.exc (Interp.VString "Invalid type definition")) in
 			ignore(Typeload.type_module ctx m "" [tdef,pos] pos);
 		);
+		Interp.module_dependency = (fun mpath file ->
+			let m = typing_timer ctx (fun() -> Typeload.load_module ctx (parse_path mpath) p) in
+			let file = Extc.get_full_path file in
+			let mdep = (try Hashtbl.find fake_modules file with Not_found ->
+				let mdep = {
+					m_id = alloc_mid();
+					m_path = (["$DEP"],file);
+					m_file = file;
+					m_types = [];
+					m_deps = ref PMap.empty;
+					m_processed = 0;
+				} in
+				Hashtbl.add fake_modules file mdep;
+				mdep
+			) in
+			(m.m_deps) := PMap.add mdep () !(m.m_deps);
+			Hashtbl.replace ctx.g.modules mdep.m_path mdep
+		);
 	}
 
 let load_macro ctx cpath f p =