Browse Source

prevent handling formated string when passed to a macro (fixed issue #1284)

Nicolas Cannasse 12 years ago
parent
commit
2cb50b8911
2 changed files with 34 additions and 7 deletions
  1. 27 6
      lexer.mll
  2. 7 1
      typer.ml

+ 27 - 6
lexer.mll

@@ -96,17 +96,37 @@ let newline lexbuf =
 	cur.lline <- cur.lline + 1;
 	cur.lline <- cur.lline + 1;
 	cur.llines <- (lexeme_end lexbuf,cur.lline) :: cur.llines
 	cur.llines <- (lexeme_end lexbuf,cur.lline) :: cur.llines
 
 
-let add_fmt_string pmin =
+let fmt_pos p =
+	p.pmin + (p.pmax - p.pmin) * 1000000
+
+let add_fmt_string p =
+	let file = (try
+		Hashtbl.find all_files p.pfile
+	with Not_found ->
+		let f = make_file p.pfile in
+		Hashtbl.replace all_files p.pfile f;
+		f
+	) in
+	file.lstrings <- (fmt_pos p) :: file.lstrings
+
+let fast_add_fmt_string p =
 	let cur = !cur in
 	let cur = !cur in
-	cur.lstrings <- pmin :: cur.lstrings
+	cur.lstrings <- (fmt_pos p) :: cur.lstrings
 	
 	
 let is_fmt_string p =
 let is_fmt_string p =
 	try
 	try
 		let file = Hashtbl.find all_files p.pfile in
 		let file = Hashtbl.find all_files p.pfile in
-		List.mem p.pmin file.lstrings
+		List.mem (fmt_pos p) file.lstrings
 	with Not_found ->
 	with Not_found ->
 		false
 		false
-	
+
+let remove_fmt_string p =
+	try
+		let file = Hashtbl.find all_files p.pfile in
+		file.lstrings <- List.filter ((<>) (fmt_pos p)) file.lstrings
+	with Not_found ->
+		()
+
 let find_line p f =
 let find_line p f =
 	(* rebuild cache if we have a new line *)
 	(* rebuild cache if we have a new line *)
 	if f.lmaxline <> f.lline then begin
 	if f.lmaxline <> f.lline then begin
@@ -258,8 +278,9 @@ and token = parse
 			let pmin = lexeme_start lexbuf in
 			let pmin = lexeme_start lexbuf in
 			let pmax = (try string2 lexbuf with Exit -> error Unterminated_string pmin) in
 			let pmax = (try string2 lexbuf with Exit -> error Unterminated_string pmin) in
 			let str = (try unescape (contents()) with Exit -> error Invalid_escape pmin) in
 			let str = (try unescape (contents()) with Exit -> error Invalid_escape pmin) in
-			add_fmt_string pmin;
-			mk_tok (Const (String str)) pmin pmax;
+			let t = mk_tok (Const (String str)) pmin pmax in
+			fast_add_fmt_string (snd t);
+			t
 		}
 		}
 	| "~/" {
 	| "~/" {
 			reset();
 			reset();

+ 7 - 1
typer.ml

@@ -3197,6 +3197,7 @@ let type_macro ctx mode cpath f (el:Ast.expr list) p =
 		| _ ->
 		| _ ->
 			el,[]
 			el,[]
 	in
 	in
+	let todo = ref [] in
 	let args =
 	let args =
 		(*
 		(*
 			force default parameter types to haxe.macro.Expr, and if success allow to pass any value type since it will be encoded
 			force default parameter types to haxe.macro.Expr, and if success allow to pass any value type since it will be encoded
@@ -3210,7 +3211,11 @@ let type_macro ctx mode cpath f (el:Ast.expr list) p =
 		let constants = List.map (fun e ->
 		let constants = List.map (fun e ->
 			let p = snd e in
 			let p = snd e in
 			let e = (try
 			let e = (try
-				ignore(Codegen.type_constant_value ctx.com e);
+				(match Codegen.type_constant_value ctx.com e with
+				| { eexpr = TConst (TString _); epos = p } when Lexer.is_fmt_string p ->
+					Lexer.remove_fmt_string p;
+					todo := (fun() -> Lexer.add_fmt_string p) :: !todo;
+				| _ -> ());
 				e
 				e
 			with Error (Custom _,_) ->
 			with Error (Custom _,_) ->
 				(* if it's not a constant, let's make something that is typed as haxe.macro.Expr - for nice error reporting *)
 				(* if it's not a constant, let's make something that is typed as haxe.macro.Expr - for nice error reporting *)
@@ -3224,6 +3229,7 @@ let type_macro ctx mode cpath f (el:Ast.expr list) p =
 			(EArray ((EArrayDecl [e],p),(EConst (Int (string_of_int (!index))),p)),p)
 			(EArray ((EArrayDecl [e],p),(EConst (Int (string_of_int (!index))),p)),p)
 		) el in
 		) el in
 		let elt, _ = unify_call_params ctx2 (Some (TInst(mclass,[]),mfield)) constants (List.map fst eargs) t_dynamic p false in
 		let elt, _ = unify_call_params ctx2 (Some (TInst(mclass,[]),mfield)) constants (List.map fst eargs) t_dynamic p false in
+		List.iter (fun f -> f()) (!todo);
 		List.map2 (fun (_,ise) e ->
 		List.map2 (fun (_,ise) e ->
 			let e, et = (match e.eexpr with
 			let e, et = (match e.eexpr with
 				(* get back our index and real expression *)
 				(* get back our index and real expression *)