Time for std.reflection

Alex Rønne Petersen alex at lycus.org
Sat Jul 21 17:28:35 PDT 2012


On 21-07-2012 23:44, Andrei Alexandrescu wrote:
> Walter and I discussed the idea below a long time (years) ago. Most
> likely it's also been discussed in this newsgroup a couple of times.
> Given the state of the compiler back then, back then it seemed like a
> super cool idea that's entirely realizable, it would just take time for
> the compiler to become as capable as needed. Nowadays we're in shape to
> tackle it.
>
> Here "it" is.
>
> Back when runtime reflection was being discussed, my response was "let's
> focus on compile-time reflection, and then we can do run-time reflection
> on demand as a library". Though this might sound sensible, I initially
> didn't have a design. Now here's what we can do.
>
> Currently we have information about symbols as __traits(...) intrinsics
> wrapped in nice but scattered ways. Now that CTFE is good enough to
> manipulate structs and arrays thereof, we have the possibility to
> finally approach things in a nicely unified, structured way.
>
> First, we need to prime std.reflection with a few abstractions that
> characterize entities in a D program.
>
> class ModuleInfo {
> @property:
>      string name();
>      ImportInfo[] imports();
>      DataInfo[] data();
>      FunctionInfo[] functions();
>      ClassInfo[] classes();
>      StructInfo[] structs(); // includes unions
>      TemplateInfo[] templates();
>      EnumInfo[] enums();
>      bool hasStaticCtor(), hasStaticDtor(),
>        hasSharedCtor(), hasSharedDtor();
> }
>
> Probably there are a few more pieces of data, but you get the idea. Then
> for each of the entities mentioned above we have a similar definition.
> For example:
>
> enum Protection { isPublic, isPackage, isProtected, isPrivate }
>
> class ClassInfo {
> @property:
>      string name();
>      string baseName();
>      string parentName(); // if applicable, null otherwise
>      string[] interfaces();
>      bool isShared();
>      Protection protection();
>      DataMemberInfo[] data();
>      MethodInfo[] methods();
>      Object defaultConstructor();
>      ...
> }
>
> Then for an e.g. method declaration we'd have:
>
> class MethodInfo {
> @property:
>      string name();
>      bool isStatic(), isFinal(), isOverride();
>      Protection protection();
>      string[] parameterTypes();
>      string[] parameterNames();
> }
>
> Some details may vary, e.g. some may be straight members instead of
> properties etc. (I used properties to allude to use of lazy gathering of
> information).
>
> So so far we have a nice collection of structured data associated with
> the entities in a D program. Note how this structuring differs yet has
> similar power to the primitives in std.traits; std.traits offers
> unstructured bits of information on demand (e.g. ParameterTypeNames)
> etc. but the objects above group information together per entity
> declared. All of the above goes in std.reflection, of course.
>
> ===========
>
> On to primitives that return such data.
>
> Given that D can (since relatively recently) create and manipulate class
> objects during compilation too, it follows that the classes above can be
> accessed in two ways - through compile-time API and run-time API. When
> possible, the APIs may even use the same functions; some other times
> they will be necessarily different.
>
> There are two possible approaches to discovering such information. One
> is by fetching the ModuleInfo for the whole module and navigating it.
> Another one is by using search primitives from strings.
>
> So we should have e.g.
>
> // inside std.reflection
> ModuleInfo getModuleInfo(string moduleName);
>
> so a CT call would go like:
>
> // client code
> static info = getModuleInfo("std.algorithm");
>
> whereas a run-time call would be:
>
> // client code
> auto info = getModuleInfo("std.algorithm");
>
> In the latter case, the module needs to save all needed information for
> ri, so it should plant this:
>
> // inside std.algorithm
> mixin(makeModuleInfoAvailableDynamically());
>
> The mixin would generate all information needed and would store it for
> later dynamic use.
>
> A search API would go like e.g.
>
> ClassInfo getClassInfo(string className);
>
> In this case the class name could be qualified with module information etc.
>
> ===========
>
> With this design we unify compile-time and run-time type manipulation in
> simple ways, by defining structured information about declarations that
> can be queried during compilation or dynamically.
>
> Please chime in with thoughts. Would someone want to pioneer this project?
>
>
> Andrei

I'm just curious about one thing: How do you plan to reify templates 
(they are Turing complete after all)?

-- 
Alex Rønne Petersen
alex at lycus.org
http://lycus.org


More information about the Digitalmars-d mailing list