瀏覽代碼

add `interpolate_code` and enable it for `__js__` (see #3226)

Simon Krajewski 11 年之前
父節點
當前提交
7533b85e98
共有 4 個文件被更改,包括 59 次插入33 次删除
  1. 37 2
      codegen.ml
  2. 1 31
      gencpp.ml
  3. 2 0
      genjs.ml
  4. 19 0
      tests/unit/issues/Issue3226.hx

+ 37 - 2
codegen.ml

@@ -385,7 +385,7 @@ let rec build_generic ctx c p tl =
 						if pl <> [] then raise Not_found;
 						if pl <> [] then raise Not_found;
 						let t = loop subst in
 						let t = loop subst in
 						(* extended type parameter: concrete type must have a constructor, but generic base class must not have one *)
 						(* extended type parameter: concrete type must have a constructor, but generic base class must not have one *)
- 						begin match follow t,c.cl_constructor with
+						begin match follow t,c.cl_constructor with
 							| TInst({cl_constructor = None} as cs,_),None -> error ("Cannot use " ^ (s_type_path cs.cl_path) ^ " as type parameter because it is extended and has no constructor") p
 							| TInst({cl_constructor = None} as cs,_),None -> error ("Cannot use " ^ (s_type_path cs.cl_path) ^ " as type parameter because it is extended and has no constructor") p
 							| _,Some cf -> error "Generics extending type parameters cannot have constructors" cf.cf_pos
 							| _,Some cf -> error "Generics extending type parameters cannot have constructors" cf.cf_pos
 							| _ -> ()
 							| _ -> ()
@@ -793,7 +793,7 @@ end
 
 
 module PatternMatchConversion = struct
 module PatternMatchConversion = struct
 
 
- 	type cctx = {
+	type cctx = {
 		ctx : typer;
 		ctx : typer;
 		mutable eval_stack : ((tvar * pos) * texpr) list list;
 		mutable eval_stack : ((tvar * pos) * texpr) list list;
 		dt_lookup : dt array;
 		dt_lookup : dt array;
@@ -1715,3 +1715,38 @@ module DeprecationCheck = struct
 				()
 				()
 		) com.types
 		) com.types
 end
 end
+
+let interpolate_code com code tl f_string f_expr p =
+	let exprs = Array.of_list tl in
+	let i = ref 0 in
+	let err msg =
+		let pos = { p with pmin = p.pmin + !i } in
+		com.error msg pos
+	in
+	let regex = Str.regexp "[{}]" in
+	let rec loop m = match m with
+		| [] ->
+			()
+		| Str.Text txt :: tl ->
+			i := !i + String.length txt;
+			f_string txt;
+			loop tl
+		| Str.Delim a :: Str.Delim b :: tl when a = b ->
+			i := !i + 2;
+			f_string a;
+			loop tl
+		| Str.Delim "{" :: Str.Text n :: Str.Delim "}" :: tl ->
+			(try
+				let expr = Array.get exprs (int_of_string n) in
+				f_expr expr;
+				i := !i + 2 + String.length n;
+				loop tl
+			with
+			| Failure "int_of_string" ->
+				err ("Index expected. Got " ^ n)
+			| Invalid_argument _ ->
+				err ("Out-of-bounds special parameter: " ^ n))
+			| Str.Delim x :: _ ->
+				err ("Unexpected " ^ x)
+	in
+	loop (Str.full_split regex code)

+ 1 - 31
gencpp.ml

@@ -1848,37 +1848,7 @@ and gen_expression ctx retval expression =
       ( match arg_list with
       ( match arg_list with
       | [{ eexpr = TConst (TString code) }] -> output code;
       | [{ eexpr = TConst (TString code) }] -> output code;
       | ({ eexpr = TConst (TString code) } as ecode) :: tl ->
       | ({ eexpr = TConst (TString code) } as ecode) :: 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
-          ctx.ctx_common.error msg pos
-        in
-        let regex = Str.regexp "[{}]" in
-        let rec loop m = match m with
-          | [] -> ()
-          | Str.Text txt :: tl ->
-            i := !i + String.length txt;
-            output txt;
-            loop tl
-          | Str.Delim a :: Str.Delim b :: tl when a = b ->
-            i := !i + 2;
-            output a;
-            loop tl
-          | Str.Delim "{" :: Str.Text n :: Str.Delim "}" :: tl ->
-            (try
-              let expr = Array.get exprs (int_of_string n) in
-              gen_expression ctx true expr;
-              i := !i + 2 + String.length n;
-              loop tl
-            with | Failure "int_of_string" ->
-              err ("Index expected. Got " ^ n)
-            | Invalid_argument _ ->
-              err ("Out-of-bounds __cpp__ special parameter: " ^ n))
-          | Str.Delim x :: _ ->
-            err ("Unexpected " ^ x)
-        in
-        loop (Str.full_split regex code)
+         Codegen.interpolate_code ctx.ctx_common code tl output (gen_expression ctx true) ecode.epos
       | _ -> error "__cpp__'s first argument must be a string" func.epos;
       | _ -> error "__cpp__'s first argument must be a string" func.epos;
       )
       )
    | TCall (func, arg_list) when tcall_expand_args->
    | TCall (func, arg_list) when tcall_expand_args->

+ 2 - 0
genjs.ml

@@ -402,6 +402,8 @@ let rec gen_call ctx e el in_value =
 		spr ctx (this ctx)
 		spr ctx (this ctx)
 	| TLocal { v_name = "__js__" }, [{ eexpr = TConst (TString code) }] ->
 	| TLocal { v_name = "__js__" }, [{ eexpr = TConst (TString code) }] ->
 		spr ctx (String.concat "\n" (ExtString.String.nsplit code "\r\n"))
 		spr ctx (String.concat "\n" (ExtString.String.nsplit code "\r\n"))
+	| TLocal { v_name = "__js__" }, { eexpr = TConst (TString code); epos = p } :: tl ->
+		Codegen.interpolate_code ctx.com code tl (spr ctx) (gen_expr ctx) p
 	| TLocal { v_name = "__instanceof__" },  [o;t] ->
 	| TLocal { v_name = "__instanceof__" },  [o;t] ->
 		spr ctx "(";
 		spr ctx "(";
 		gen_value ctx o;
 		gen_value ctx o;

+ 19 - 0
tests/unit/issues/Issue3226.hx

@@ -0,0 +1,19 @@
+package unit.issues;
+
+class Issue3226 extends Test {
+	#if js
+	function testJs() {
+		var a = 1;
+		var v = 2;
+		untyped __js__("{0} = {0} + {1}", a, v);
+		eq(3, a);
+	}
+	#elseif cpp
+	function testCpp() {
+		var a = 1;
+		var v = 2;
+		untyped __cpp__("{0} = {0} + {1}", a, v);
+		eq(3, a);
+	}
+	#end
+}