Selaa lähdekoodia

change @:build again (returns Array<Field>, added haxe.macro.Context.getBuildFields())

Nicolas Cannasse 14 vuotta sitten
vanhempi
commit
6b19423132
6 muutettua tiedostoa jossa 57 lisäystä ja 21 poistoa
  1. 4 0
      interp.ml
  2. 7 0
      std/haxe/macro/Context.hx
  3. 3 3
      std/neko/db/SpodData.hx
  4. 6 1
      typecore.ml
  5. 11 8
      typeload.ml
  6. 26 9
      typer.ml

+ 4 - 0
interp.ml

@@ -99,6 +99,7 @@ type extern_api = {
 	meta_patch : string -> string -> string option -> bool -> unit;
 	meta_patch : string -> string -> string option -> bool -> unit;
 	set_js_generator : (value -> unit) -> unit;
 	set_js_generator : (value -> unit) -> unit;
 	get_cur_class : unit -> tclass option;
 	get_cur_class : unit -> tclass option;
+	get_build_fields : unit -> value;
 }
 }
 
 
 type context = {
 type context = {
@@ -1730,6 +1731,9 @@ let macro_lib =
 			in
 			in
 			encode_type (match once with VNull | VBool false -> follow t | VBool true -> follow_once t | _ -> error())
 			encode_type (match once with VNull | VBool false -> follow t | VBool true -> follow_once t | _ -> error())
 		);
 		);
+		"build_fields", Fun0 (fun() ->
+			(get_ctx()).curapi.get_build_fields()
+		);
 	]
 	]
 
 
 (* ---------------------------------------------------------------------- *)
 (* ---------------------------------------------------------------------- *)

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

