Przeglądaj źródła

add Context.getExpecteType

Simon Krajewski 11 lat temu
rodzic
commit
af99c07450
5 zmienionych plików z 32 dodań i 0 usunięć
  1. 6 0
      interp.ml
  2. 16 0
      std/haxe/macro/Context.hx
  3. 1 0
      typecore.ml
  4. 1 0
      typeload.ml
  5. 8 0
      typer.ml

+ 6 - 0
interp.ml

@@ -110,6 +110,7 @@ type extern_api = {
 	meta_patch : string -> string -> string option -> bool -> unit;
 	set_js_generator : (value -> unit) -> unit;
 	get_local_type : unit -> t option;
+	get_expected_type : unit -> t option;
 	get_local_method : unit -> string;
 	get_local_using : unit -> tclass list;
 	get_local_vars : unit -> (string, Type.tvar) PMap.t;
@@ -2416,6 +2417,11 @@ let macro_lib =
 			| None -> VNull
 			| Some t -> encode_type t
 		);
+		"expected_type", Fun0 (fun() ->
+			match (get_ctx()).curapi.get_expected_type() with
+			| None -> VNull
+			| Some t -> encode_type t
+		);
 		"local_method", Fun0 (fun() ->
 			VString ((get_ctx()).curapi.get_local_method())
 		);

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

@@ -97,6 +97,22 @@ class Context {
 		return load("curpos", 0)();
 	}
 
+	/**
+		Returns the type which is expected at the place the macro is called.
+		
+		This affects usages such as `var x:Int = macroCall()`, where the
+		expected type will be reported as Int.
+		
+		Might return null if no specific type is expected or if the calling
+		macro is not an expression-macro.
+	**/
+	@:require(haxe_ver >= 3.01)
+	public static function getExpectedType():Null<Type> {
+		var l : Type = load("expected_type", 0)();
+		if( l == null ) return null;
+		return l;
+	}
+	
 	/**
 		Returns the current class in which the macro was called.
 		

+ 1 - 0
typecore.ml

@@ -94,6 +94,7 @@ and typer = {
 	g : typer_globals;
 	mutable meta : metadata;
 	mutable this_stack : texpr list;
+	mutable with_type_stack : with_type list;
 	(* variable *)
 	mutable pass : typer_pass;
 	(* per-module *)

+ 1 - 0
typeload.ml

@@ -2470,6 +2470,7 @@ let type_module ctx m file tdecls p =
 		};
 		meta = [];
 		this_stack = [];
+		with_type_stack = [];
 		pass = PBuildModule;
 		on_error = (fun ctx msg p -> ctx.com.error msg p);
 		macro_depth = ctx.macro_depth;

+ 8 - 0
typer.ml

@@ -3366,6 +3366,7 @@ and build_call ctx acc el (with_type:with_type) p =
 	| AKMacro (ethis,f) ->
 		if ctx.macro_depth > 300 then error "Stack overflow" p;
 		ctx.macro_depth <- ctx.macro_depth + 1;
+		ctx.with_type_stack <- with_type :: ctx.with_type_stack;
 		let f = (match ethis.eexpr with
 		| TTypeExpr (TClassDecl c) ->
 			(match ctx.g.do_macro ctx MExpr c.cl_path f.cf_name el p with
@@ -3390,6 +3391,7 @@ and build_call ctx acc el (with_type:with_type) p =
 				loop c
 			| _ -> assert false)) in
 		ctx.macro_depth <- ctx.macro_depth - 1;
+		ctx.with_type_stack <- List.tl ctx.with_type_stack;
 		let old = ctx.on_error in
 		ctx.on_error <- (fun ctx msg ep ->
 			old ctx msg ep;
@@ -3811,6 +3813,11 @@ let make_macro_api ctx p =
 				else
 					Some (TInst (ctx.curclass,[]))
 		);
+		Interp.get_expected_type = (fun() ->
+			match ctx.with_type_stack with
+				| (WithType t | WithTypeResume t) :: _ -> Some t
+				| _ -> None
+		);
 		Interp.get_local_method = (fun() ->
 			ctx.curfield.cf_name;
 		);
@@ -4216,6 +4223,7 @@ let rec create com =
 		};
 		meta = [];
 		this_stack = [];
+		with_type_stack = [];
 		pass = PBuildModule;
 		macro_depth = 0;
 		untyped = false;