Need reflection facilities

Dave Woldrich dave at woldrich.com
Wed Jan 3 14:48:09 PST 2007


== Quote from Pragma (ericanderton at yahoo.removeme.com)'s article

> Neither is very pretty.
> 1) Use the DMD front-end to compose a utility that pre-processes .d
> files and generates the needed reflection support code.  I think there
> are other D-ers who are doing this, but I can't recall who at the moment
> (hasn't been much word about it lately).  I honestly don't see why this
> can't be done today, and made to work everywhere D already does.
> The facts that the front-end will furnish you with a 100% spec-compliant
> AST, D supports the #line directive, and the spec allows for custom
> pragma() statements, only make this approach more appealing.
> 2) Parse the .map file.  D's mangling specification allows for far more
> useful information than what any C++ compiler spits out.  The result is
> that you can extract entire call-signatures and name-spaces directly
> from the symbol table.  I'm presently using this technique in DDL to
> bootstrap dynamic linking with object files:
> http://www.dsource.org/projects/ddl

Excellent, thanks for this response, I will look into it.  I think hacking the
compiler wouldn't be a bad deal and would probably produce the fastest executing
solution.  My thoughts based on what you are saying is that static construction of
compiler-generated type metadata classes would be possible and could be enabled
with a compiler switch.

CeeFIT uses a two tier approach to registering types.  Within classes that need
reflection, CeeFIT has macros that register fields and functions for reflection
for each class instance that is created.  Macros place a "FITFIELD<T>" in the
class for every field that needs to be found by name where T is the type of the
field.  They place a "FITTEST<T, U>" for every zero-arg function that needs to be
found by name where T is the type of the containing class and U is the type of the
return type.  There are variants of FITTEST for one-arg functions as well.  Each
FITFIELD and FITTEST is initialized with a string name and a pointer to the member
function or field.  Templates take care of the rest.

As each FITFIELD and FITTEST member placed by the macros initializes during object
construction, they add themselves to a singly-linked list hosted by a base class
that facilitates the reflection.  The drawback of this is the additional memory
and cpu cycles burned whenever a reflectable object is instantiated.  I did this
out of necessity since the C++ limitations had me hamstrung.  Wherever the macros
cant or won't work, I have a less efficient manual registration technique that
users can use, but that's not really relevant to what I'm discussing here.

I figure a D compiler extension that generates these field and function metadata
artifacts could generate them to some class outside the classes being described
and initialize them only once at startup.  Leading to function and field metadata
in a hashmap keyed by the string name representation.  Slap a simple reflection
API on top of that hashmap and you've got it.

The second tier of the reflection facilities in CeeFIT is to register the classes
themselves by name for construction.  To do this, macros place a static
REGISTERFIXTURECLASS<T> object after the class definition is closed where T is the
class type.  The linker ensures that the REGISTERFIXTURECLASS<T> is initialized at
program start.   REGISTERFIXTURECLASS<T> provides the mapping between class string
name and the class's zero-arg default constructor.  Upon initialization, the
REGISTERFIXTURECLASS<T> adds itself to a global singly-linked list which can be
searched at runtime to pull off the Class.forName() functionality I needed.

Of course, searching singly-linked lists are going to perform badly for any decent
sized application, and a D version of this code could add the statically
initialized REGISTERFIXTURECLASS<T> to a hashmap or whatnot instead.  I don't know
what kind of DLL support there is in D, but dynamically loading and unloading
classes and magically keeping this hashmap up to date would be so cherry.

I am only just now learning about D, so I don't know what the limitations of the
compiler are and whether such extensions would be feasible.  As you were saying
Eric, the map file could be sufficient to generate all of this type metadata code
as a post-processing step, I just figure the compiler has all the information
while it is running and therefore would be the best place to put the logic.  Plus,
to have reflection facilities be a first class feature of the
language/compiler/runtime library would be very slick.

If I had reflection in a systems-programming language like D, the tools that could
be written to work with D would be incredible.  I'm sure Eclipse for D would be a
dream to use and would benefit from all the refactoring and type information that
Java gets.  I am already thinking of porting my videogame code to D (since I'm
using a replacement GC heap in my C++ code anyhow, not like D is going to perform
any slower.)  I will probably make some ant tasks for D if I do and there aren't
any already.

I am just really liking the D language, thank you Walter and whoever else is
responsible for this!  :)

Cheers,
Dave Woldrich



More information about the Digitalmars-d mailing list