July 23, 2012
On Mon, Jul 23, 2012 at 2:43 PM, David Nadlinger <see@klickverbot.at> wrote: [getting subclasses]
> You can't do that without breaking the module system – as long as a class is not final (and then it doesn't make much sense to ask for its subclasses anyway), somebody can always extend it in a module completely separate from the code making the query.
>
> To illustrate what I mean, let's assume you define a class Foo in a module A. The user imports A from a second module B, and potentially extends Foo there. Now, if it was possible to get all possible subclasses in A, this would lead to information leaking from B to A, while the import graph only allows the other direction. As a consequence, all kinds of issues related to order dependence, separate compilation, etc. would arise.

Yes, I know. That would be a purely local question: from module A,
what subclasses of class Foo do I see?
Anyway, maybe I'm warped by CLOS.
November 19, 2012
>> In the latter case, the module needs to save all needed information for
>> ri, so it should plant this:
>>
>> // inside std.algorithm
>> mixin(makeModuleInfoAvailableDynamically());
>>

Is there a way to get the current module at compile time?

__traits(allMembers, pkg.modulename)


November 19, 2012
On Monday, 19 November 2012 at 11:43:36 UTC, sclytrack wrote:

You could do something like this:
string currentModule(alias T = {})() { return __traits(parent, T).stringof; }

November 20, 2012
Huge interest!
I wouldn't want to see static data structures bloat/clutter the exe though
in cases where it's not ever used/queried.
The object factory is already a serious problem.


On 22 July 2012 00:44, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org>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(**makeModuleInfoAvailableDynamic**ally());
>
> 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
>


November 20, 2012
I like it. First a couple details:

> 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();
>     ...
> }

Why do you not use recursion here? Why not
ClassInfo base();
ClassInfo parent();
and then you get baseName by calling base.name;

> 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();
> }

Do you think there'll be any way to get the actual types of the arguments and the return type back from the struct? I think that without compiler magic or an uncomfortable amount of templates it probably won't be possible, but I might be wrong.


Now to my big complaint:

I really dislike making the runtime api accessible through a mixin. I'd much prefer making it a non-member template. Reasons are
a) I don't want to store the runtime information in my type. A vtable pointer should be enough to get that information. Maybe use it as an index into a global immutable associative array. For modules and non-class types the name can act as a unique identifier.
b) It'd make it possible to get runtime information on types that I get from libraries.
c) It would lead to less coupling.
d) It would discourage writing types that rely on runtime reflection, but it would not make it impossible.
1 2 3 4 5
Next ›   Last »