Generating switch at Compile Time
ag0aep6g via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Mon Apr 17 15:49:39 PDT 2017
On 04/17/2017 09:29 PM, Jesse Phillips wrote:
> On Thursday, 13 April 2017 at 21:33:28 UTC, ag0aep6g wrote:
[...]
>> By the way, in my opinion, `case li[0]:` shouldn't compile with the
>> static immutable `list`. `list` and `li[0]` are dynamic values. The
>> compiler only attempts (and succeeds) to evaluate them at compile time
>> because they're typed as immutable. The way I see it, that only makes
>> things more confusing.
>
> This is very interesting. I wonder if the compiler is still unrolling
> the loop at compile time since it functions as expected; It certainly
> needs that deprecation though.
It's really weird. I thought the loop would just not be unrolled at all.
However, both `case`s seem to be generated as expected. So it behaves
like a static foreach in that regard. But when you use `li` as a dynamic
value (e.g. `writeln(li[1])`), it's suddenly empty. Seems that dmd can't
decide what to do, so it does a little bit of both.
Maybe I was wrong, and the loop in your code is a static foreach, but at
some point there's a bug that makes dmd think it's dealing with run-time
values.
The behavior is also completely inconsistent.
With ints, the program compiles and the assert passes:
----
alias AliasSeq(stuff ...) = stuff;
immutable list = AliasSeq!(1, 2);
void main()
{
switch(1)
{
foreach(li; list)
{
case li: enum e = li; assert(e == li); return;
}
default:
}
}
----
With strings, the program doesn't compile:
----
alias AliasSeq(stuff ...) = stuff;
immutable list = AliasSeq!("foo", "bar");
void main()
{
switch("foo")
{
foreach(li; list)
{
case li: enum e = li; assert(e == li); return;
/* "Error: case must be a string or an integral constant, not li" */
}
default:
}
}
----
And with structs (your case), it compiles with a deprecation warning and
behaves schizophrenically:
----
alias AliasSeq(stuff ...) = stuff;
struct S { int x; }
immutable list = AliasSeq!(S(1), S(2));
void main()
{
switch(1)
/* Deprecation: 'switch' skips declaration of variable */
{
foreach(li; list)
{
case li.x: enum e = li; assert(e == li); return;
/* The assert fails. */
}
default:
}
}
----
In my opinion, they should all simply be rejected. But I have no idea
what's intended by the compiler writers. It's a mess.
With enum/alias, they all compile and work as expected, of course.
More information about the Digitalmars-d-learn
mailing list