Sfoglia il codice sorgente

added metadata api

Nicolas Cannasse 15 anni fa
parent
commit
a7ef7105b5
13 ha cambiato i file con 211 aggiunte e 14 eliminazioni
  1. 52 6
      codegen.ml
  2. 1 0
      doc/CHANGES.txt
  3. 7 1
      genjs.ml
  4. 5 2
      genneko.ml
  5. 7 0
      genswf8.ml
  6. 23 4
      genswf9.ml
  7. 44 0
      std/haxe/rtti/Meta.hx
  8. 1 1
      tests/unit/RunCpp.hx
  9. 1 0
      tests/unit/Test.hx
  10. 62 0
      tests/unit/TestMeta.hx
  11. 1 0
      tests/unit/unit.hxml
  12. 2 0
      tests/unit/unit.hxp
  13. 5 0
      typeload.ml

+ 52 - 6
codegen.ml

@@ -260,6 +260,43 @@ let extend_xml_proxy ctx c t file p =
 		| Xml.Error e -> error ("XML error " ^ Xml.error e) p
 		| Xml.File_not_found f -> error ("XML File not found : " ^ f) p
 
+(* -------------------------------------------------------------------------- *)
+(* BUILD META DATA OBJECT *)
+
+let build_metadata com t =
+	let api = com.type_api in
+	let p, meta, fields, statics = (match t with
+		| TClassDecl c ->
+			let fields = List.map (fun f -> f.cf_name,f.cf_meta) (c.cl_ordered_fields @ (match c.cl_constructor with None -> [] | Some f -> [{ f with cf_name = "_" }])) in
+			let statics =  List.map (fun f -> f.cf_name,f.cf_meta) c.cl_ordered_statics in
+			(c.cl_pos, ["",c.cl_meta],fields,statics)
+		| TEnumDecl e ->
+			(e.e_pos, ["",e.e_meta],List.map (fun n -> n, (PMap.find n e.e_constrs).ef_meta) e.e_names, [])
+		| TTypeDecl t ->
+			(t.t_pos, ["",t.t_meta],(match follow t.t_type with TAnon a -> PMap.fold (fun f acc -> (f.cf_name,f.cf_meta) :: acc) a.a_fields [] | _ -> []),[])
+	) in
+	let filter l = 
+		let l = List.map (fun (n,ml) -> n, List.filter (fun (m,_) -> m.[0] <> ':') ml) l in
+		List.filter (fun (_,ml) -> ml <> []) l
+	in
+	let meta, fields, statics = filter meta, filter fields, filter statics in
+	let make_meta_field ml =
+		mk (TObjectDecl (List.map (fun (f,l) -> 
+			f, mk (match l with [] -> TConst TNull | _ -> TArrayDecl l) (api.tarray t_dynamic) p
+		) ml)) (api.tarray t_dynamic) p
+	in
+	let make_meta l =
+		mk (TObjectDecl (List.map (fun (f,ml) -> f,make_meta_field ml) l)) t_dynamic p
+	in
+	if meta = [] && fields = [] && statics = [] then
+		None
+	else
+		let meta_obj = [] in
+		let meta_obj = (if fields = [] then meta_obj else ("fields",make_meta fields) :: meta_obj) in		
+		let meta_obj = (if statics = [] then meta_obj else ("statics",make_meta statics) :: meta_obj) in
+		let meta_obj = (try ("obj", make_meta_field (List.assoc "" meta)) :: meta_obj with Not_found -> meta_obj) in
+		Some (mk (TObjectDecl meta_obj) t_dynamic p)		
+
 (* -------------------------------------------------------------------------- *)
 (* API EVENTS *)
 
@@ -314,12 +351,21 @@ let rec has_rtti c =
 
 let on_generate ctx t =
 	match t with
