瀏覽代碼

Merge branch 'follow_with_abstracts' of https://github.com/waneck/haxe into waneck-follow_with_abstracts

Conflicts:
	interp.ml
Cauê Waneck 10 年之前
父節點
當前提交
cb96076de3
共有 5 個文件被更改,包括 76 次插入1 次删除
  1. 20 0
      interp.ml
  2. 9 0
      std/haxe/macro/Context.hx
  3. 16 0
      std/haxe/macro/TypeTools.hx
  4. 20 1
      tests/unit/src/unit/MyMacro.hx
  5. 11 0
      tests/unit/src/unit/TestType.hx

+ 20 - 0
interp.ml

@@ -2539,6 +2539,25 @@ let macro_lib =
 				PMap.iter (fun n v -> Hashtbl.replace h (VString n) (encode_type v.v_type)) vars;
 			enc_hash h
 		);
+		"follow_with_abstracts", Fun2 (fun v once ->
+			let t = decode_type v in
+			let follow_once t =
+				match t with
+				| TMono r ->
+					(match !r with
+					| None -> t
+					| Some t -> t)
+				| TAbstract (a,tl) when not (Ast.Meta.has Ast.Meta.CoreType a.a_meta) ->
+					Abstract.get_underlying_type a tl
+				| TAbstract _ | TEnum _ | TInst _ | TFun _ | TAnon _ | TDynamic _ ->
+					t
+				| TType (t,tl) ->
+					apply_params t.t_params tl t.t_type
+				| TLazy f ->
+					(!f)()
+			in
+			encode_type (match once with VNull | VBool false -> Abstract.follow_with_abstracts t | VBool true -> follow_once t | _ -> error())
+		);
 		"follow", Fun2 (fun v once ->
 			let t = decode_type v in
 			let follow_once t =
@@ -4987,3 +5006,4 @@ decode_path_ref := decode_path;
 encode_import_ref := encode_import;
 decode_import_ref := decode_import;
 eval_expr_ref := eval_expr;
+encode_import_ref := encode_import;

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

@@ -393,6 +393,15 @@ class Context {
 		return load("follow", 2)(t,once);
 	}
 
+	/**
+		Follows a type, including abstracts' underlying implementation
+
+		See `haxe.macro.TypeTools.followWithAbstracts` for details.
+	**/
+	public static function followWithAbstracts(t : Type, once : Bool = false ) : Type {
+		return load("follow_with_abstracts", 2)(t,once);
+	}
+
 	/**
 		Returns the information stored in `Position` `p`.
 	**/

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

@@ -173,6 +173,22 @@ class TypeTools {
 	static public inline function follow( t : Type, ?once : Bool ) : Type
 		return Context.follow(t, once);
 
+	/**
+		Like `follow`, follows all typedefs of `t` to reach the actual type.
+
+		Will however follow also abstracts to their underlying implementation,
+		if they are not a @:coreType abstract
+
+		If `t` is null, an internal exception is thrown.
+
+		Usage example:
+			var t = Context.typeof(macro new Map<String, String>());
+			trace(t); // TAbstract(Map,[TInst(String,[]),TInst(String,[])])
+			trace(t.followWithAbstracts()); // TInst(haxe.ds.StringMap, [TInst(String,[])])
+	**/
+	static public inline function followWithAbstracts( t : Type, once : Bool = false ) : Type
+		return Context.followWithAbstracts(t, once);
+
 	/**
 		Returns true if `t1` and `t2` unify, false otherwise.
 	**/

+ 20 - 1
tests/unit/src/unit/MyMacro.hx

@@ -1,6 +1,7 @@
 package unit;
 
 import haxe.macro.Expr;
+import haxe.macro.Context;
 
 class MyRestMacro {
 	static public macro function testRest1(e:Expr, r:Array<Expr>) {
@@ -16,4 +17,22 @@ class MyRestMacro {
 			ret.push(e);
 		return macro $a{ret};
 	}
-}
+}
+
+class MyMacroHelper
+{
+	static public macro function followWithAbstracts(e1:Expr):Expr
+	{
+		return macro $v{Context.followWithAbstracts(Context.typeof(e1)) + ""};
+	}
+
+	static public macro function followWithAbstractsOnce(e1:Expr):Expr
+	{
+		return macro $v{Context.followWithAbstracts(Context.typeof(e1),true) + ""};
+	}
+
+	static public macro function ttype(e1:Expr):Expr
+	{
+		return macro $v{Context.typeof(e1) + ""};
+	}
+}

+ 11 - 0
tests/unit/src/unit/TestType.hx

@@ -523,6 +523,15 @@ class TestType extends Test {
 		map[0];
 	}
 
+	public function testMacroFollowWithAbstracts()
+	{
+		#if !macro
+		eq(MyMacro.MyMacroHelper.followWithAbstracts(new Map<String,String>()), "TInst(haxe.ds.StringMap,[TInst(String,[])])");
+		eq(MyMacro.MyMacroHelper.followWithAbstractsOnce({ var x:TypedefToStringMap<String>; x; }), "TAbstract(Map,[TInst(String,[]),TInst(String,[])])");
+		eq(MyMacro.MyMacroHelper.followWithAbstracts(new TypedefToStringMap<String>()), "TInst(haxe.ds.StringMap,[TInst(String,[])])");
+		#end
+	}
+
 	public function testMacroRest() {
 		#if !macro
 		var r = MyMacro.MyRestMacro.testRest1(1, 2, 3);
@@ -876,3 +885,5 @@ class TestType extends Test {
 		typedAs(unit.MyAbstract.GADTEnumAbstract.B, expectedB);
 	}
 }
+
+typedef TypedefToStringMap<T> = Map<String,T>