Quellcode durchsuchen

make the difference between "parse" and "parseInlineString" (substring error reporting + completion support)

Nicolas Cannasse vor 13 Jahren
Ursprung
Commit
0c71f57905
4 geänderte Dateien mit 92 neuen und 17 gelöschten Zeilen
  1. 64 0
      ast.ml
  2. 4 4
      interp.ml
  3. 9 2
      std/haxe/macro/Context.hx
  4. 15 11
      typer.ml

+ 64 - 0
ast.ml

@@ -443,3 +443,67 @@ let unescape s =
 	in
 	loop false 0;
 	Buffer.contents b
+
+
+let map_expr loop (e,p) =
+	let opt f o =
+		match o with None -> None | Some v -> Some (f v)
+	in
+	let rec tparam = function
+		| TPType t -> TPType (ctype t)
+		| TPExpr e -> TPExpr (loop e)
+	and cfield f = 
+		{ f with cff_kind = (match f.cff_kind with
+			| FVar (t,e) -> FVar (opt ctype t, opt loop e)
+			| FFun f -> FFun (func f)
+			| FProp (get,set,t,e) -> FProp (get,set,ctype t,opt loop e))
+		}
+	and ctype = function
+		| CTPath t -> CTPath (tpath t)
+		| CTFunction (cl,c) -> CTFunction (List.map ctype cl, ctype c)
+		| CTAnonymous fl -> CTAnonymous (List.map cfield fl)
+		| CTParent t -> CTParent (ctype t)
+		| CTExtend (t,fl) -> CTExtend (tpath t, List.map cfield fl)
+		| CTOptional t -> CTOptional (ctype t)
+	and func f =
+		{	
+			f_params = List.map (fun (n,tl) -> n,List.map ctype tl)  f.f_params;
+			f_args = List.map (fun (n,o,t,e) -> n,o,opt ctype t,opt loop e) f.f_args;
+			f_type = opt ctype f.f_type;
+			f_expr = opt loop f.f_expr;
+		}
+	and tpath t = { t with tparams = List.map tparam t.tparams }
+	in
+	let e = (match e with
+	| EConst _ -> e
+	| EArray (e1,e2) -> EArray (loop e1, loop e2)
+	| EBinop (op,e1,e2) -> EBinop (op,loop e1, loop e2)
+	| EField (e,f) -> EField (loop e, f)
+	| EType (e,f) -> EType (loop e, f)
+	| EParenthesis e -> EParenthesis (loop e)
+	| EObjectDecl fl -> EObjectDecl (List.map (fun (f,e) -> f,loop e) fl)
+	| EArrayDecl el -> EArrayDecl (List.map loop el)
+	| ECall (e,el) -> ECall (loop e, List.map loop el)
+	| ENew (t,el) -> ENew (tpath t,List.map loop el)
+	| EUnop (op,f,e) -> EUnop (op,f,loop e)
+	| EVars vl -> EVars (List.map (fun (n,t,eo) -> n,opt ctype t,opt loop eo) vl)
+	| EFunction (n,f) -> EFunction (n,func f)
+	| EBlock el -> EBlock (List.map loop el)
+	| EFor (e1,e2) -> EFor (loop e1, loop e2)
+	| EIn (e1,e2) -> EIn (loop e1, loop e2)
+	| EIf (e,e1,e2) -> EIf (loop e, loop e1, opt loop e2)
+	| EWhile (econd,e,f) -> EWhile (loop econd, loop e, f)
+	| ESwitch (e,cases,def) -> ESwitch (loop e, List.map (fun (el,e) -> List.map loop el, loop e) cases, opt loop def)
+	| ETry (e, catches) -> ETry (loop e, List.map (fun (n,t,e) -> n,ctype t,loop e) catches)
+	| EReturn e -> EReturn (opt loop e)
+	| EBreak -> EBreak
+	| EContinue -> EContinue
+	| EUntyped e -> EUntyped (loop e)
+	| EThrow e -> EThrow (loop e)
+	| ECast (e,t) -> ECast (loop e,opt ctype t)
+	| EDisplay (e,f) -> EDisplay (loop e,f)
+	| EDisplayNew t -> EDisplayNew (tpath t)
+	| ETernary (e1,e2,e3) -> ETernary (loop e1,loop e2,loop e3)
+	| ECheckType (e,t) -> ECheckType (loop e, ctype t)
+	) in
+	(e,p)

+ 4 - 4
interp.ml

@@ -92,7 +92,7 @@ type extern_api = {
 	get_type : string -> Type.t option;
 	get_module : string -> Type.t list;
 	on_generate : (Type.t list -> unit) -> unit;
-	parse_string : string -> Ast.pos -> Ast.expr;
+	parse_string : string -> Ast.pos -> bool -> Ast.expr;
 	typeof : Ast.expr -> Type.t;
 	type_patch : string -> string -> bool -> string option -> unit;
 	meta_patch : string -> string -> string option -> bool -> unit;
@@ -1752,9 +1752,9 @@ let macro_lib =
 				VNull
 			| _ -> error()
 		);
