Explorar o código

partial support for Reflect.getProperty/setProperty

Nicolas Cannasse %!s(int64=13) %!d(string=hai) anos
pai
achega
22ec3c982e

+ 25 - 7
codegen.ml

@@ -83,6 +83,24 @@ let rec type_constant_value com (e,p) =
 	| _ ->
 	| _ ->
 		error "Constant value expected" p
 		error "Constant value expected" p
 
 
+let rec has_properties c =
+	List.exists (fun f ->
+		match f.cf_kind with
+		| Var { v_read = AccCall _ } -> true
+		| Var { v_write = AccCall _ } -> true
+		| _ -> false
+	) c.cl_ordered_fields || (match c.cl_super with Some (c,_) -> has_properties c | _ -> false)
+
+let get_properties fields =
+	List.fold_left (fun acc f ->
+		let acc = (match f.cf_kind with
+		| Var { v_read = AccCall getter } -> ("get_" ^ f.cf_name , getter) :: acc
+		| _ -> acc) in
+		match f.cf_kind with
+		| Var { v_write = AccCall setter } -> ("set_" ^ f.cf_name , setter) :: acc
+		| _ -> acc
+	) [] fields	
+
 (* -------------------------------------------------------------------------- *)
 (* -------------------------------------------------------------------------- *)
 (* REMOTING PROXYS *)
 (* REMOTING PROXYS *)
 
 
@@ -649,13 +667,13 @@ let captured_vars com e =
 			(match com.platform with
 			(match com.platform with
 			| Cpp -> e
 			| Cpp -> e
 			| _ ->
 			| _ ->
-				mk (TCall (
-					mk_parent (mk (TFunction {
-						tf_args = List.map (fun v -> v, None) vars;
-						tf_type = e.etype;
-						tf_expr = mk_block (mk (TReturn (Some e)) e.etype e.epos);
-					}) (TFun (List.map (fun v -> v.v_name,false,v.v_type) vars,e.etype)) e.epos),
-					List.map (fun v -> mk (TLocal v) v.v_type e.epos) vars)
+				mk (TCall (
+					mk_parent (mk (TFunction {
+						tf_args = List.map (fun v -> v, None) vars;
+						tf_type = e.etype;
+						tf_expr = mk_block (mk (TReturn (Some e)) e.etype e.epos);
+					}) (TFun (List.map (fun v -> v.v_name,false,v.v_type) vars,e.etype)) e.epos),
+					List.map (fun v -> mk (TLocal v) v.v_type e.epos) vars)
 				) e.etype e.epos)
 				) e.etype e.epos)
 		| _ ->
 		| _ ->
 			map_expr (wrap used) e
 			map_expr (wrap used) e

+ 2 - 0
doc/CHANGES.txt

@@ -20,6 +20,8 @@
 	all : allowed abitrary string fields in anonymous objects
 	all : allowed abitrary string fields in anonymous objects
 	all : structure fields which are Null<X> are now optional (for constant values)
 	all : structure fields which are Null<X> are now optional (for constant values)
 	all : allowed optional args in functions types (?Int -> Void)
 	all : allowed optional args in functions types (?Int -> Void)
+	all : added Reflect.getProperty/setProperty 
+		(partial support : neko, js only so far)
 
 
 2011-09-25: 2.08
 2011-09-25: 2.08
 	js : added js.JQuery
 	js : added js.JQuery

+ 21 - 0
genjs.ml

@@ -732,6 +732,16 @@ let generate_class ctx c =
 		newline ctx;
 		newline ctx;
 	);
 	);
 
 