-	| TClassDecl c when has_rtti c && not (PMap.mem "__rtti" c.cl_statics) ->
-		let f = mk_field "__rtti" ctx.api.tstring in
-		let str = Genxml.gen_type_string ctx.com t in
-		f.cf_expr <- Some (mk (TConst (TString str)) f.cf_type c.cl_pos);
-		c.cl_ordered_statics <- f :: c.cl_ordered_statics;
-		c.cl_statics <- PMap.add f.cf_name f c.cl_statics;
+	| TClassDecl c ->
+		if has_rtti c && not (PMap.mem "__rtti" c.cl_statics) then begin
+			let f = mk_field "__rtti" ctx.api.tstring in
+			let str = Genxml.gen_type_string ctx.com t in
+			f.cf_expr <- Some (mk (TConst (TString str)) f.cf_type c.cl_pos);
+			c.cl_ordered_statics <- f :: c.cl_ordered_statics;
+			c.cl_statics <- PMap.add f.cf_name f c.cl_statics;
+		end;
+		(match build_metadata ctx.com t with
+		| None -> ()
+		| Some e -> 
+			let f = mk_field "__meta__" t_dynamic in
+			f.cf_expr <- Some e;
+			c.cl_ordered_statics <- f :: c.cl_ordered_statics;
+			c.cl_statics <- PMap.add f.cf_name f c.cl_statics);
 	| _ ->
 		()
 

+ 1 - 0
doc/CHANGES.txt

@@ -31,6 +31,7 @@
 	neko : rewrote Array class using neko.NativeArray
 	all : core classes implementation are now in std/(platform)/_std
 	all : added @:final support
+	all : added haxe.rtti.Meta
 
 2010-01-09: 2.05
 	js : added js.Scroll

+ 7 - 1
genjs.ml

@@ -688,7 +688,13 @@ let generate_enum ctx e =
 			print ctx "%s%s.__enum__ = %s" p (field f.ef_name) p;
 		);
 		newline ctx
-	) e.e_constrs
+	) e.e_constrs;
+	match Codegen.build_metadata ctx.com (TEnumDecl e) with
+	| None -> ()
+	| Some e ->
+		print ctx "%s.__meta__ = " p;
+		gen_expr ctx e;
+		newline ctx
 
 let generate_static ctx (c,f,e) =
 	print ctx "%s%s = " (s_path ctx c.cl_path) (field f);

+ 5 - 2
genneko.ml

@@ -603,9 +603,12 @@ let gen_enum ctx e =
 			"__string" , ident p "@enum_to_string"
 		],p)),p) ::
 		pmap_list (gen_enum_constr ctx path) e.e_constrs @
-		match e.e_path with
+		(match e.e_path with
 		| [] , name -> [EBinop ("=",field p (ident p "@classes") name,ident p name),p]
-		| _ -> []
+		| _ -> []) @
+		(match Codegen.build_metadata ctx.com (TEnumDecl e) with
+		| None -> []
+		| Some e -> [EBinop ("=",field p path "__meta__", gen_expr ctx e),p])
 	),p)
 
 let gen_type ctx t acc =

+ 7 - 0
genswf8.ml

@@ -1417,6 +1417,13 @@ let gen_type_def ctx t =
 		List.iter (fun s -> push ctx [VStr (s,false)]) (List.rev e.e_names);
 		init_array ctx (List.length e.e_names);
 		write ctx AObjSet;
+		(match Codegen.build_metadata ctx.com t with
+		| None -> ()
+		| Some e ->
+			push ctx [VReg 0; VStr ("__meta__",true)];
+			gen_expr ctx true e;
+			write ctx AObjSet;
+		);
 		PMap.iter (fun _ f -> gen_enum_field ctx e f) e.e_constrs
 	| TTypeDecl _ ->
 		()

+ 23 - 4
genswf9.ml

@@ -1687,7 +1687,7 @@ let generate_class_init ctx c hc =
 	write ctx (HInitProp (type_path ctx c.cl_path));
 	if ctx.swc then generate_class_statics ctx c
 
