This limits what can be done with CTFE and forces a variety of compile-time data structures and functions to be complicated templates without necessity.
Consider a simple module introspection structure:
struct Module
{
string name;
string[] allMembers()
{
assert(__ctfe);
mixin("immutable result = [ __traits(allMembers, " ~ name ~ ") ];");
return result;
}
}
unittest
{
enum x = Module("std.typecons").allMembers;
}
The error is "value of this is not known at compile time". But it can, because this is itself a compile-time value.
Passing the string as a parameter doesn't help either:
struct Module
{
string[] allMembers(string name)
{
assert(__ctfe, "Can only be invoked during compilation");
mixin("immutable result = [ __traits(allMembers, " ~ name ~ ") ];");
return result;
}
}
unittest
{
enum x = Module().allMembers("std.typecons");
}
Here the error is "variable name cannot be read at compile time". Again that should work because the code is being evaluated during compilation.
In this case the cure is simple - make Module a template parameterized on the module name/alias. But the matter gets a lot more problematic when trying to represent e.g. "all function declarations in this module".
Comment #1 by ag0aep6g — 2018-02-11T18:32:11Z
(In reply to Andrei Alexandrescu from comment #0)
> In this case the cure is simple - make Module a template parameterized on
> the module name/alias. But the matter gets a lot more problematic when
> trying to represent e.g. "all function declarations in this module".
If you have a better example, why not show it? How would you implement "all function declarations in this module" with/without the proposed feature?
Also, this needs to be a full-blown DIP, no? The restriction that all functions must be compilable for run time is in the spec and widely accepted (as far as I'm aware). If you want to lift it, you'll have to go into much more detail than you did here.
Comment #2 by andrei — 2018-02-11T18:40:37Z
Happy to oblige!
struct Data
{
string name;
string type;
string qualifier;
string[] attributes;
}
Then the module can give you all top-level data declarations:
enum Data[] d = Module("mypack.mymod").data;
...
Indeed it is odd there'd be functions that only run during compilation. Need to think of that.
Comment #3 by ag0aep6g — 2018-02-11T19:21:28Z
(In reply to Andrei Alexandrescu from comment #2)
> Happy to oblige!
>
> struct Data
> {
> string name;
> string type;
> string qualifier;
> string[] attributes;
> }
>
> Then the module can give you all top-level data declarations:
>
> enum Data[] d = Module("mypack.mymod").data;
> ...
Eh? Previously it was "function declarations", now it's "data declarations". And you've not given an implementation of either.
Comment #4 by andrei — 2018-02-11T19:39:37Z
(In reply to ag0aep6g from comment #3)
> (In reply to Andrei Alexandrescu from comment #2)
> > Happy to oblige!
> >
> > struct Data
> > {
> > string name;
> > string type;
> > string qualifier;
> > string[] attributes;
> > }
> >
> > Then the module can give you all top-level data declarations:
> >
> > enum Data[] d = Module("mypack.mymod").data;
> > ...
>
> Eh? Previously it was "function declarations", now it's "data declarations".
> And you've not given an implementation of either.
Somebody's in a testy mood :o). It was quicker to exemplify with data. Will follow up with a working sample.
Comment #6 by destructionator — 2018-02-12T01:47:30Z
Why doesn't:
enum Data[] d = getModule!("mypack.mymod").data;
work? Where getModule is a small template that just returns the populated Module object with the CT data.
Comment #7 by andrei — 2018-02-12T02:18:58Z
(In reply to Adam D. Ruppe from comment #6)
> Why doesn't:
>
> enum Data[] d = getModule!("mypack.mymod").data;
>
>
> work? Where getModule is a small template that just returns the populated
> Module object with the CT data.
Cool variant, thanks.
Comment #8 by hsteoh — 2018-02-13T02:28:59Z
It's a bit ironic, but perhaps reading this might help explain why what you proposed doesn't work:
https://wiki.dlang.org/User:Quickfur/Compile-time_vs._compile-time
OTOH, why not just make the module name a template parameter? That would sidestep the issue:
----
struct Module(string name)
{
string[] allMembers() {
enum impl = __traits(allMembers, name);
return impl;
}
}
----
Comment #9 by andrei — 2018-02-13T03:11:44Z
(In reply to hsteoh from comment #8)
> It's a bit ironic, but perhaps reading this might help explain why what you
> proposed doesn't work:
>
> https://wiki.dlang.org/User:Quickfur/Compile-time_vs._compile-time
>
> OTOH, why not just make the module name a template parameter? That would
> sidestep the issue:
>
> ----
> struct Module(string name)
> {
> string[] allMembers() {
> enum impl = __traits(allMembers, name);
> return impl;
> }
> }
> ----
Whoa, great article. I didn't know about it. Thanks!
Comment #10 by robert.schadek — 2024-12-13T18:57:06Z