+	let gen_props props = 
+		String.concat "," (List.map (fun (p,v) -> p ^":\""^v^"\"") props)
+	in
+
+	(match Codegen.get_properties c.cl_ordered_statics with
+	| [] -> ()
+	| props ->
+		print ctx "%s.__properties__ = {%s}" p (gen_props props);
+		newline ctx);
+
 	List.iter (gen_class_static_field ctx c) c.cl_ordered_statics;
 	List.iter (gen_class_static_field ctx c) c.cl_ordered_statics;
 
 
 	(match c.cl_super with
 	(match c.cl_super with
@@ -747,6 +757,17 @@ let generate_class ctx c =
 	List.iter (fun f -> match f.cf_kind with Var { v_read = AccResolve } -> () | _ -> gen_class_field ctx c f) c.cl_ordered_fields;
 	List.iter (fun f -> match f.cf_kind with Var { v_read = AccResolve } -> () | _ -> gen_class_field ctx c f) c.cl_ordered_fields;
 	newprop ctx;
 	newprop ctx;
 	print ctx "__class__: %s" p;
 	print ctx "__class__: %s" p;
+
+	let props = Codegen.get_properties c.cl_ordered_fields in
+	(match c.cl_super with
+	| _ when props = [] -> ()
+	| Some (csup,_) when Codegen.has_properties csup ->
+		newprop ctx;
+		let psup = s_path ctx csup.cl_path in
+		print ctx "__properties__: $extend(%s.prototype.__properties__,{%s})" psup (gen_props props)
+	| _ ->
+		newprop ctx;
+		print ctx "__properties__: {%s}" (gen_props props));
 	
 	
 	bend();
 	bend();
 	print ctx "\n}";
 	print ctx "\n}";

+ 24 - 2
genneko.ml

@@ -204,6 +204,8 @@ and gen_expr ctx e =
 	match e.eexpr with
 	match e.eexpr with
 	| TConst c ->
 	| TConst c ->
 		gen_constant ctx e.epos c
 		gen_constant ctx e.epos c
+	| TLocal v when v.v_name.[0] = '$' ->
+		(EConst (Builtin (String.sub v.v_name 1 (String.length v.v_name - 1))),p)
 	| TLocal v ->
 	| TLocal v ->
 		if v.v_capture then
 		if v.v_capture then
 			(EArray (ident p v.v_name,int p 0),p)
 			(EArray (ident p v.v_name,int p 0),p)
@@ -491,9 +493,14 @@ let gen_class ctx c =
 	let build (f,e) = (EBinop ("=",field p (ident p "@tmp") f,e),p) in
 	let build (f,e) = (EBinop ("=",field p (ident p "@tmp") f,e),p) in
 	let tmp = (EVars ["@tmp",Some (call p (builtin p "new") [null p])],p) in
 	let tmp = (EVars ["@tmp",Some (call p (builtin p "new") [null p])],p) in
 	let estat = (EBinop ("=", stpath, ident p "@tmp"),p) in
 	let estat = (EBinop ("=", stpath, ident p "@tmp"),p) in
+	let gen_props props = (EObject (List.map (fun (n,s) -> n,str p s) props),p) in
+	let sprops = (match Codegen.get_properties c.cl_ordered_statics with
+		| [] -> []
+		| l -> ["__properties__",gen_props l]
+	) in
 	let sfields = List.map build
 	let sfields = List.map build
 		(
 		(
-			("prototype",clpath) ::
+			("prototype",clpath) :: sprops @
 			PMap.fold (gen_method ctx p) c.cl_statics (fnew @ others)
 			PMap.fold (gen_method ctx p) c.cl_statics (fnew @ others)
 		)
 		)
 	in
 	in
@@ -501,8 +508,23 @@ let gen_class ctx c =
 	let mfields = List.map build
 	let mfields = List.map build
 		(PMap.fold (gen_method ctx p) c.cl_fields (fserialize :: fstring))
 		(PMap.fold (gen_method ctx p) c.cl_fields (fserialize :: fstring))
 	in
 	in
+	let props = Codegen.get_properties c.cl_ordered_fields in
 	let emeta = (EBinop ("=",field p clpath "__class__",stpath),p) ::
 	let emeta = (EBinop ("=",field p clpath "__class__",stpath),p) ::
-		match c.cl_path with
+		(match props with
+		| [] -> []
+		| _ ->
+			let props = gen_props props in
+			let props = (match c.cl_super with
+				| Some (csup,_) when Codegen.has_properties csup ->
+					(EBlock [
+						(EVars ["@tmp",Some props],p);
+						call p (builtin p "objsetproto") [ident p "@tmp";field p (field p (gen_type_path p csup.cl_path) "prototype") "__properties__"];
+						ident p "@tmp"
+					],p)
+				| _ -> props					
+			) in
+			[EBinop ("=",field p clpath "__properties__",props),p])
+		@ match c.cl_path with
 		| [] , name -> [(EBinop ("=",field p (ident p "@classes") name,ident p name),p)]
 		| [] , name -> [(EBinop ("=",field p (ident p "@classes") name,ident p name),p)]
 		| _ -> []
 		| _ -> []
 	in
 	in

+ 2 - 3
lexer.mll

@@ -136,9 +136,8 @@ let mk lexbuf t =
 	mk_tok t (lexeme_start lexbuf) (lexeme_end lexbuf)
 	mk_tok t (lexeme_start lexbuf) (lexeme_end lexbuf)
 
 
 let mk_ident lexbuf =
 let mk_ident lexbuf =
-	match lexeme lexbuf with
-	| s ->
-		mk lexbuf (try Kwd (Hashtbl.find keywords s) with Not_found -> Const (Ident s))
+	let s = lexeme lexbuf in
+	mk lexbuf (try Kwd (Hashtbl.find keywords s) with Not_found -> Const (Ident s))
 
 
 let invalid_char lexbuf =
 let invalid_char lexbuf =
 	error (Invalid_character (lexeme_char lexbuf 0)) (lexeme_start lexbuf)
 	error (Invalid_character (lexeme_char lexbuf 0)) (lexeme_start lexbuf)

+ 11 - 0
std/Reflect.hx

@@ -45,6 +45,17 @@ extern class Reflect {
 	**/
 	**/
 	public static function setField( o : Dynamic, field : String, value : Dynamic ) : Void;
 	public static function setField( o : Dynamic, field : String, value : Dynamic ) : Void;
 
 
+	/**
+		Similar to field but also supports property (might be slower).
+	**/
+	public static function getProperty( o : Dynamic, field : String ) : Dynamic;
+
+	/**
+		Similar to setField but also supports property (might be slower).
+	**/
+	public static function setProperty( o : Dynamic, field : String, value : Dynamic ) : Void;
+
+
 	/**
 	/**
 		Call a method with the given object and arguments.
 		Call a method with the given object and arguments.
 	**/
 	**/

+ 8 - 0
std/cpp/_std/Reflect.hx

@@ -39,6 +39,14 @@
 			o.__SetField(field,value);
 			o.__SetField(field,value);
 	}
 	}
 
 
+	public static inline function getProperty( o : Dynamic, field : String ) : Dynamic {
+		return Reflect.field(o,field);
+	}
+
+	public static inline function setProperty( o : Dynamic, field : String, value : Dynamic ) : Void {
+		setField(o,field,value);
+	}
+
 	public static function callMethod( o : Dynamic, func : Dynamic, args : Array<Dynamic> ) : Dynamic untyped {
 	public static function callMethod( o : Dynamic, func : Dynamic, args : Array<Dynamic> ) : Dynamic untyped {
 			if (func!=null && func.__GetType()==__global__.vtString)
 			if (func!=null && func.__GetType()==__global__.vtString)
 				func = o.__Field(func);
 				func = o.__Field(func);

+ 8 - 0
std/flash/_std/Reflect.hx

@@ -37,6 +37,14 @@
 		o[field] = value;
 		o[field] = value;
 	}
 	}
 
 
+	public static inline function getProperty( o : Dynamic, field : String ) : Dynamic {
+		return Reflect.field(o,field);
+	}
+
+	public static inline function setProperty( o : Dynamic, field : String, value : Dynamic ) : Void {
+		setField(o,field,value);
+	}
+
 	public inline static function callMethod( o : Dynamic, func : Dynamic, args : Array<Dynamic> ) : Dynamic untyped {
 	public inline static function callMethod( o : Dynamic, func : Dynamic, args : Array<Dynamic> ) : Dynamic untyped {
 		return func["apply"](o,args);
 		return func["apply"](o,args);
 	}
 	}

+ 8 - 0
std/flash9/_std/Reflect.hx

@@ -38,6 +38,14 @@
 		o[field] = value;
 		o[field] = value;
 	}
 	}
 
 