-		"parse", Fun2 (fun s p ->
-			match s, p with
-			| VString s, VAbstract (APos p) -> encode_expr ((get_ctx()).curapi.parse_string s p)
+		"parse", Fun3 (fun s p b ->
+			match s, p, b with
+			| VString s, VAbstract (APos p), VBool b -> encode_expr ((get_ctx()).curapi.parse_string s p b)
 			| _ -> error()
 		);
 		"make_expr", Fun2 (fun v p ->

+ 9 - 2
std/haxe/macro/Context.hx

@@ -113,10 +113,17 @@ class Context {
 	}
 
 	/**
-		Parse an expression.
+		Parse a constructed string into the corresponding expression.
 	**/
 	public static function parse( expr : String, pos : Position ) : Expr {
-		return load("parse", 2)(untyped expr.__s, pos);
+		return load("parse", 3)(untyped expr.__s, pos, false);
+	}
+
+	/**
+		Parse a string contained into source code into the corresponding expression. Errors positions are reported within this string
+	**/
+	public static function parseInlineString( expr : String, pos : Position ) : Expr {
+		return load("parse", 3)(untyped expr.__s, pos, true);
 	}
 
 	/**

+ 15 - 11
typer.ml

@@ -2188,24 +2188,27 @@ let get_type_patch ctx t sub =
 			Hashtbl.add h k tp;
 			tp
 
-let parse_string ctx s p =
+let parse_string ctx s p inlined =
 	let old = Lexer.save() in
 	let old_file = (try Some (Hashtbl.find Lexer.all_files p.pfile) with Not_found -> None) in
+	let old_display = !Parser.resume_display in
 	let restore() =
 		(match old_file with
 		| None -> ()
 		| Some f -> Hashtbl.replace Lexer.all_files p.pfile f);
+		if not inlined then Parser.resume_display := old_display;
 		Lexer.restore old;
 	in
 	Lexer.init p.pfile;
+	if not inlined then Parser.resume_display := null_pos;
 	let _, decls = try
 		Parser.parse ctx.com (Lexing.from_string s)
-	with Parser.Error (e,p) ->
+	with Parser.Error (e,pe) ->
 		restore();
-		error (Parser.error_msg e) p
-	| Lexer.Error (e,p) ->
+		error (Parser.error_msg e) (if inlined then pe else p)
+	| Lexer.Error (e,pe) ->
 		restore();
-		error (Lexer.error_msg e) p
+		error (Lexer.error_msg e) (if inlined then pe else p)
 	in
 	restore();
 	match decls with
@@ -2268,12 +2271,13 @@ let make_macro_api ctx p =
 				t()
 			)
 		);
-		Interp.parse_string = (fun s p ->
+		Interp.parse_string = (fun s p inl ->
 			typing_timer ctx (fun() ->
 				let head = "class X{static function main() " in
 				let head = (if p.pmin > String.length head then head ^ String.make (p.pmin - String.length head) ' ' else head) in
-				match parse_string ctx (head ^ s ^ "}") p with
-				| EClass { d_data = [{ cff_name = "main"; cff_kind = FFun { f_expr = Some e } }]} -> e
+				let rec loop e = let e = Ast.map_expr loop e in (fst e,p) in
+				match parse_string ctx (head ^ s ^ "}") p inl with
+				| EClass { d_data = [{ cff_name = "main"; cff_kind = FFun { f_expr = Some e } }]} -> if inl then e else loop e
 				| _ -> assert false
 			)
 		);
@@ -2283,7 +2287,7 @@ let make_macro_api ctx p =
 		Interp.type_patch = (fun t f s v ->
 			typing_timer ctx (fun() ->
 				let v = (match v with None -> None | Some s ->
-					match parse_string ctx ("typedef T = " ^ s) null_pos with
+					match parse_string ctx ("typedef T = " ^ s) null_pos false with
 					| ETypedef { d_data = ct } -> Some ct
 					| _ -> assert false
 				) in
@@ -2294,7 +2298,7 @@ let make_macro_api ctx p =
 			);
 		);
 		Interp.meta_patch = (fun m t f s ->
-			let m = (match parse_string ctx (m ^ " typedef T = T") null_pos with
+			let m = (match parse_string ctx (m ^ " typedef T = T") null_pos false with
 				| ETypedef t -> t.d_meta
 				| _ -> assert false
 			) in
@@ -2603,7 +2607,7 @@ let call_macro ctx path meth args p =
 let call_init_macro ctx e =
 	let p = { pfile = "--macro"; pmin = 0; pmax = 0 } in
 	let api = make_macro_api ctx p in
-	let e = api.Interp.parse_string e p in
+	let e = api.Interp.parse_string e p false in
 	match fst e with
 	| ECall (e,args) ->
 		let rec loop e =