@@ -160,6 +160,13 @@ class Context {
 	public static function addResource( name : String, data : haxe.io.Bytes ) {
 	public static function addResource( name : String, data : haxe.io.Bytes ) {
 		return load("add_resource",2)(untyped name.__s,data.getData());
 		return load("add_resource",2)(untyped name.__s,data.getData());
 	}
 	}
+	
+	/**
+		Returns the list of fields for the current type inside the build macro.
+	**/
+	public static function getBuildFields() : Array<Field> {
+		return load("build_fields", 0)();
+	}
 
 
 	static function load( f, nargs ) : Dynamic {
 	static function load( f, nargs ) : Dynamic {
 		#if macro
 		#if macro

+ 3 - 3
std/neko/db/SpodData.hx

@@ -827,8 +827,8 @@ class SpodData {
 	#if macro
 	#if macro
 	static var RTTI = false;
 	static var RTTI = false;
 
 
-	public static function addRtti( fields ) {
-		if( RTTI ) return fields;
+	public static function addRtti() : Array<Field> {
+		if( RTTI ) return null;
 		RTTI = true;
 		RTTI = true;
 		Context.getType("neko.db.SpodInfos");
 		Context.getType("neko.db.SpodInfos");
 		Context.onGenerate(function(types) {
 		Context.onGenerate(function(types) {
@@ -853,7 +853,7 @@ class SpodData {
 				default:
 				default:
 				}
 				}
 		});
 		});
-		return fields;
+		return null;
 	}
 	}
 
 
 	static function getManagerInfos( t : haxe.macro.Type ) {
 	static function getManagerInfos( t : haxe.macro.Type ) {

+ 6 - 1
typecore.ml

@@ -25,6 +25,10 @@ type type_patch = {
 	mutable tp_meta : Ast.metadata;
 	mutable tp_meta : Ast.metadata;
 }
 }
 
 
+type macro_mode =
+	| MExpr
+	| MBuild
+
 type typer_globals = {
 type typer_globals = {
 	types_module : (path, path) Hashtbl.t;
 	types_module : (path, path) Hashtbl.t;
 	modules : (path , module_def) Hashtbl.t;
 	modules : (path , module_def) Hashtbl.t;
@@ -36,10 +40,11 @@ type typer_globals = {
 	mutable std : module_def;
 	mutable std : module_def;
 	mutable hook_generate : (unit -> unit) list;
 	mutable hook_generate : (unit -> unit) list;
 	type_patches : (path, (string * bool, type_patch) Hashtbl.t * type_patch) Hashtbl.t;
 	type_patches : (path, (string * bool, type_patch) Hashtbl.t * type_patch) Hashtbl.t;
+	mutable get_build_fields : unit -> Ast.class_field list;
 	(* api *)
 	(* api *)
 	do_inherit : typer -> Type.tclass -> Ast.pos -> Ast.class_flag -> bool;
 	do_inherit : typer -> Type.tclass -> Ast.pos -> Ast.class_flag -> bool;
 	do_create : Common.context -> typer;
 	do_create : Common.context -> typer;
-	do_macro : typer -> path -> string -> Ast.expr list -> Ast.pos -> Ast.expr option;
+	do_macro : typer -> macro_mode -> path -> string -> Ast.expr list -> Ast.pos -> Ast.expr option;
 	do_load_module : typer -> path -> pos -> module_def;
 	do_load_module : typer -> path -> pos -> module_def;
 	do_optimize : typer -> texpr -> texpr;
 	do_optimize : typer -> texpr -> texpr;
 	do_build_instance : typer -> module_type -> pos -> ((string * t) list * path * (t list -> t));
 	do_build_instance : typer -> module_type -> pos -> ((string * t) list * path * (t list -> t));

+ 11 - 8
typeload.ml

@@ -37,12 +37,12 @@ let type_static_var ctx t e p =
 	| TType ({ t_path = ([],"UInt") },[]) -> { e with etype = t }
 	| TType ({ t_path = ([],"UInt") },[]) -> { e with etype = t }
 	| _ -> e
 	| _ -> e
 
 
-let apply_macro ctx path el p =
+let apply_macro ctx mode path el p =
 	let cpath, meth = (match List.rev (ExtString.String.nsplit path ".") with
 	let cpath, meth = (match List.rev (ExtString.String.nsplit path ".") with
 		| meth :: name :: pack -> (List.rev pack,name), meth
 		| meth :: name :: pack -> (List.rev pack,name), meth
 		| _ -> error "Invalid macro path" p
 		| _ -> error "Invalid macro path" p
 	) in
 	) in
-	ctx.g.do_macro ctx cpath meth el p
+	ctx.g.do_macro ctx mode cpath meth el p
 
 
 (** since load_type_def and load_instance are used in PASS2, they should not access the structure of a type **)
 (** since load_type_def and load_instance are used in PASS2, they should not access the structure of a type **)
 
 
@@ -682,7 +682,11 @@ let build_module_def ctx meta fvars fbuild =
 			in
 			in
 			let s = String.concat "." (List.rev (getpath epath)) in
 			let s = String.concat "." (List.rev (getpath epath)) in
 			if ctx.in_macro then error "You cannot used :build inside a macro : make sure that your enum is not used in macro" p;
 			if ctx.in_macro then error "You cannot used :build inside a macro : make sure that your enum is not used in macro" p;
-			(match apply_macro ctx s (fvars() :: el) p with
+			let old = ctx.g.get_build_fields in
+			ctx.g.get_build_fields <- fvars;
+			let r = try apply_macro ctx MBuild s el p with e -> ctx.g.get_build_fields <- old; raise e in
+			ctx.g.get_build_fields <- old;
+			(match r with
 			| None -> error "Build failure" p
 			| None -> error "Build failure" p
 			| Some e -> fbuild e; loop l)
 			| Some e -> fbuild e; loop l)
 		| _ :: l -> loop l
 		| _ :: l -> loop l
@@ -700,7 +704,7 @@ let init_class ctx c p herits fields =
 	c.cl_interface <- List.mem HInterface herits;
 	c.cl_interface <- List.mem HInterface herits;
 	set_heritance ctx c herits p;
 	set_heritance ctx c herits p;
 	let fields = ref fields in
 	let fields = ref fields in
-	let get_fields() = (EVars ["fields",Some (CTAnonymous !fields),None],p) in
+	let get_fields() = !fields in
 	build_module_def { ctx with curclass = c } c.cl_meta get_fields (fun (e,p) ->
 	build_module_def { ctx with curclass = c } c.cl_meta get_fields (fun (e,p) ->
 		match e with
 		match e with
 		| EVars [_,Some (CTAnonymous f),None] -> fields := f
 		| EVars [_,Some (CTAnonymous f),None] -> fields := f
@@ -810,7 +814,7 @@ let init_class ctx c p herits fields =
 			if display_file && (cp.pmin = 0 || (p.pmin <= cp.pmin && p.pmax >= cp.pmax)) then begin
 			if display_file && (cp.pmin = 0 || (p.pmin <= cp.pmin && p.pmax >= cp.pmax)) then begin
 				if macro && not ctx.in_macro then
 				if macro && not ctx.in_macro then
 					(* force macro system loading of this class in order to get completion *)
 					(* force macro system loading of this class in order to get completion *)
-					(fun() -> ignore(ctx.g.do_macro ctx c.cl_path cf.cf_name [] p))
+					(fun() -> ignore(ctx.g.do_macro ctx MExpr c.cl_path cf.cf_name [] p))
 				else begin
 				else begin
 					cf.cf_type <- TLazy r;
 					cf.cf_type <- TLazy r;
 					(fun() -> ignore((!r)()))
 					(fun() -> ignore((!r)()))
@@ -1340,7 +1344,7 @@ let type_module ctx m tdecls loadp =
 			let ctx = { ctx with type_params = e.e_types } in
 			let ctx = { ctx with type_params = e.e_types } in
 			let constructs = ref d.d_data in
 			let constructs = ref d.d_data in
 			let get_constructs() =
 			let get_constructs() =
-				let cl = List.map (fun (c,doc,meta,pl,p) ->
+				List.map (fun (c,doc,meta,pl,p) ->
 					{
 					{
 						cff_name = c;
 						cff_name = c;
 						cff_doc = doc;
 						cff_doc = doc;
@@ -1351,8 +1355,7 @@ let type_module ctx m tdecls loadp =
 							| [] -> FVar (None,None)
 							| [] -> FVar (None,None)
 							| _ -> FFun { f_params = []; f_type = None; f_expr = None; f_args = List.map (fun (n,o,t) -> n,o,Some t,None) pl });
 							| _ -> FFun { f_params = []; f_type = None; f_expr = None; f_args = List.map (fun (n,o,t) -> n,o,Some t,None) pl });
 					}
 					}
-				) (!constructs) in
-				(EVars ["constructs",Some (CTAnonymous cl),None],p) 
+				) (!constructs)
 			in
 			in
 			build_module_def ctx e.e_meta get_constructs (fun (e,p) ->
 			build_module_def ctx e.e_meta get_constructs (fun (e,p) ->
 				match e with
 				match e with

+ 26 - 9
typer.ml

@@ -1697,7 +1697,7 @@ and type_call ctx e el p =
 							| EConst (Ident f | Type f) -> if f <> ef.cf_name then assert false; (EConst (Ident "this"),snd e)
 							| EConst (Ident f | Type f) -> if f <> ef.cf_name then assert false; (EConst (Ident "this"),snd e)
 							| _ -> error "Unsupported" (snd e)
 							| _ -> error "Unsupported" (snd e)
 						) in
 						) in
-						(match ctx.g.do_macro ctx c.cl_path ef.cf_name (e :: el) p with
+						(match ctx.g.do_macro ctx MExpr c.cl_path ef.cf_name (e :: el) p with
 						| None -> type_expr ctx (EConst (Ident "null"),p)
 						| None -> type_expr ctx (EConst (Ident "null"),p)
 						| Some e -> type_expr ctx e)
 						| Some e -> type_expr ctx e)
 					| _ -> assert false)
 					| _ -> assert false)
@@ -1712,7 +1712,7 @@ and type_call ctx e el p =
 		| AKMacro (ethis,f) ->
 		| AKMacro (ethis,f) ->
 			(match ethis.eexpr with
 			(match ethis.eexpr with
 			| TTypeExpr (TClassDecl c) ->
 			| TTypeExpr (TClassDecl c) ->
-				(match ctx.g.do_macro ctx c.cl_path f.cf_name el p with
+				(match ctx.g.do_macro ctx MExpr c.cl_path f.cf_name el p with
 				| None -> type_expr ctx (EConst (Ident "null"),p)
 				| None -> type_expr ctx (EConst (Ident "null"),p)
 				| Some e -> type_expr ctx e)
 				| Some e -> type_expr ctx e)
 			| _ ->
 			| _ ->
@@ -1721,7 +1721,7 @@ and type_call ctx e el p =
 				| TInst (c,_) ->					
 				| TInst (c,_) ->					
 					let rec loop c =
 					let rec loop c =
 						if PMap.mem f.cf_name c.cl_fields then
 						if PMap.mem f.cf_name c.cl_fields then
-							match ctx.g.do_macro ctx c.cl_path f.cf_name (Interp.make_ast ethis :: el) p with
+							match ctx.g.do_macro ctx MExpr c.cl_path f.cf_name (Interp.make_ast ethis :: el) p with
 							| None -> type_expr ctx (EConst (Ident "null"),p)
 							| None -> type_expr ctx (EConst (Ident "null"),p)
 							| Some e -> type_expr ctx e
 							| Some e -> type_expr ctx e
 						else
 						else
@@ -2049,6 +2049,9 @@ let make_macro_api ctx p =
 			);
 			);
 		);
 		);
 		Interp.get_cur_class = (fun() -> Some ctx.curclass);
 		Interp.get_cur_class = (fun() -> Some ctx.curclass);
+		Interp.get_build_fields = (fun() -> 
+			Interp.enc_array (List.map Interp.encode_field (ctx.g.get_build_fields()))
+		)
 	}
 	}
 
 
 let load_macro ctx cpath f p =
 let load_macro ctx cpath f p =
@@ -2098,7 +2101,7 @@ let load_macro ctx cpath f p =
 		| TInst (c,_) -> (try PMap.find f c.cl_statics with Not_found -> error ("Method " ^ f ^ " not found on class " ^ s_type_path cpath) p)
 		| TInst (c,_) -> (try PMap.find f c.cl_statics with Not_found -> error ("Method " ^ f ^ " not found on class " ^ s_type_path cpath) p)
 		| _ -> error "Macro should be called on a class" p
 		| _ -> error "Macro should be called on a class" p
 	) in
 	) in
