Browse Source

revert pythonCode string interpolation to the same used in cpp, c# etc.

frabbit 11 years ago
parent
commit
a8a24b972e
5 changed files with 52 additions and 21 deletions
  1. 32 9
      genpy.ml
  2. 7 1
      std/python/Syntax.hx
  3. 1 1
      std/python/internal/ArrayImpl.hx
  4. 1 0
      std/python/internal/HxBuiltin.hx
  5. 11 10
      tests/unit/TestPython.hx

+ 32 - 9
genpy.ml

@@ -157,7 +157,7 @@ module Transformer = struct
 	let create_non_local n pos =
 		let s = "nonlocal " ^ (KeywordHandler.handle_keywords n) in
 		(* TODO: this is a hack... *)
-		let id = mk (TLocal (to_tvar "python_Syntax.pythonCode" t_dynamic ) ) !t_void pos in
+		let id = mk (TLocal (to_tvar "python_Syntax._pythonCode" t_dynamic ) ) !t_void pos in
 		let id2 = mk (TLocal( to_tvar s t_dynamic )) !t_void pos in
 		mk (TCall(id, [id2])) t_dynamic pos
 
@@ -1367,15 +1367,38 @@ module Printer = struct
 			| "super",_ ->
 				let s_el = print_exprs pctx ", " el in
 				Printf.sprintf "super().__init__(%s)" s_el
-			| ("python_Syntax.pythonCode"),[e] ->
-				(* supports native haxe string interpolation *)
-				let rec loop x =
-					(match x with
-					| { eexpr = TBinop(OpAdd,a,b)} -> (loop a) ^ (loop b)
-					| { eexpr = TConst (TString s) } -> s
-					| e -> print_expr pctx e)
+			| ("python_Syntax._pythonCode"),[({ eexpr = TConst (TString code) } as ecode); {eexpr = TArrayDecl tl}] ->
+				let exprs = Array.of_list tl in
+				let i = ref 0 in
+				let err msg =
+					let pos = { ecode.epos with pmin = ecode.epos.pmin + !i } in
+					error msg pos
 				in
-				loop e
+				let regex = Str.regexp "[{}]" in
+				let rec loop m = match m with
+					| [] -> ""
+					| Str.Text txt :: tl ->
+						i := !i + String.length txt;
+						txt ^ (loop tl)
+					| Str.Delim a :: Str.Delim b :: tl when a = b ->
+						i := !i + 2;
+						a ^ (loop tl)
+					| Str.Delim "{" :: Str.Text n :: Str.Delim "}" :: tl ->
+						(try
+						let expr = Array.get exprs (int_of_string n) in
+						let txt = print_expr pctx expr in
+						i := !i + 2 + String.length n;
+						txt ^ (loop tl)
+					with | Failure "int_of_string" ->
+						err ("Index expected. Got " ^ n)
+					| Invalid_argument _ ->
+						err ("Out-of-bounds pythonCode special parameter: " ^ n))
+					| Str.Delim x :: _ ->
+						err ("Unexpected " ^ x)
+				in
+				loop (Str.full_split regex code)
+			| ("python_Syntax._pythonCode"), [e] ->
+				print_expr pctx e
 			| "python_Syntax._callNamedUntyped",el ->
 				let res,fields = match List.rev el with
 					| {eexpr = TObjectDecl fields} :: el ->

+ 7 - 1
std/python/Syntax.hx

@@ -44,7 +44,13 @@ extern class Syntax {
 	public static function assign(a:Dynamic, b:Dynamic):Void { }
 
 	@:noUsing
-	public static function pythonCode<T>(b:String):T { return null; };
+	macro public static function pythonCode(b:ExprOf<String>, rest:Array<Expr>):Expr {
+		if (rest == null) rest = [];
+		return macro @:pos(Context.currentPos()) $self._pythonCode($b, $a{rest});
+	};
+
+	@:noUsing
+	public static function _pythonCode<T>(b:String, args:Array<Dynamic>):T { return null; };
 
 	@:noUsing
 	macro public static function arrayAccess(x:Expr, rest:Array<Expr>):ExprOf<Dynamic> {

+ 1 - 1
std/python/internal/ArrayImpl.hx

@@ -71,7 +71,7 @@ class ArrayImpl {
 
 	@:access(python.Boot)
 	public static inline function join<T>(x:Array<T>, sep : String ) : String {
-		return Syntax.field(sep, "join")(x.map(python.Boot.toString));
+		return Syntax.field(sep, "join")(Syntax.pythonCode("[{0}(x1) for x1 in {1}]", python.Boot.toString, x));
 	}
 
 	public static inline function toString<T>(x:Array<T>) : String {

+ 1 - 0
std/python/internal/HxBuiltin.hx

@@ -19,6 +19,7 @@ package python.internal;
 	public static function int(x:Dynamic):Int;
 	public static function ord(s:String):Int;
 
+	public static function map (a:Dynamic, b:Dynamic):Dynamic;
 	public static function str(o:Dynamic):String;
 
 	public static function float(x:Dynamic):Float;

+ 11 - 10
tests/unit/TestPython.hx

@@ -294,18 +294,18 @@ class TestPython extends Test {
 
 	function testPythonCodeStringInterpolation () {
 		var z = 1;
-		var a = (Syntax.pythonCode('[$z, ${2}]'):Array<Int>);
+		var a = (Syntax.pythonCode('[{0}, {1}]', z, 2):Array<Int>);
 
 		eq(a[0], z);
 		eq(a[1], 2);
 
-		inline function test2 (x:Int) {
+		function test2 (x:Int) {
 			x += 1;
-			return (Syntax.pythonCode('$x'):Int);
+			return (Syntax.pythonCode("{0}", x):Int);
 		}
 
-		inline function test3 (x:Int) {
-			return (Syntax.pythonCode('[$x]'):Array<Int>);
+		function test3 (x:Int) {
+			return (Syntax.pythonCode('[{0}]', x):Array<Int>);
 		}
 
 		var x = 1;
@@ -314,18 +314,19 @@ class TestPython extends Test {
 		eq(1, x);
 		eq(1, test3(1)[0]);
 
-		eq("foo1bar", Syntax.pythonCode("'foo' + str(" + x + ") + 'bar'"));
+		eq("foo1bar", Syntax.pythonCode("'foo' + str({0}) + 'bar'", x));
 
 
 		function test4a (x:Int) {
-			return (Syntax.pythonCode("["+'${x+x}' + "][0]"):Int);
+			return (Syntax.pythonCode("[{0}][0]", x+x):Int);
 		}
 
-		function test4b (x:Int) {
-			return (Syntax.pythonCode('['+ Std.string(x+x) + '][0]'):Int);
+		function test4b (x:Int):String {
+			return Syntax.pythonCode('[{0}][0]', (function () return Std.string(x+x))() );
 		}
 
-		eq(test4a(1), test4b(1));
+		eq(2, test4a(1));
+		eq("2", test4b(1));
 	}
 
 	function testExtern()