+	public static inline function getProperty( o : Dynamic, field : String ) : Dynamic {
+		return Reflect.field(o,field);
+	}
+
+	public static inline function setProperty( o : Dynamic, field : String, value : Dynamic ) : Void {
+		setField(o,field,value);
+	}
+	
 	public inline static function callMethod( o : Dynamic, func : Dynamic, args : Array<Dynamic> ) : Dynamic untyped {
 	public inline static function callMethod( o : Dynamic, func : Dynamic, args : Array<Dynamic> ) : Dynamic untyped {
 		return func.apply(o,args);
 		return func.apply(o,args);
 	}
 	}

+ 10 - 0
std/js/_std/Reflect.hx

@@ -47,6 +47,16 @@
 		o[field] = value;
 		o[field] = value;
 	}
 	}
 
 
+	public static inline function getProperty( o : Dynamic, field : String ) : Dynamic untyped {
+		var tmp;
+		return if( o == null ) null else if( o.__properties__ && (tmp=o.__properties__["get_"+field]) ) o[tmp]() else o[field];
+	}
+
+	public static inline function setProperty( o : Dynamic, field : String, value : Dynamic ) : Void untyped {
+		var tmp;
+		if( o.__properties__ && (tmp=o.__properties__["set_"+field]) ) o[tmp](value) else o[field] = value;
+	}
+
 	public inline static function callMethod( o : Dynamic, func : Dynamic, args : Array<Dynamic> ) : Dynamic untyped {
 	public inline static function callMethod( o : Dynamic, func : Dynamic, args : Array<Dynamic> ) : Dynamic untyped {
 		return func.apply(o,args);
 		return func.apply(o,args);
 	}
 	}

