Skip to content

Commit

Permalink
added metadata api
Browse files Browse the repository at this point in the history
git-svn-id: http://haxe.googlecode.com/svn/trunk@3242 f16182fa-f095-11de-8f43-4547254af6c6
  • Loading branch information
ncannasse committed Jul 23, 2010
1 parent 17227d6 commit cae4e7e
Show file tree
Hide file tree
Showing 13 changed files with 211 additions and 14 deletions.
58 changes: 52 additions & 6 deletions codegen.ml
Expand Up @@ -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 *)

Expand Down Expand Up @@ -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);
| _ ->
()

Expand Down
1 change: 1 addition & 0 deletions doc/CHANGES.txt
Expand Up @@ -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
Expand Down
8 changes: 7 additions & 1 deletion genjs.ml
Expand Up @@ -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);
Expand Down
7 changes: 5 additions & 2 deletions genneko.ml
Expand Up @@ -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 =
Expand Down
7 changes: 7 additions & 0 deletions genswf8.ml
Expand Up @@ -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 _ ->
()
Expand Down
27 changes: 23 additions & 4 deletions genswf9.ml
Expand Up @@ -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;
Expand Down Expand Up @@ -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 =
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
44 changes: 44 additions & 0 deletions 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;
}

}
2 changes: 1 addition & 1 deletion 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();
Expand Down
1 change: 1 addition & 0 deletions tests/unit/Test.hx
Expand Up @@ -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;
Expand Down
62 changes: 62 additions & 0 deletions 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 change: 1 addition & 0 deletions tests/unit/unit.hxml
Expand Up @@ -89,6 +89,7 @@ unit.Test

-cpp cpp

-debug
-main unit.Test

-cp ..
Expand Down
2 changes: 2 additions & 0 deletions tests/unit/unit.hxp
Expand Up @@ -55,6 +55,7 @@

-cpp cpp

-debug
-main unit.Test

-cp ..
Expand All @@ -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" />
Expand Down
5 changes: 5 additions & 0 deletions typeload.ml
Expand Up @@ -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;
Expand Down

0 comments on commit cae4e7e

Please sign in to comment.