Przeglądaj źródła

added new macro reification syntax

Simon Krajewski 12 lat temu
rodzic
commit
fa5e80d92a

+ 13 - 6
ast.ml

@@ -718,7 +718,7 @@ let reify in_macro =
 		else
 		else
 			to_obj [("file",file);("min",pmin);("max",pmax)] p
 			to_obj [("file",file);("min",pmin);("max",pmax)] p
 	and to_expr_array a p = match a with
 	and to_expr_array a p = match a with
-		| [EArray ((EConst(Ident("$")),_),e),p] -> e
+		| [EMeta (("$a",[],_),e1),_] -> (match fst e1 with EArrayDecl el -> to_expr_array el p | _ -> e1)
 		| _ -> to_array to_expr a p
 		| _ -> to_array to_expr a p
 	and to_expr e _ =
 	and to_expr e _ =
 		let p = snd e in
 		let p = snd e in
@@ -732,8 +732,6 @@ let reify in_macro =
 			to_string n p
 			to_string n p
 		| EConst c ->
 		| EConst c ->
 			expr "EConst" [to_const c p]
 			expr "EConst" [to_const c p]
-		| EArray ((EConst(Ident("$")),_),e) ->
-			expr "EArrayDecl" [e]
 		| EArray (e1,e2) ->
 		| EArray (e1,e2) ->
 			expr "EArray" [loop e1;loop e2]
 			expr "EArray" [loop e1;loop e2]
 		| EBinop (op,e1,e2) ->
 		| EBinop (op,e1,e2) ->
@@ -746,8 +744,6 @@ let reify in_macro =
 			expr "EObjectDecl" [to_array (fun (f,e) -> to_obj [("field",to_string f p);("expr",loop e)]) fl p]
 			expr "EObjectDecl" [to_array (fun (f,e) -> to_obj [("field",to_string f p);("expr",loop e)]) fl p]
 		| EArrayDecl el ->
 		| EArrayDecl el ->
 			expr "EArrayDecl" [to_expr_array el p]
 			expr "EArrayDecl" [to_expr_array el p]
-		| ECall ((EConst(Ident("$")),_),[e]) ->
-			(ECall ((EField ((EField ((EField ((EConst (Ident "haxe"),p),"macro"),p),"Context"),p),"makeExpr"),p),[e; to_pos (pos e)]),p)
 		| ECall (e,el) ->
 		| ECall (e,el) ->
 			expr "ECall" [loop e;to_expr_array el p]
 			expr "ECall" [loop e;to_expr_array el p]
 		| ENew (t,el) ->
 		| ENew (t,el) ->
@@ -813,6 +809,17 @@ let reify in_macro =
 		| ECheckType (e1,ct) ->
 		| ECheckType (e1,ct) ->
 			expr "ECheckType" [loop e1; to_ctype ct p]
 			expr "ECheckType" [loop e1; to_ctype ct p]
 		| EMeta ((m,ml,p),e1) ->
 		| EMeta ((m,ml,p),e1) ->
-			expr "EMeta" [to_obj [("name",to_string m p);("params",to_expr_array ml p);("pos",to_pos p)] p;loop e1]
+			match m with
+			| "$" | "$e" ->
+				e1
+			| "$a" ->
+				expr "EArrayDecl" (match fst e1 with EArrayDecl el -> [to_expr_array el p] | _ -> [e1])
+			(* TODO: can $v and $i be implemented better? *)
+			| "$v" ->
+				(ECall ((EField ((EField ((EField ((EConst (Ident "haxe"),p),"macro"),p),"Context"),p),"makeExpr"),p),[e; to_pos (pos e)]),p)
+			| "$i" ->
+				(ECall ((EField ((EField ((EField ((EConst (Ident "haxe"),p),"macro"),p),"ExprTools"),p),"asIdent"),p),[e; to_pos (pos e)]),p)
+			| _ ->
+				expr "EMeta" [to_obj [("name",to_string m p);("params",to_expr_array ml p);("pos",to_pos p)] p;loop e1]
 	in
 	in
 	(fun e -> to_expr e (snd e)), to_ctype
 	(fun e -> to_expr e (snd e)), to_ctype

+ 12 - 0
parser.ml

@@ -96,6 +96,12 @@ let is_not_assign = function
 	| OpAssign | OpAssignOp _ -> false
 	| OpAssign | OpAssignOp _ -> false
 	| _ -> true
 	| _ -> true
 
 
+let is_dollar_ident e = match fst e with
+	| EConst (Ident n) when n.[0] = '$' ->
+		true
+	| _ ->
+		false
+
 let swap op1 op2 =
 let swap op1 op2 =
 	let p1, left1 = precedence op1 in
 	let p1, left1 = precedence op1 in
 	let p2, _ = precedence op2 in
 	let p2, _ = precedence op2 in
