Time for std.reflection

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Sun Jul 22 07:28:44 PDT 2012


On 7/22/12 9:39 AM, Philippe Sigaud wrote:
> 1) About templates, would class/struct/function templates be in there?
> As in:
>
> class Foo(T,U) { ... }
> =>
> class TemplateInfo {
> @property:
>      string name();
>      FunctionInfo[] functions();
>      ClassInfo[] classes();
>      TemplateInfo[] templates(); // Yes, templates in templates are
> possible, and so on, recursively
> ....
> }

Yah, ideally all entities definable in a D module should be available 
via reflection. But I focused on things that e.g. the user of a 
dynamically-loaded library would be interested in: functions, classes.

std.reflection could become the lynchpin for dynamic library use; once 
the library is loaded (with dlopen or such), the client needs to call 
getModuleInfo() (a C function that can be found with dlsym()) and then 
get access to pointers to functions necessary for doing all other work. 
(Note that my examples don't yet include pointers to executable code yet.)

> 2) Why classes, as opposed to structs? Would inheritance/hierarchies
> play a role there? Or reference semantics?
> Note that between structs, classes, templates and modules there is a
> lot of redundancy. A possibility could be to have an AggregateInfo
> base class.

Initially I used struct, but then I figured reference semantics are more 
natural for storing cross-entity information, as you indeed took 
advantage of in your TemplateInfo.

> 3) For a class, a (to my eyes) standard request would be to get the
> parents chain, up to Object. Could that be added in ClassInfo, or as
> an external free function? (edit: scratch that, you're talking about
> lazy gathering below).

I used strings because I assumed it's easy to just query the ClassInfo 
given a string. But yes, we could use references to ClassInfo and 
InterfaceInfo etc. in a transitive manner.

> 4) How would that allows queries like "Here is class C, give me all
> its available subclasses."? Hmm, wait, I get it: extract classes from
> the module, and recursively from imported modules. From these classes,
> extract the parent classes and so on, until the search ranged over the
> whole inheritance tree. I guess inheritance info could be standard
> enough for std.reflection to provide such a search.

Something like that. Note that such a query is not particularly OO-ish, 
because getting a class' cone (totality of subclasses) works against the 
modularity that inheritance is meant for. I don't think we should make 
getting class cones particularly easy.

> 5) The compiler can emit JSON output giving a partial view of the same
> information. As a long-term goal, I suggest these infos should be
> compatible somehow. The JSON output should be enriched, and we should
> ascertain that using std.json to read this kind of
> automatically-generated information should give std.reflection infos
> back.

Yes, that's a great connection that Walter and I discussed a bit.

> 6) Is really all the necessary info available through std.traits and
> __traits? Imported modules and their subtilities (renamed functions,
> etc) seem out of reach, no?

We'll need indeed to enhance __traits with what's needed. Much of the 
point of std.reflection is to determine exactly what's there and what's 
needed. And that starts with the data structures design (the algorithmic 
aspects are minor).

> 7) I know your examples are not complete, but don't forget aliases and
> symbols, and module-level values. Since these can be of any type, I'm
> not sure how they are managed in your scheme. I mean, you cannot have
> IntInfo[], DoubleInfo[], ...

I sort of eschewed part of that by using strings for types.

> 8) (more a remark than a question) To me, it's another example of a
> tree-like structure. I humbly suggest we get a std.tree somewhere, to
> manipulate generic n-ary trees: mapping on trees, searching
> (extracting elements or whole subtrees), folding trees, etc. That is,
> a module that deals with trees/graphs not so much as containers, but
> as a way to represent the relationships between elements. I'm not sure
> I'm so clear here, but ideally std.json, std.xml, std.reflection and
> probably a few others should use it as a low-level basis.
> Btw, I have tree / trees algo (including depth-first / breadth-first
> ranges) / graph / graph algo (strongly connected components, search in
> graphs, ...) on github, but it's code that predate std.container and
> is in limbo, pending std.allocator.

Well you're the resident crazy-stuff-during-compilation guy. Did you try 
your trees during compilation?


Andrei


More information about the Digitalmars-d mailing list