+ 5 - 3
std/js/_std/Type.hx

@@ -117,14 +117,16 @@ enum ValueType {
 		var a = [];
 		var a = [];
 		untyped __js__("for(var i in c.prototype) a.push(i)");
 		untyped __js__("for(var i in c.prototype) a.push(i)");
 		a.remove("__class__");
 		a.remove("__class__");
+		a.remove("__properties__");
 		return a;
 		return a;
 	}
 	}
 
 
 	public static function getClassFields( c : Class<Dynamic> ) : Array<String> {
 	public static function getClassFields( c : Class<Dynamic> ) : Array<String> {
 		var a = Reflect.fields(c);
 		var a = Reflect.fields(c);
-		a.remove(__unprotect__("__name__"));
-		a.remove(__unprotect__("__interfaces__"));
-		a.remove(__unprotect__("__super__"));
+		a.remove("__name__");
+		a.remove("__interfaces__");
+		a.remove("__properties__");
+		a.remove("__super__");
 		a.remove("prototype");
 		a.remove("prototype");
 		return a;
 		return a;
 	}
 	}

+ 27 - 15
std/neko/_std/Reflect.hx

@@ -26,31 +26,43 @@
 @:core_api class Reflect {
 @:core_api class Reflect {
 
 
 	public static function hasField( o : Dynamic, field : String ) : Bool untyped {
 	public static function hasField( o : Dynamic, field : String ) : Bool untyped {
-		return __dollar__typeof(o) == __dollar__tobject && __dollar__objfield(o,__dollar__hash(field.__s));
+		return $typeof(o) == $tobject && $objfield(o,$hash(field.__s));
 	}
 	}
 
 
 	public inline static function field( o : Dynamic, field : String ) : Dynamic untyped {
 	public inline static function field( o : Dynamic, field : String ) : Dynamic untyped {
-		return if( __dollar__typeof(o) != __dollar__tobject ) null else __dollar__objget(o,__dollar__hash(field.__s));
+		return if( $typeof(o) != $tobject ) null else $objget(o,$hash(field.__s));
 	}
 	}
 
 
 	public inline static function setField( o : Dynamic, field : String, value : Dynamic ) : Void untyped {
 	public inline static function setField( o : Dynamic, field : String, value : Dynamic ) : Void untyped {
-		if( __dollar__typeof(o) == __dollar__tobject )
-			__dollar__objset(o,__dollar__hash(field.__s),value);
+		if( $typeof(o) == $tobject )
+			$objset(o,$hash(field.__s),value);
+	}
+
+	public static inline function getProperty( o : Dynamic, field : String ) : Dynamic untyped {
+		var tmp;
+		return if( $typeof(o) != $tobject ) null else if( o.__properties__ != null && (tmp=$objget(o.__properties__,$hash("get_".__s+field.__s))) != null ) $call($objget(o,$hash(tmp)),o,$array()) else $objget(o,$hash(field.__s));
+	}
+
+	public static inline function setProperty( o : Dynamic, field : String, value : Dynamic ) : Void untyped {
+		if( $typeof(o) == $tobject ) {
+			var tmp;
+			if( o.__properties__ != null && (tmp=$objget(o.__properties__,$hash("set_".__s+field.__s))) != null ) $call($objget(o,$hash(tmp)),o,$array(value)) else $objset(o,$hash(field.__s),value);
+		}
 	}
 	}
 
 
 	public inline static function callMethod( o : Dynamic, func : Dynamic, args : Array<Dynamic> ) : Dynamic untyped {
 	public inline static function callMethod( o : Dynamic, func : Dynamic, args : Array<Dynamic> ) : Dynamic untyped {
-		return __dollar__call(func,o,args.__neko());
+		return $call(func,o,args.__neko());
 	}
 	}
 
 
 	public static function fields( o : Dynamic ) : Array<String> untyped {
 	public static function fields( o : Dynamic ) : Array<String> untyped {
-		if( __dollar__typeof(o) != __dollar__tobject )
+		if( $typeof(o) != $tobject )
 			return new Array<String>();
 			return new Array<String>();
 		else {
 		else {
-			var a : neko.NativeArray<Int> = __dollar__objfields(o);
+			var a : neko.NativeArray<Int> = $objfields(o);
 			var i = 0;
 			var i = 0;
-			var l = __dollar__asize(a);
+			var l = $asize(a);
 			while( i < l ) {
 			while( i < l ) {
-				a[i] = new String(__dollar__field(a[i]));
+				a[i] = new String($field(a[i]));
 				i++;
 				i++;
 			}
 			}
 			return Array.new1(a,l);
 			return Array.new1(a,l);
@@ -58,11 +70,11 @@
 	}
 	}
 
 
 	public static function isFunction( f : Dynamic ) : Bool untyped {
 	public static function isFunction( f : Dynamic ) : Bool untyped {
-		return __dollar__typeof(f) == __dollar__tfunction;
+		return $typeof(f) == $tfunction;
 	}
 	}
 
 
 	public inline static function compare<T>( a : T, b : T ) : Int {
 	public inline static function compare<T>( a : T, b : T ) : Int {
-		return untyped __dollar__compare(a,b);
+		return untyped $compare(a,b);
 	}
 	}
 
 
 	public inline static function compareMethods( f1 : Dynamic, f2 : Dynamic ) : Bool {
 	public inline static function compareMethods( f1 : Dynamic, f2 : Dynamic ) : Bool {
@@ -70,19 +82,19 @@
 	}
 	}
 
 
 	public static function isObject( v : Dynamic ) : Bool untyped {
 	public static function isObject( v : Dynamic ) : Bool untyped {
-		return __dollar__typeof(v) == __dollar__tobject && v.__enum__ == null;
+		return $typeof(v) == $tobject && v.__enum__ == null;
 	}
 	}
 
 
 	public inline static function deleteField( o : Dynamic, f : String ) : Bool untyped {
 	public inline static function deleteField( o : Dynamic, f : String ) : Bool untyped {
-		return __dollar__objremove(o,__dollar__hash(f.__s));
+		return $objremove(o,$hash(f.__s));
 	}
 	}
 
 
 	public inline static function copy<T>( o : T ) : T {
 	public inline static function copy<T>( o : T ) : T {
-		return untyped __dollar__new(o);
+		return untyped $new(o);
 	}
 	}
 
 
 	public static function makeVarArgs( f : Array<Dynamic> -> Dynamic ) : Dynamic {
 	public static function makeVarArgs( f : Array<Dynamic> -> Dynamic ) : Dynamic {
-		return untyped __dollar__varargs(function(a) { return f(Array.new1(a,__dollar__asize(a))); });
+		return untyped $varargs(function(a) { return f(Array.new1(a,$asize(a))); });
 	}
 	}
 
 
 	#if neko
 	#if neko

+ 3 - 1
std/neko/_std/Type.hx

@@ -140,6 +140,7 @@ enum ValueType {
 		a.remove("__class__");
 		a.remove("__class__");
 		a.remove("__serialize");
 		a.remove("__serialize");
 		a.remove("__string");
 		a.remove("__string");
+		a.remove("__properties__");
 		return a;
 		return a;
 	}
 	}
 
 
@@ -150,6 +151,7 @@ enum ValueType {
 		a.remove("__super__");
 		a.remove("__super__");
 		a.remove("__string");
 		a.remove("__string");
 		a.remove("__construct__");
 		a.remove("__construct__");
+		a.remove("__properties__");
 		a.remove("prototype");
 		a.remove("prototype");
 		a.remove("new");
 		a.remove("new");
 		#if macro
 		#if macro
@@ -211,7 +213,7 @@ enum ValueType {
 	public inline static function enumIndex( e : Dynamic ) : Int {
 	public inline static function enumIndex( e : Dynamic ) : Int {
 		return e.index;
 		return e.index;
 	}
 	}
-	
+
 	public static function allEnums<T>( e : Enum<T> ) : Array<T> {
 	public static function allEnums<T>( e : Enum<T> ) : Array<T> {
 		var all = [];
 		var all = [];
 		var cst : Array<String> = untyped e.__constructs__;
 		var cst : Array<String> = untyped e.__constructs__;

+ 8 - 0
std/php/_std/Reflect.hx

@@ -37,6 +37,14 @@
 		untyped __setfield__(o, field, value);
 		untyped __setfield__(o, field, value);
 	}
 	}
 
 
+	public static inline function getProperty( o : Dynamic, field : String ) : Dynamic {
+		return Reflect.field(o,field);
+	}
+
+	public static inline function setProperty( o : Dynamic, field : String, value : Dynamic ) : Void {
+		setField(o,field,value);
+	}
+	
 	public static function callMethod( o : Dynamic, func : Dynamic, args : Array<Dynamic> ) : Dynamic untyped {
 	public static function callMethod( o : Dynamic, func : Dynamic, args : Array<Dynamic> ) : Dynamic untyped {
 		if (__call__("is_string", o) && !__call__("is_array", func)) {
 		if (__call__("is_string", o) && !__call__("is_array", func)) {
 			return __call__("call_user_func_array", field(o, func), __field__(args, "»a"));
 			return __call__("call_user_func_array", field(o, func), __field__(args, "»a"));

+ 1 - 1
tests/unit/Test.hx

@@ -117,7 +117,7 @@ class Test #if swf_mark implements mt.Protect #end #if as3 implements haxe.Publi
 		}
 		}
 		haxe.Log.trace(msg,pos);
 		haxe.Log.trace(msg,pos);
 		reportCount++;
 		reportCount++;
-		if( reportCount == 10 ) {
+		if( reportCount == 20 ) {
 			trace("Too many errors");
 			trace("Too many errors");
 			report = function(msg,?pos) {};
 			report = function(msg,?pos) {};
 		}
 		}

+ 84 - 0
tests/unit/TestReflect.hx

@@ -1,6 +1,58 @@
 package unit;
 package unit;
 import Type;
 import Type;
 
 
+class ClassWithProp {
+	public var x(getX, setX) : Int;
+	var _x : Int;
+	
+	public function new() {
+		_x = 5;
+	}
+	
+	function getX() {
+		return _x;
+	}
+	function setX(v) {
+		_x = v;
+		return v;
+	}
+	
+	public static var STAT_X(default, setStatX) : Int;
+	
+	static function setStatX(v) {
+		STAT_X = v * 2;
+		return v;
+	}
+	
+	static function __init__() {
+		STAT_X = 3;
+	}
+	
+	
+}
+
+class SubClassWithProp extends ClassWithProp {
+	public var y(default, setY) : Int;
+	
+	public function new() {
+		super();
+		y = 10;
+	}
+	
+	override function getX() {
+		return _x + 1;
+	}
+	
+	function getY() {
+		return y;
+	}
+	
+	function setY(v) {
+		y = v;
+		return v;
+	}
+}
+
 class TestReflect extends Test {
 class TestReflect extends Test {
 
 
 	static var TYPES = [
 	static var TYPES = [
@@ -186,5 +238,37 @@ class TestReflect extends Test {
 		f( Reflect.compareMethods(a.add,null) );
 		f( Reflect.compareMethods(a.add,null) );
 		f( Reflect.compareMethods(null,a.add) );
 		f( Reflect.compareMethods(null,a.add) );
 	}
 	}
+	
+	function testGetProp() {
+		
+		var c = new ClassWithProp();
+		eq( c.x, 5);
+		eq( Reflect.getProperty(c, "x"), 5);
+		Reflect.setProperty(c, "x", 10);
+		eq( c.x, 10);
+		eq( Reflect.getProperty(c, "x"), 10);
+		
+		var c = new SubClassWithProp();
+		eq( c.x, 6);
+		eq( Reflect.getProperty(c, "x"), 6);
+		eq( c.y, 10);
+		eq( Reflect.getProperty(c, "y"), 10);
+		
+		Reflect.setProperty(c, "x", 10);
+		Reflect.setProperty(c, "y", 20);
+		
+		eq( c.x, 11);
+		eq( Reflect.getProperty(c, "x"), 11);
+		eq( c.y, 20);
+		eq( Reflect.getProperty(c, "y"), 20);
+		
+		eq( ClassWithProp.STAT_X, 6 );
+		eq( Reflect.getProperty(ClassWithProp, "STAT_X"), 6 );
+		
+		Reflect.setProperty(ClassWithProp, "STAT_X", 8);
+		
+		eq( ClassWithProp.STAT_X, 16 );
+		eq( Reflect.getProperty(ClassWithProp, "STAT_X"), 16 );
+	}
 
 
 }
 }