Type/Reflect to get type of instance fields

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Type/Reflect to get type of instance fields

Eric Borts
Hello, List! Long time listener, first time caller. Great work on the
haXe language, Nicolas. It's a wonderful, modern replacement for the
stagnating adobe language.

At the moment, I'm experiencing some behavior I can't understand with
the Type/Reflect libraries, compiling to AS3 (10.1).

Basically I'm trying to get the type of an instance field. My code is
below. In the first scenario (creating an empty instance) the string
field reports as null. In the second scenario (using the default
constructor) the type of the float field reports as an integer if the
value assigned to it is a whole number (12.0). Note I've been certain to
include the decimal point.

My understanding of what is happening in the first case is that
Reflect.fields returns a list of the field names, and the only way for
me to get the type information about the field is to call Reflect.field
(no 's'). But since this returns the VALUE of the field from the
instance and the string field isn't populated, I get back NULL.

In the second case I have no idea what is happening. I've declared the
field as float and assigned it a floating point value complete with
decimal point. I've used the Dynamic type as recommended by Nicolas
[http://lists.motion-twin.com/pipermail/haxe/2007-October/012091.html]
to ensure it isn't a type inference problem. But the field is reporting
to be a TInt. Also, Std.is reports that the field is both an Int and Float.

I would prefer to use the empty instance, side-effect-less creation. But
this doesn't seem to work for non-value types. I could use a work around
that uses the empty instance for value types and then falls back to the
default constructor for any field that returned TNull.

Is there no way to extract type information from the fields at runtime
without requesting the value of the field?

Thanks for the help and sorry for my ignorance,

E

--- CODE ---
// Target AS3 Flash player 10.1
class TestReflection
{
     public var ival:Int;
     public var sval:String;
     public var f1:Float;
     public var f2:Float;

     public function new()
     {
         ival = 42;
         sval = "iAmAString";
         f1 = 12.0; // setting f1 to a whole number
         f2 = 13.1;
     }

     public static function run():Void
     {
         testEmpty();
         testCTOR();
     }

     private static function testEmpty():Void
     {
         // Scenario 1: Try creating an empty instance, but
         // non-value fields return TNull
         var c:Class<Dynamic> = Type.resolveClass("TestReflection");
         var empty:Dynamic = Type.createEmptyInstance( c );
         test(empty);
         // ival, true, 0,    TInt
         // sval, true, null, TNull   *** Expected TClass([class String])
         // f1,   true, NaN,  TFloat
         // f2,   true, NaN,  TFloat

         // Scenario 2: Use the default constructor which assigns values
         // to each of the fields, but incorrectly reports that f1:Float
is an int
         var c:Class<Dynamic> = Type.resolveClass("TestReflection");
         var ctor:Dynamic = Type.createInstance( c, [] );
         // ival, true, 42,        TInt
         // sval, true, iAmString, TClass([class String])
         // f1,   true, 12,        TInt    *** Expected TFloat
         // f2,   true, 13.1,      TFloat
     }

     private static function test(instance:Dynamic)
     {
         for (s in ["ival", "sval", "f1", "f2"]) {
             trace( s );
             trace( Reflect.hasField( instance, s ));
             var val:Dynamic = Reflect.field( instance, s);
             trace( val );
             trace( Type.typeof(val) );
         }
     }
}

--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Type/Reflect to get type of instance fields

Eric Borts
Apologies. The run method should look like this:

     public static function run():Void
     {
         // Scenario 1: Try creating an empty instance, but
         // non-value fields return TNull
         var c:Class<Dynamic> = Type.resolveClass("TestReflection");
         var empty:Dynamic = Type.createEmptyInstance( c );
         test(empty);
         // ival, true, 0,    TInt
         // sval, true, null, TNull   *** Expected TClass([class String])
         // f1,   true, NaN,  TFloat
         // f2,   true, NaN,  TFloat

         // Scenario 2: Use the default constructor which assigns values
         // to each of the fields, but incorrectly reports that f1:Float
is an int
         var c:Class<Dynamic> = Type.resolveClass("TestReflection");
         var ctor:Dynamic = Type.createInstance( c, [] );
         test(ctor);
         // ival, true, 42,        TInt
         // sval, true, iAmString, TClass([class String])
         // f1,   true, 12,        TInt    *** Expected TFloat
         // f2,   true, 13.1,      TFloat
     }



On 11/16/2011 3:16 PM, Eric Borts wrote:

> Hello, List! Long time listener, first time caller. Great work on the
> haXe language, Nicolas. It's a wonderful, modern replacement for the
> stagnating adobe language.
>
> At the moment, I'm experiencing some behavior I can't understand with
> the Type/Reflect libraries, compiling to AS3 (10.1).
>
> Basically I'm trying to get the type of an instance field. My code is
> below. In the first scenario (creating an empty instance) the string
> field reports as null. In the second scenario (using the default
> constructor) the type of the float field reports as an integer if the
> value assigned to it is a whole number (12.0). Note I've been certain
> to include the decimal point.
>
> My understanding of what is happening in the first case is that
> Reflect.fields returns a list of the field names, and the only way for
> me to get the type information about the field is to call
> Reflect.field (no 's'). But since this returns the VALUE of the field
> from the instance and the string field isn't populated, I get back NULL.
>
> In the second case I have no idea what is happening. I've declared the
> field as float and assigned it a floating point value complete with
> decimal point. I've used the Dynamic type as recommended by Nicolas
> [http://lists.motion-twin.com/pipermail/haxe/2007-October/012091.html]
> to ensure it isn't a type inference problem. But the field is
> reporting to be a TInt. Also, Std.is reports that the field is both an
> Int and Float.
>
> I would prefer to use the empty instance, side-effect-less creation.
> But this doesn't seem to work for non-value types. I could use a work
> around that uses the empty instance for value types and then falls
> back to the default constructor for any field that returned TNull.
>
> Is there no way to extract type information from the fields at runtime
> without requesting the value of the field?
>
> Thanks for the help and sorry for my ignorance,
>
> E
>
> --- CODE ---
> // Target AS3 Flash player 10.1
> class TestReflection
> {
>     public var ival:Int;
>     public var sval:String;
>     public var f1:Float;
>     public var f2:Float;
>
>     public function new()
>     {
>         ival = 42;
>         sval = "iAmAString";
>         f1 = 12.0; // setting f1 to a whole number
>         f2 = 13.1;
>     }
>
>     public static function run():Void
>     {
>         testEmpty();
>         testCTOR();
>     }
>
>     private static function testEmpty():Void
>     {
>         // Scenario 1: Try creating an empty instance, but
>         // non-value fields return TNull
>         var c:Class<Dynamic> = Type.resolveClass("TestReflection");
>         var empty:Dynamic = Type.createEmptyInstance( c );
>         test(empty);
>         // ival, true, 0,    TInt
>         // sval, true, null, TNull   *** Expected TClass([class String])
>         // f1,   true, NaN,  TFloat
>         // f2,   true, NaN,  TFloat
>
>         // Scenario 2: Use the default constructor which assigns values
>         // to each of the fields, but incorrectly reports that
> f1:Float is an int
>         var c:Class<Dynamic> = Type.resolveClass("TestReflection");
>         var ctor:Dynamic = Type.createInstance( c, [] );
>         // ival, true, 42,        TInt
>         // sval, true, iAmString, TClass([class String])
>         // f1,   true, 12,        TInt    *** Expected TFloat
>         // f2,   true, 13.1,      TFloat
>     }
>
>     private static function test(instance:Dynamic)
>     {
>         for (s in ["ival", "sval", "f1", "f2"]) {
>             trace( s );
>             trace( Reflect.hasField( instance, s ));
>             var val:Dynamic = Reflect.field( instance, s);
>             trace( val );
>             trace( Type.typeof(val) );
>         }
>     }
> }
>


--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Type/Reflect to get type of instance fields

Cauê W.
Hey Eric, well there are ways to extract the type information with either macros or with rtti ( http://haxe.org/doc/advanced/rtti )

At runtime, without macros nor rtti, it is really difficult to get a precise information, because of the problems you just mentioned. I also find strange that f1 and f2 are being typed as TInt, but I don't really know the underlying implementation for this.

If macros or rtti can help you solve your issue, and you need help to use them, ask here and I'll be glad to help!

Cheers
Cauê

2011/11/16 Eric Borts <[hidden email]>
Apologies. The run method should look like this:


   public static function run():Void
   {
       // Scenario 1: Try creating an empty instance, but
       // non-value fields return TNull
       var c:Class<Dynamic> = Type.resolveClass("TestReflection");
       var empty:Dynamic = Type.createEmptyInstance( c );
       test(empty);
       // ival, true, 0,    TInt
       // sval, true, null, TNull   *** Expected TClass([class String])
       // f1,   true, NaN,  TFloat
       // f2,   true, NaN,  TFloat

       // Scenario 2: Use the default constructor which assigns values
       // to each of the fields, but incorrectly reports that f1:Float is an int
       var c:Class<Dynamic> = Type.resolveClass("TestReflection");
       var ctor:Dynamic = Type.createInstance( c, [] );
       test(ctor);

       // ival, true, 42,        TInt
       // sval, true, iAmString, TClass([class String])
       // f1,   true, 12,        TInt    *** Expected TFloat
       // f2,   true, 13.1,      TFloat
   }



On 11/16/2011 3:16 PM, Eric Borts wrote:
Hello, List! Long time listener, first time caller. Great work on the haXe language, Nicolas. It's a wonderful, modern replacement for the stagnating adobe language.

At the moment, I'm experiencing some behavior I can't understand with the Type/Reflect libraries, compiling to AS3 (10.1).

Basically I'm trying to get the type of an instance field. My code is below. In the first scenario (creating an empty instance) the string field reports as null. In the second scenario (using the default constructor) the type of the float field reports as an integer if the value assigned to it is a whole number (12.0). Note I've been certain to include the decimal point.

My understanding of what is happening in the first case is that Reflect.fields returns a list of the field names, and the only way for me to get the type information about the field is to call Reflect.field (no 's'). But since this returns the VALUE of the field from the instance and the string field isn't populated, I get back NULL.

In the second case I have no idea what is happening. I've declared the field as float and assigned it a floating point value complete with decimal point. I've used the Dynamic type as recommended by Nicolas [http://lists.motion-twin.com/pipermail/haxe/2007-October/012091.html] to ensure it isn't a type inference problem. But the field is reporting to be a TInt. Also, Std.is reports that the field is both an Int and Float.

I would prefer to use the empty instance, side-effect-less creation. But this doesn't seem to work for non-value types. I could use a work around that uses the empty instance for value types and then falls back to the default constructor for any field that returned TNull.

Is there no way to extract type information from the fields at runtime without requesting the value of the field?

Thanks for the help and sorry for my ignorance,

E

--- CODE ---
// Target AS3 Flash player 10.1
class TestReflection
{
   public var ival:Int;
   public var sval:String;
   public var f1:Float;
   public var f2:Float;

   public function new()
   {
       ival = 42;
       sval = "iAmAString";
       f1 = 12.0; // setting f1 to a whole number
       f2 = 13.1;
   }

   public static function run():Void
   {
       testEmpty();
       testCTOR();
   }

   private static function testEmpty():Void
   {
       // Scenario 1: Try creating an empty instance, but
       // non-value fields return TNull
       var c:Class<Dynamic> = Type.resolveClass("TestReflection");
       var empty:Dynamic = Type.createEmptyInstance( c );
       test(empty);
       // ival, true, 0,    TInt
       // sval, true, null, TNull   *** Expected TClass([class String])
       // f1,   true, NaN,  TFloat
       // f2,   true, NaN,  TFloat

       // Scenario 2: Use the default constructor which assigns values
       // to each of the fields, but incorrectly reports that f1:Float is an int
       var c:Class<Dynamic> = Type.resolveClass("TestReflection");
       var ctor:Dynamic = Type.createInstance( c, [] );
       // ival, true, 42,        TInt
       // sval, true, iAmString, TClass([class String])
       // f1,   true, 12,        TInt    *** Expected TFloat
       // f2,   true, 13.1,      TFloat
   }

   private static function test(instance:Dynamic)
   {
       for (s in ["ival", "sval", "f1", "f2"]) {
           trace( s );
           trace( Reflect.hasField( instance, s ));
           var val:Dynamic = Reflect.field( instance, s);
           trace( val );
           trace( Type.typeof(val) );
       }
   }
}



--
haXe - an open source web programming language
http://haxe.org


--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Type/Reflect to get type of instance fields

Eric Borts
Cauê,

RTTI works perfectly for my task. Below is a snippet from the code I
ended up using.

Thanks very much for your assistance,
E

-- CODE --

static function exportRTTI(t:Class<Dynamic>):Void
{
     var rtti:String = untyped t.__rtti;
     var x = Xml.parse(rtti).firstElement();
     var infos:TypeTree = new XmlParser().processElement(x);

     switch (infos) {
         case TClassdecl(c):
             trace("Found class - " + c.path);

             // scan the fields of the class looking for type information
             var fieldTypes = new Hash<String>();
             for (field in c.fields) {
                 trace("field name: " + field.name);
                 switch (field.type) {
                     case CClass(name, params): fieldTypes.set(
field.name, name );
                     case CEnum(name, params):  fieldTypes.set(
field.name, name );
                     default: trace("    skipping field: " + field.type);
                 }
             }

             // PROCESS FIELDS HERE

         default: trace("skipping type: " + infos);
     }
}

On 11/16/2011 7:14 PM, Cauê Waneck wrote:

> Hey Eric, well there are ways to extract the type information with
> either macros or with rtti ( http://haxe.org/doc/advanced/rtti )
>
> At runtime, without macros nor rtti, it is really difficult to get a
> precise information, because of the problems you just mentioned. I
> also find strange that f1 and f2 are being typed as TInt, but I don't
> really know the underlying implementation for this.
>
> If macros or rtti can help you solve your issue, and you need help to
> use them, ask here and I'll be glad to help!
>
> Cheers
> Cauê


--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Type/Reflect to get type of instance fields

Yanis Benson

I don't remember the place in haXe where i've seen the code, but I remember that testing int vs float was done by checking that it is integer by mathematical means. I believe it is related to flash type Number and it's weirdness. However, I can't guarantee this info is still actual.

On 17 Nov 2011 09:27, "Eric Borts" <[hidden email]> wrote:
Cauê,

RTTI works perfectly for my task. Below is a snippet from the code I ended up using.

Thanks very much for your assistance,
E

-- CODE --

static function exportRTTI(t:Class<Dynamic>):Void
{
   var rtti:String = untyped t.__rtti;
   var x = Xml.parse(rtti).firstElement();
   var infos:TypeTree = new XmlParser().processElement(x);

   switch (infos) {
       case TClassdecl(c):
           trace("Found class - " + c.path);

           // scan the fields of the class looking for type information
           var fieldTypes = new Hash<String>();
           for (field in c.fields) {
               trace("field name: " + field.name);
               switch (field.type) {
                   case CClass(name, params): fieldTypes.set( field.name, name );
                   case CEnum(name, params):  fieldTypes.set( field.name, name );
                   default: trace("    skipping field: " + field.type);
               }
           }

           // PROCESS FIELDS HERE

       default: trace("skipping type: " + infos);
   }
}

On 11/16/2011 7:14 PM, Cauê Waneck wrote:
Hey Eric, well there are ways to extract the type information with either macros or with rtti ( http://haxe.org/doc/advanced/rtti )

At runtime, without macros nor rtti, it is really difficult to get a precise information, because of the problems you just mentioned. I also find strange that f1 and f2 are being typed as TInt, but I don't really know the underlying implementation for this.

If macros or rtti can help you solve your issue, and you need help to use them, ask here and I'll be glad to help!

Cheers
Cauê


--
haXe - an open source web programming language
http://haxe.org

--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Type/Reflect to get type of instance fields

Nicolas Cannasse
Le 17/11/2011 08:55, Yanis Benson a écrit :
> I don't remember the place in haXe where i've seen the code, but I
> remember that testing int vs float was done by checking that it is
> integer by mathematical means. I believe it is related to flash type
> Number and it's weirdness. However, I can't guarantee this info is still
> actual.

Yes. Type.typeof is only able to know the actual current _value_ type,
not the type the _field_ was declared with (you need RTTI for that).

Best,
Nicolas

--
haXe - an open source web programming language
http://haxe.org