-	let meth = (match follow meth.cf_type with TFun (args,ret) -> args,ret | _ -> error "Macro call should be a method" p) in
+	let meth = (match follow meth.cf_type with TFun (args,ret) -> args,ret,meth.cf_pos | _ -> error "Macro call should be a method" p) in
 	let in_macro = ctx.in_macro in
 	let in_macro = ctx.in_macro in
 	if not in_macro then begin
 	if not in_macro then begin
 		finalize ctx2;
 		finalize ctx2;
@@ -2114,11 +2117,18 @@ let load_macro ctx cpath f p =
 	in
 	in
 	ctx2, meth, call
 	ctx2, meth, call
 
 
-let type_macro ctx cpath f (el:Ast.expr list) p =
-	let ctx2, (margs,mret), call_macro = load_macro ctx cpath f p in
+let type_macro ctx mode cpath f (el:Ast.expr list) p =
+	let ctx2, (margs,mret,mpos), call_macro = load_macro ctx cpath f p in
 	let ctexpr = { tpackage = ["haxe";"macro"]; tname = "Expr"; tparams = []; tsub = None } in
 	let ctexpr = { tpackage = ["haxe";"macro"]; tname = "Expr"; tparams = []; tsub = None } in
 	let expr = Typeload.load_instance ctx2 ctexpr p false in
 	let expr = Typeload.load_instance ctx2 ctexpr p false in