-let generate_enum_init ctx e hc =
+let generate_enum_init ctx e hc meta =
 	let path = ([],"Object") in
 	let name_id = type_path ctx e.e_path in
 	write ctx HGetGlobalScope;
@@ -1718,6 +1718,13 @@ let generate_enum_init ctx e hc =
 	List.iter (fun n -> write ctx (HString n)) e.e_names;
 	write ctx (HArray (List.length e.e_names));
 	write ctx (HSetProp (ident "__constructs__"));
+	(match meta with
+	| None -> ()
+	| Some e -> 
+		write ctx (HReg r.rid);
+		gen_expr ctx true e;
+		write ctx (HSetProp (ident "__meta__"));
+	);
 	free_reg ctx r
 
 let generate_field_kind ctx f c stat =
@@ -1859,7 +1866,7 @@ let generate_class ctx c =
 		) c.cl_ordered_statics);
 	}
 
-let generate_enum ctx e =
+let generate_enum ctx e meta =
 	let name_id = type_path ctx e.e_path in
 	let api = ctx.com.type_api in
 	let f = begin_fun ctx [("tag",None,api.tstring);("index",None,api.tint);("params",None,mk_mono())] api.tvoid [ethis] false e.e_pos in
@@ -1913,6 +1920,17 @@ let generate_enum ctx e =
 			hlf_metas = None;
 		} :: acc
 	) e.e_constrs [] in
