-
-
Notifications
You must be signed in to change notification settings - Fork 610
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[dmd-cxx] Implement static foreach, aliasing traits, and fix allMembers. #10791
Conversation
----
Implement DIP 1010 - (Static foreach)
Support for `static foreach` has been added.
`static foreach` is a conditional compilation construct that is to `foreach` what `static if` is to `if`.
It is a convenient way to generate declarations and statements by iteration.
```
import std.conv: to;
static foreach(i; 0 .. 10)
{
// a `static foreach` body does not introduce a nested scope
// (similar to `static if`).
// The following mixin declaration is at module scope:
mixin(`enum x` ~ to!string(i) ~ ` = i;`); // declares 10 variables x0, x1, ..., x9
}
import std.range: iota;
// all aggregate types that can be iterated with a standard `foreach`
// loop are also supported by static foreach:
static foreach(i; iota(10))
{
// we access the declarations generated in the first `static foreach`
pragma(msg, "x", i, ": ", mixin(`x` ~ to!string(i)));
static assert(mixin(`x` ~ to!string(i)) == i);
}
void main()
{
import std.conv: text;
import std.typecons: tuple;
import std.algorithm: map;
import std.stdio: writeln;
// `static foreach` has both declaration and statement forms
// (similar to `static if`).
static foreach(x; iota(3).map!(i => tuple(text("x", i), i)))
{
// generates three local variables x0, x1 and x2.
mixin(text(`int `,x[0],` = x[1];`));
scope(exit) // this is within the scope of `main`
{
writeln(mixin(x[0]));
}
}
writeln(x0," ",x1," ",x2); // first runtime output
}
```
----
Aliases can be created directly from a `__trait`.
Aliases can be created directly from the traits that return symbol(s) or tuples.
This includes `getMember`, `allMembers`, `derivedMembers`, `parent`, `getOverloads`,
`getVirtualFunctions`, `getVirtualMethods`, `getUnitTests`, `getAttributes` and finally `getAliasThis`.
Previously an `AliasSeq` was necessary in order to alias their return.
Now the grammar allows to write shorter declarations:
```
struct Foo
{
static int a;
}
alias oldWay = AliasSeq!(__traits(getMember, Foo, "a"))[0];
alias newWay = __traits(getMember, Foo, "a");
```
To permit this it was more interesting to include `__trait` in the basic types
rather than just changing the alias syntax. So additionally, wherever a type appears
a `__trait` can be used, for example in a variable declaration:
```
struct Foo { static struct Bar {} }
const(__traits(getMember, Foo, "Bar")) fooBar;
static assert(is(typeof(fooBar) == const(Foo.Bar)));
```
----
fix Issue 10100 - Identifiers with double underscores and allMembers
Convert the identifier whitelist into a blacklist of all possible
internal D language declarations.
|
Thanks for your pull request, @ibuclaw! Bugzilla references
Testing this PR locallyIf you don't have a local development environment setup, you can use Digger to test this PR: dub fetch digger
dub run digger -- build "dmd-cxx + dmd#10791" |
|
Apparently the win32 box can't checkout the repository anymore... oh well. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really appreciate the thankless job you're doing here - thank you!
|
I'm sure people can't wait to use For those who are attentive, the magic template functions in the D implementation have been de-templatized in the C++ version. Don't know if it would be desirable to also remove the templates in dmd/master as well. |
|
@ibuclaw I would greatly appreciate seeing less templates in dmd. |
1. Implement DIP 1010 - (Static foreach)
Support for 'static foreach' has been added. 'static foreach' is a conditional
compilation construct that is to 'foreach' what 'static if' is to 'if'. It is
a convenient way to generate declarations and statements by iteration.
import std.conv: to;
static foreach(i; 0 .. 10)
{
// a 'static foreach' body does not introduce a nested scope
// (similar to 'static if').
// The following mixin declaration is at module scope:
// declares 10 variables x0, x1, ..., x9
mixin('enum x' ~ to!string(i) ~ ' = i;');
}
import std.range: iota;
// all aggregate types that can be iterated with a standard 'foreach'
// loop are also supported by static foreach:
static foreach(i; iota(10))
{
// we access the declarations generated in the first 'static foreach'
pragma(msg, "x", i, ": ", mixin(`x` ~ to!string(i)));
static assert(mixin(`x` ~ to!string(i)) == i);
}
void main()
{
import std.conv: text;
import std.typecons: tuple;
import std.algorithm: map;
import std.stdio: writeln;
// 'static foreach' has both declaration and statement forms
// (similar to 'static if').
static foreach(x; iota(3).map!(i => tuple(text("x", i), i)))
{
// generates three local variables x0, x1 and x2.
mixin(text(`int `,x[0],` = x[1];`));
scope(exit) // this is within the scope of 'main'
{
writeln(mixin(x[0]));
}
}
writeln(x0," ",x1," ",x2); // first runtime output
}
2. Aliases can be created directly from a '__trait'.
Aliases can be created directly from the traits that return symbol(s) or
tuples. This includes 'getMember', 'allMembers', 'derivedMembers', 'parent',
'getOverloads', 'getVirtualFunctions', 'getVirtualMethods', 'getUnitTests',
'getAttributes' and finally 'getAliasThis'. Previously an 'AliasSeq' was
necessary in order to alias their return. Now the grammar allows to write
shorter declarations:
struct Foo
{
static int a;
}
alias oldWay = AliasSeq!(__traits(getMember, Foo, "a"))[0];
alias newWay = __traits(getMember, Foo, "a");
To permit this it was more interesting to include '__trait' in the basic types
rather than just changing the alias syntax. So additionally, wherever a type
appears a '__trait' can be used, for example in a variable declaration:
struct Foo { static struct Bar {} }
const(__traits(getMember, Foo, "Bar")) fooBar;
static assert(is(typeof(fooBar) == const(Foo.Bar)));
3. fix Issue 10100 - Identifiers with double underscores and allMembers
The identifer whitelist has been converted into a blacklist of all possible
internal D language declarations.
Reviewed-on: dlang/dmd#10791
This'll be the notable addition to gdc10, as it's too late to switch to self-hosted now.
Bootstrapped and regression tested on x86_64-linux-gnu. Though we'll wait and see how the dmd autotester responds, particularly on Windows and OSX.
ChangeLog entries below:
Implement DIP 1010 - (Static foreach)
Support for
static foreachhas been added.static foreachis a conditional compilation construct that is toforeachwhatstatic ifis toif.It is a convenient way to generate declarations and statements by iteration.
Aliases can be created directly from a
__trait.Aliases can be created directly from the traits that return symbol(s) or tuples.
This includes
getMember,allMembers,derivedMembers,parent,getOverloads,getVirtualFunctions,getVirtualMethods,getUnitTests,getAttributesand finallygetAliasThis.Previously an
AliasSeqwas necessary in order to alias their return.Now the grammar allows to write shorter declarations:
To permit this it was more interesting to include
__traitin the basic typesrather than just changing the alias syntax. So additionally, wherever a type appears
a
__traitcan be used, for example in a variable declaration:fix Issue 10100 - Identifiers with double underscores and allMembers
Convert the identifier whitelist into a blacklist of all possible
internal D language declarations.