-	unify ctx2 mret expr p;
+	let ctfields = { tpackage = []; tname = "Array"; tparams = [TPType (CTPath { tpackage = ["haxe";"macro"]; tname = "Expr"; tparams = []; tsub = Some "Field" })]; tsub = None } in
+	(match mode with
+	| MExpr ->
+		unify ctx2 mret expr mpos;
+	| MBuild _ ->
+		let tfields = Typeload.load_instance ctx2 ctfields p false in
+		unify ctx2 mret tfields mpos
+	);
 	let args = (try
 	let args = (try
 		(*
 		(*
 			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
@@ -2169,7 +2179,13 @@ let type_macro ctx cpath f (el:Ast.expr list) p =
 	let call() =
 	let call() =
 		match call_macro args with
 		match call_macro args with
 		| None -> None
 		| None -> None
-		| Some v -> Some (try Interp.decode_expr v with Interp.Invalid_expr -> error "The macro didn't return a valid expression" p)
+		| Some v -> 
+			try
+				Some (match mode with
+				| MExpr -> Interp.decode_expr v
+				| MBuild _ -> (EVars ["fields",Some (CTAnonymous (match v with Interp.VNull -> ctx.g.get_build_fields() | _ -> List.map Interp.decode_field (Interp.dec_array v))),None],p))
+			with Interp.Invalid_expr ->
+				error "The macro didn't return a valid result" p
 	in
 	in
 	let e = (if ctx.in_macro then begin
 	let e = (if ctx.in_macro then begin
 		(*
 		(*
@@ -2199,7 +2215,7 @@ let type_macro ctx cpath f (el:Ast.expr list) p =
 	e
 	e
 
 
 let call_macro ctx path meth args p =
 let call_macro ctx path meth args p =
-	let ctx2, (margs,_), call = load_macro ctx path meth p in
+	let ctx2, (margs,_,_), call = load_macro ctx path meth p in
 	let el = unify_call_params ctx2 (Some (meth,[])) args margs p false in
 	let el = unify_call_params ctx2 (Some (meth,[])) args margs p false in
 	call (List.map (fun e -> try Interp.make_const e with Exit -> error "Parameter should be a constant" e.epos) el)
 	call (List.map (fun e -> try Interp.make_const e with Exit -> error "Parameter should be a constant" e.epos) el)
 
 
@@ -2244,6 +2260,7 @@ let rec create com =
 			delayed = [];
 			delayed = [];
 			doinline = not (Common.defined com "no_inline" || com.display);
 			doinline = not (Common.defined com "no_inline" || com.display);
 			hook_generate = [];
 			hook_generate = [];
+			get_build_fields = (fun() -> []);
 			std = empty;
 			std = empty;
 			do_inherit = Codegen.on_inherit;
 			do_inherit = Codegen.on_inherit;
 			do_create = create;
 			do_create = create;