+	let constrs = (match meta with
+		| None -> constrs
+		| Some _ -> 
+			incr st_count;
+			{
+				hlf_name = ident "__meta__";
+				hlf_slot = !st_count;
+				hlf_kind = HFVar { hlv_type = None; hlv_value = HVNone; hlv_const = false; };
+				hlf_metas = None;
+			} :: constrs
+	) in			
 	{
 		hlc_index = 0;
 		hlc_name = name_id;
@@ -1999,9 +2017,10 @@ let generate_type ctx t =
 		if e.e_extern && e.e_path <> ([],"Void") then
 			None
 		else
-			let hlc = generate_enum ctx e in
+			let meta = Codegen.build_metadata ctx.com t in
+			let hlc = generate_enum ctx e meta in
 			let init = begin_fun ctx [] ctx.com.type_api.tvoid [ethis] false e.e_pos in
-			generate_enum_init ctx e hlc;
+			generate_enum_init ctx e hlc meta;
 			write ctx HRetVoid;
 			Some (init(), {
 				hlf_name = type_path ctx e.e_path;

+ 44 - 0
std/haxe/rtti/Meta.hx

@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2005-2009, The haXe Project Contributors
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   - Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+package haxe.rtti;
+
+class Meta {
+
+	public static function getType( t : Dynamic ) : Dynamic<Array<Dynamic>> {
+		var meta : Dynamic = untyped t.__meta__;
+		return (meta == null) ? meta : meta.obj;
+	}
+
+	public static function getStatics( t : Dynamic ) : Dynamic<Dynamic<Array<Dynamic>>> {
+		var meta : Dynamic = untyped t.__meta__;
+		return (meta == null) ? meta : meta.statics;
+	}
+
+	public static function getFields( t : Dynamic ) : Dynamic<Dynamic<Array<Dynamic>>> {
+		var meta : Dynamic = untyped t.__meta__;
+		return (meta == null) ? meta : meta.fields;
+	}
+
+}

+ 1 - 1
tests/unit/RunCpp.hx

@@ -1,7 +1,7 @@
 class RunCpp {
 
 	static function main() {
-		var p = new neko.io.Process(neko.Web.getCwd()+"cpp/Test",[]);
+		var p = new neko.io.Process(neko.Web.getCwd()+"cpp/Test-debug",[]);
 		try {
 			while( true ) {
 				var c = p.stdout.readByte();

+ 1 - 0
tests/unit/Test.hx

@@ -183,6 +183,7 @@ class Test #if swf_mark implements mt.Protect #end #if as3 implements haxe.Publi
 			new TestEReg(),
 			new TestType(),
 			new TestXML(),
+			new TestMeta(),
 //			new TestRemoting(),
 		];
 		var current = null;

+ 62 - 0
tests/unit/TestMeta.hx

@@ -0,0 +1,62 @@
+package unit;
+
+@enumMeta private enum E {
+	@a A;
+	@b(0) B;
+}
+
+@classMeta("x") class TestMeta extends Test {
+
+	@empty() @_int(-45) @complex([{ x : 0, y : "hello", z : -1.48, b : true, k : null }]) static var foo : Int;
+
+	@new public function new() {
+		super();
+	}
+
+	function fields( o : Dynamic ) {
+		if( o == null ) return null;
+		var fl = Reflect.fields(o);
+		fl.sort(Reflect.compare);
+		return fl.join("#");
+	}
+
+	public function testMeta() {
+		var m = haxe.rtti.Meta.getType(E);
+		eq( fields(m), "enumMeta" );
+		eq( m.enumMeta, null );
+
+		var m = haxe.rtti.Meta.getType(TestMeta);
+		eq( fields(m), "classMeta" );
+		eq( Std.string(m.classMeta), "[x]" );
+
+		var m = haxe.rtti.Meta.getFields(E);
+		eq( fields(m), "A#B" );
+		eq( fields(m.A), "a" );
+		eq( m.A.a, null );
+		eq( fields(m.B), "b" );
+		eq( Std.string(m.B.b), "[0]" );
+
+		var m = haxe.rtti.Meta.getFields(TestMeta);
+		eq( fields(m), "_" );
+		eq( fields(m._), "new" );
+
+		var m = haxe.rtti.Meta.getStatics(E);
+		eq( m, null );
+
+		var m = haxe.rtti.Meta.getStatics(TestMeta);
+		eq( fields(m), "foo" );
+		eq( fields(m.foo), "_int#complex#empty" );
+		eq( m.foo.empty, null );
+		eq( Std.string(m.foo._int), "[-45]" );
+		var c : Dynamic = m.foo.complex[0][0];
+		eq( fields(c), "b#k#x#y#z" );
+		eq( c.x, 0 );
+		eq( c.y, "hello" );
+		eq( c.z, -1.48 );
+		eq( c.b, true );
+		eq( c.k, null );
+	}
+
+
+
+}

+ 1 - 0
tests/unit/unit.hxml

@@ -89,6 +89,7 @@ unit.Test
 
 -cpp cpp
 
+-debug
 -main unit.Test
 
 -cp ..

+ 2 - 0
tests/unit/unit.hxp

@@ -55,6 +55,7 @@
 
 -cpp cpp
 
+-debug
 -main unit.Test
 
 -cp ..
@@ -78,6 +79,7 @@
     <file path="TestInt32.hx" />
     <file path="TestIO.hx" />
     <file path="TestLocals.hx" />
+    <file path="TestMeta.hx" />
     <file path="TestMisc.hx" />
     <file path="TestReflect.hx" />
     <file path="TestRemoting.hx" />

+ 5 - 0
typeload.ml

@@ -541,6 +541,11 @@ let type_meta ctx meta =
 			(match c with
 			| Int _ | Float _ | String _ | Ident "true" | Ident "false" | Ident "null" -> type_constant ctx c p
 			| _ -> notconst p)
+		| EUnop (Neg,Prefix,(EConst c,_)) ->
+			(match c with
+			| Int i -> type_constant ctx (Int ("-" ^ i)) p
+			| Float f -> type_constant ctx (Float ("-" ^ f)) p
+			| _ -> notconst p)
 		| EObjectDecl fl ->
 			let rec loop (l,acc) (f,e) =
 				if PMap.mem f acc then error ("Duplicate field in object declaration : " ^ f) p;