Browse Source

deal with member macro calls the same way as static extensions (closes #2003)

Simon Krajewski 11 years ago
parent
commit
2786a4c47d
3 changed files with 57 additions and 8 deletions
  1. 12 0
      tests/unit/issues/Issue2003.hx
  2. 24 0
      tests/unit/issues/misc/Issue2003Macro.hx
  3. 21 8
      typer.ml

+ 12 - 0
tests/unit/issues/Issue2003.hx

@@ -0,0 +1,12 @@
+package unit.issues;
+import unit.Test;
+
+class Issue2003 extends Test {
+	
+	var myVar:String = "cool";
+	
+	function test() {
+		var o = unit.issues.misc.Issue2003Macro.create().callMe( function() { this.myVar = "super "+myVar; } ).testMacro();
+		eq("super cool", myVar);
+	}
+}

+ 24 - 0
tests/unit/issues/misc/Issue2003Macro.hx

@@ -0,0 +1,24 @@
+package unit.issues.misc;
+
+import haxe.macro.Expr;
+
+class Issue2003Macro {
+    public function new() {}
+
+    public function callMe( cb:Void->Void ) {
+        cb();
+        return this;
+    }
+
+    public static function create() {
+        return new Issue2003Macro();
+    }
+
+    macro public function testMacro( ethis : Expr ) : Expr {
+        var vname = "_____ref";
+        var vdecl = macro var $vname = $ethis;
+        var v = { expr : EConst(CIdent(vname)), pos : haxe.macro.Context.currentPos() };
+        var eret = macro (function() { $vdecl;  return $v; })();
+        return eret;
+    }
+}

+ 21 - 8
typer.ml

@@ -3432,13 +3432,14 @@ and build_call ctx acc el (with_type:with_type) p =
 			in
 			make_call ctx et (eparam :: params) r p
 		end
-	| AKMacro (ethis,f) ->
+	| AKMacro (ethis,cf) ->
 		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 ethis_f = ref (fun () -> ()) in
 		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
+			(match ctx.g.do_macro ctx MExpr c.cl_path cf.cf_name el p with
 			| None -> (fun() -> type_expr ctx (EConst (Ident "null"),p) Value)
 			| Some (EMeta((Meta.MergeBlock,_,_),(EBlock el,_)),_) -> (fun () -> let e = type_block ctx el with_type p in mk (TMeta((Meta.MergeBlock,[],p), e)) e.etype e.epos)
 			| Some (EVars vl,p) -> (fun() -> type_vars ctx vl p true)
@@ -3448,17 +3449,22 @@ and build_call ctx acc el (with_type:with_type) p =
 			(match follow ethis.etype with
 			| TInst (c,_) ->
 				let rec loop c =
-					if PMap.mem f.cf_name c.cl_fields then
-						match ctx.g.do_macro ctx MExpr c.cl_path f.cf_name (Interp.make_ast ethis :: el) p with
-						| None -> (fun() -> type_expr ctx (EConst (Ident "null"),p) Value)
-						| Some e -> (fun() -> type_expr ctx e Value)
+					if PMap.mem cf.cf_name c.cl_fields then
+						let eparam,f = push_this ethis in
+						ethis_f := f;
+						let e = match ctx.g.do_macro ctx MExpr c.cl_path cf.cf_name (eparam :: el) p with
+							| None -> (fun() -> type_expr ctx (EConst (Ident "null"),p) Value)
+							| Some e -> (fun() -> type_expr ctx e Value)
+						in
+						e
 					else
 						match c.cl_super with
 						| None -> assert false
 						| Some (csup,_) -> loop csup
 				in
 				loop c
-			| _ -> assert false)) in
+			| _ -> 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
@@ -3467,8 +3473,15 @@ and build_call ctx acc el (with_type:with_type) p =
 			(* display additional info in the case the error is not part of our original call *)
 			if ep.pfile <> p.pfile || ep.pmax < p.pmin || ep.pmin > p.pmax then old ctx "Called from macro here" p
 		);
-		let e = try f() with Error (m,p) -> ctx.on_error <- old; raise (Fatal_error ((error_msg m),p)) in
+		let e = try
+			f()
+		with Error (m,p) ->
+			ctx.on_error <- old;
+			!ethis_f();
+			raise (Fatal_error ((error_msg m),p))
+		in
 		ctx.on_error <- old;
+		!ethis_f();
 		e
 	| AKNo _ | AKSet _ | AKAccess _ ->
 		ignore(acc_get ctx acc p);