@@ -813,10 +819,16 @@ and expr = parser
 	| [< '(Dollar v,p); s >] -> expr_next (EConst (Ident ("$"^v)),p) s
 	| [< '(Dollar v,p); s >] -> expr_next (EConst (Ident ("$"^v)),p) s
 
 
 and expr_next e1 = parser
 and expr_next e1 = parser
+	| [< '(BrOpen,p1) when is_dollar_ident e1; eparam = expr; '(BrClose,p2) >] ->
+		(match fst e1 with
+		| EConst(Ident s) -> (EMeta((s,[],snd e1),eparam), punion p1 p2)
+		| _ -> assert false)
 	| [< '(Dot,p); s >] ->
 	| [< '(Dot,p); s >] ->
 		if is_resuming p then display (EDisplay (e1,false),p);
 		if is_resuming p then display (EDisplay (e1,false),p);
 		(match s with parser
 		(match s with parser
 		| [< '(Const (Ident f),p2) when p.pmax = p2.pmin; s >] -> expr_next (EField (e1,f) , punion (pos e1) p2) s
 		| [< '(Const (Ident f),p2) when p.pmax = p2.pmin; s >] -> expr_next (EField (e1,f) , punion (pos e1) p2) s
+		(* TODO: we have to limit this to the reification case *)
+		| [< '(Dollar v,p2); s >] -> expr_next (EField (e1,"$"^v) , punion (pos e1) p2) s
 		| [< '(Binop OpOr,p2) when do_resume() >] -> display (EDisplay (e1,false),p) (* help for debug display mode *)
 		| [< '(Binop OpOr,p2) when do_resume() >] -> display (EDisplay (e1,false),p) (* help for debug display mode *)
 		| [< >] ->
 		| [< >] ->
 			(* turn an integer followed by a dot into a float *)
 			(* turn an integer followed by a dot into a float *)

+ 3 - 0
std/haxe/macro/ExprTools.hx

@@ -34,6 +34,9 @@ import haxe.macro.Expr;
 **/
 **/
 class ExprTools {
 class ExprTools {
 	
 	
+	static public function asIdent( s : String, p:Position ) : Expr
+		return { expr : EConst(CIdent(s)), pos : p }
+		
 	/**
 	/**
 		Converts expression [e] to a human-readable String representation.
 		Converts expression [e] to a human-readable String representation.
 		
 		

+ 2 - 2
std/haxe/macro/Printer.hx

@@ -26,10 +26,10 @@ import haxe.macro.Expr;
 using Lambda;
 using Lambda;
 
 
 class Printer {
 class Printer {
-	var tabs = "";
+	var tabs:String;
 
 
 	public function new() {
 	public function new() {
-
+		tabs = "";
 	}
 	}
 	
 	
 	public function printUnop(op:Unop) return switch(op) {
 	public function printUnop(op:Unop) return switch(op) {

+ 2 - 2
tests/unit/MyMacro.hx

@@ -7,13 +7,13 @@ class MyRestMacro {
 		var ret = [e];
 		var ret = [e];
 		for (e in r)
 		for (e in r)
 			ret.push(e);
 			ret.push(e);
-		return macro $[ret];
+		return macro $a{ret};
 	}
 	}
 	
 	
 	@:macro static public function testRest2(e1:Expr, e2:Expr, r:Array<Expr>) {
 	@:macro static public function testRest2(e1:Expr, e2:Expr, r:Array<Expr>) {
 		var ret = [e1,e2];
 		var ret = [e1,e2];
 		for (e in r)
 		for (e in r)
 			ret.push(e);
 			ret.push(e);
-		return macro $[ret];
+		return macro $a{ret};
 	}
 	}
 }
 }

+ 1 - 1
tests/unit/TestMatch.hx

@@ -23,7 +23,7 @@ class TestMatch extends Test {
 			haxe.macro.Context.typeof(e);
 			haxe.macro.Context.typeof(e);
 			"no error";
 			"no error";
 		} catch (e:Dynamic) Std.string(e.message);
 		} catch (e:Dynamic) Std.string(e.message);
-		return macro $(result);
+		return macro $v{result};
 	}
 	}
 	
 	
 	static function switchNormal(e:Expr):String {
 	static function switchNormal(e:Expr):String {

+ 1 - 1
tests/unit/TestMeta.hx

@@ -71,7 +71,7 @@ package unit;
 	@:macro static function getMeta(e) {
 	@:macro static function getMeta(e) {
 		switch(e.expr) {
 		switch(e.expr) {
 			case EMeta(m, _):
 			case EMeta(m, _):
-				return macro { name: $(m.name), args: $[m.params] };
+				return macro { name: $v{m.name}, args: $a{m.params} };
 			default:
 			default:
 				return macro report("Metadata expected");
 				return macro report("Metadata expected");
 		}
 		}

+ 3 - 3
tests/unit/UnitBuilder.hx

@@ -128,12 +128,12 @@ class UnitBuilder {
 					var el2 = [];
 					var el2 = [];
 					for (i in 0...el.length) {
 					for (i in 0...el.length) {
 						var e2 = el[i];
 						var e2 = el[i];
-						el2.push(mkEq((macro $e1[$(i)]), e2, e.pos));
+						el2.push(mkEq((macro $e1[$v{i}]), e2, e.pos));
 					}
 					}
 					if (el2.length == 0)
 					if (el2.length == 0)
 						mkEq((macro $e1.length), (macro 0), e.pos);
 						mkEq((macro $e1.length), (macro 0), e.pos);
 					else
 					else
-						macro { $[el2]; };
+						macro { $a{el2}; };
 				case EBinop(OpEq, e1, e2):
 				case EBinop(OpEq, e1, e2):
 					mkEq(e1, e2, e.pos);
 					mkEq(e1, e2, e.pos);
 				case EThrow(e):
 				case EThrow(e):
@@ -148,7 +148,7 @@ class UnitBuilder {
 			}
 			}
 			ret.push(e);
 			ret.push(e);
 		}
 		}
-		return macro { $[ret]; };
+		return macro { $a{ret}; };
 	}
 	}
 	#end
 	#end
 }
 }