Kaynağa Gözat

added haxe.macro.Context.parse

Nicolas Cannasse 15 yıl önce
ebeveyn
işleme
6763cee123
5 değiştirilmiş dosya ile 37 ekleme ve 3 silme
  1. 9 0
      interp.ml
  2. 1 2
      parser.ml
  3. 7 0
      std/haxe/macro/Context.hx
  4. 2 1
      typeload.ml
  5. 18 0
      typer.ml

+ 9 - 0
interp.ml

@@ -86,6 +86,7 @@ type locals = (string, value ref) PMap.t
 type extern_api = {
 	pos : Ast.pos;
 	get_type : string -> Type.t option;
+	parse_string : string -> Ast.pos -> Ast.expr;
 }
 
 type context = {
@@ -129,8 +130,10 @@ exception Return of value
 
 let get_ctx_ref = ref (fun() -> assert false)
 let encode_type_ref = ref (fun t -> assert false)
+let encode_expr_ref = ref (fun e -> assert false)
 let get_ctx() = (!get_ctx_ref)()
 let encode_type (t:Type.t) : value = (!encode_type_ref) t
+let encode_expr (e:Ast.expr) : value = (!encode_expr_ref) e
 
 let to_int f = int_of_float (mod_float f 2147483648.0)
 
@@ -1530,6 +1533,11 @@ let macro_lib =
 				| Some t -> encode_type t)
 			| _ -> error()
 		);
+		"parse", Fun2 (fun s p ->
+			match s, p with
+			| VString s, VAbstract (APos p) -> encode_expr ((get_ctx()).curapi.parse_string s p)
+			| _ -> error()
+		);
 	]
 
 (* ---------------------------------------------------------------------- *)
@@ -2791,3 +2799,4 @@ let decode_expr v =
 	in
 	loop v
 
+;;encode_expr_ref := encode_expr;;

+ 1 - 2
parser.ml

@@ -681,13 +681,12 @@ and toplevel_expr s =
 	with
 		Display e -> e
 
-let parse ctx code file =
+let parse ctx code =
 	let old = Lexer.save() in
 	let old_cache = !cache in
 	let mstack = ref [] in
 	cache := DynArray.create();
 	doc := None;
-	Lexer.init file;
 	Lexer.skip_header code;
 	let rec next_token() = process_token (Lexer.token code)
 

+ 7 - 0
std/haxe/macro/Context.hx

@@ -84,6 +84,13 @@ class Context {
 		return load("get_type", 1)(untyped name.__s);
 	}
 
+	/**
+		Parse an expression.
+	**/
+	public static function parse( expr : String, pos : Position ) : Expr {
+		return load("parse", 2)(untyped expr.__s, pos);
+	}
+
 	static function load( f, nargs ) : Dynamic {
 		#if macro
 		return neko.Lib.load("macro", f, nargs);

+ 2 - 1
typeload.ml

@@ -1186,7 +1186,8 @@ let parse_module ctx m p =
 	let file = Common.find_file ctx.com file in
 	let ch = (try open_in_bin file with _ -> error ("Could not open " ^ file) p) in
 	let t = Common.timer "parsing" in
-	let pack , decls = (try Parser.parse ctx.com (Lexing.from_channel ch) file with e -> close_in ch; t(); raise e) in
+	Lexer.init file;
+	let pack , decls = (try Parser.parse ctx.com (Lexing.from_channel ch) with e -> close_in ch; t(); raise e) in
 	t();
 	close_in ch;
 	if ctx.com.verbose then print_endline ("Parsed " ^ file);

+ 18 - 0
typer.ml

@@ -1816,6 +1816,24 @@ let make_macro_api ctx p =
 			with Error (Module_not_found _,p2) when p == p2 ->
 				None
 		);
+		Interp.parse_string = (fun s p ->
+			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
+			let s = head ^ s ^ "; }}" in
+			let old = Lexer.save() in
+			Lexer.init p.pfile;
+			let _, decls = try 
+				Parser.parse ctx.com (Lexing.from_string s)
+			with Parser.Error (e,_) ->
+				failwith (Parser.error_msg e)
+			| Lexer.Error (e,_) ->
+				failwith (Lexer.error_msg e)
+			in
+			Lexer.restore old;
+			match decls with
+			| [EClass { d_data = [FFun ("main",_,_,_,_,{ f_expr = e}),_] },_] -> e
+			| _ -> assert false
+		);
 	}
 
 let type_macro ctx cpath f el p =