www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - CTFE UFCs?

reply bitwise <bitwise.pvt gmail.com> writes:
Hi.

I've been building a reflection library for D, but I've hit a snag. If  
anyone can help out, it would be much appreciated =D

In the example below, the second line of main() retrieves the reflection  
of a base class. Everything is well and good. Now, I am trying to come up  
with a more pleasant syntax, which is the code that is commented out.

When I uncomment the nicer syntax, I get the errors below:

[1] Error: variable refl cannot be read at compile time
[2] Error: CTFE failed because of previous errors in base


class Base {
     double d = 0.4;
}

class Test : Base {
     int x = 4;
}

abstract class Refl {
      property abstract string name() const;
      property abstract string baseName() const;
}

class ClassRefl(T) : Refl {
      property override string name() const {
         return T.stringof;
     }

      property override string baseName() const {
         alias BaseClassesTuple!T base_types;
         return base_types[0].stringof;
     }
}

const(Refl) reflect(T)() {
     static const(Refl) refl = new ClassRefl!T;
     return refl;
}

const(Refl) reflect(string name)() {
     mixin("return reflect!(" ~ name ~ ");");
}

//const(Refl) base(const(Refl) refl) {
//    return reflect!(refl.baseName());        ERROR  [1]
//}

void main()
{
     static const(Refl) refl = reflect!Test;

     static const(Refl) baseRefl = reflect!(refl.baseName());

     //static const(Refl) baseRefl = refl.base;       ERROR  [2]

     writeln(refl.name);
     writeln(baseRefl.name);
}


If anyone can offer a work around it would be much appreciated.
Apr 14 2015
next sibling parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Tue, 14 Apr 2015 11:20:38 -0400, bitwise wrote:

i believe that you can't do what you want in a way you want, 'cause UFCS=20
is not working for template args. but you can do this:

alias base(alias CC) =3D reflect!(CC.baseName());
...
static const(Refl) baseRefl =3D base!refl;=
Apr 14 2015
parent bitwise <bitwise.pvt gmail.com> writes:
On Tue, 14 Apr 2015 12:46:40 -0400, ketmar <ketmar ketmar.no-ip.org> wrote:

 On Tue, 14 Apr 2015 11:20:38 -0400, bitwise wrote:

 i believe that you can't do what you want in a way you want, 'cause UFCS
 is not working for template args. but you can do this:

 alias base(alias CC) = reflect!(CC.baseName());
 ...
 static const(Refl) baseRefl = base!refl;
Yeah.. but at this point you may as well you std.traits.BaseClassesTuple.
Apr 15 2015
prev sibling parent reply "anonymous" <anonymous example.com> writes:
On Tuesday, 14 April 2015 at 15:20:37 UTC, bitwise wrote:
 When I uncomment the nicer syntax, I get the errors below:

 [1] Error: variable refl cannot be read at compile time
 [2] Error: CTFE failed because of previous errors in base


 class Base {
     double d = 0.4;
 }

 class Test : Base {
     int x = 4;
 }

 abstract class Refl {
      property abstract string name() const;
      property abstract string baseName() const;
 }

 class ClassRefl(T) : Refl {
      property override string name() const {
         return T.stringof;
     }

      property override string baseName() const {
         alias BaseClassesTuple!T base_types;
         return base_types[0].stringof;
     }
 }

 const(Refl) reflect(T)() {
     static const(Refl) refl = new ClassRefl!T;
     return refl;
 }

 const(Refl) reflect(string name)() {
     mixin("return reflect!(" ~ name ~ ");");
 }

 //const(Refl) base(const(Refl) refl) {
 //    return reflect!(refl.baseName());        ERROR  [1]
 //}

 void main()
 {
     static const(Refl) refl = reflect!Test;

     static const(Refl) baseRefl = reflect!(refl.baseName());

     //static const(Refl) baseRefl = refl.base;       ERROR  [2]

     writeln(refl.name);
     writeln(baseRefl.name);
 }


 If anyone can offer a work around it would be much appreciated.
Minimal changes to what you have now; gives you `base!refl` instead of `refl.base`: ---- const(Refl) base(alias refl)() { return reflect!(refl.baseName()); } static const(Refl) baseRefl = base!refl; ---- Digging deeper: ---- abstract class Refl { property abstract string name() const; immutable(Refl) base() const; } class ClassRefl(T) : Refl { property override string name() const { return T.stringof; } override immutable(Refl) base() const { alias BaseClassesTuple!T base_types; static if(base_types.length > 0) { static immutable(Refl) instance = new ClassRefl!(base_types[0]); return instance; } else return null; } } static const(Refl) baseRefl = refl.base; ---- Parting thoughts: I don't know where you're heading with this. But so far I don't see what it would buy you over std.traits and TypeInfo/TypeInfo_Class.
Apr 14 2015
next sibling parent bitwise <bitwise.pvt gmail.com> writes:
On Tue, 14 Apr 2015 12:52:19 -0400, anonymous <anonymous example.com>  
wrote:

 abstract class Refl {
       property abstract string name() const;
      immutable(Refl) base() const;
 }

 class ClassRefl(T) : Refl {
       property override string name() const {
          return T.stringof;
      }

      override immutable(Refl) base() const
      {
          alias BaseClassesTuple!T base_types;
          static if(base_types.length > 0)
          {
              static immutable(Refl) instance = new  
 ClassRefl!(base_types[0]);
              return instance;
          }
          else return null;
      }
 }
 static const(Refl) baseRefl = refl.base;
It looks like you ripped this code right out of my current prototype ;) The problem is though, that having the base() method means that "ClassRefl!(base_types[0])" must be instantiated, and that template will also have a base() method, and so will it's base, etc... so reflecting a single class will automatically reflect all bases. I'm trying to get away from this behavior and make reflection total opt-in, meaning that the ClassRefl for the base will only be instantiated if it's actually used.
 Parting thoughts:
 I don't know where you're heading with this. But so far I don't see what  
 it would buy you over std.traits and TypeInfo/TypeInfo_Class.
Because an object-hierarchy is easier to use and self-documenting. Instead of having to look things up, you just type "Reflection" ".", and all the choices of what you can do with the object are presented to you by intellisense.
Apr 15 2015
prev sibling parent bitwise <bitwise.pvt gmail.com> writes:
On Tue, 14 Apr 2015 12:52:19 -0400, anonymous <anonymous example.com>  
wrote:
 Parting thoughts:
 I don't know where you're heading with this. But so far I don't see what  
 it would buy you over std.traits and TypeInfo/TypeInfo_Class.
Forgot to mention support for runtime reflection. See here: https://github.com/bitwise-github/D-Reflection/blob/master/main.d#L14
Apr 15 2015