On Sunday, 4 September 2016 at 19:15:15 UTC, Igor wrote:
So, you are saying compiler is keeping a kind of linked list of
dependencies and then checks if any of those lists are
circular? But how exactly would that list be structured since
one expression can have multiple dependencies, like:
enum a = b + c + d + e;
enum b = 10 + c;
enum c = d + e + a;
...
Disclaimer: I don't know how the D compiler works internally. I
just happen to know how generic compilers usually work.
I think the easiest solution is to keep a stack of what you are
doing.
So in your last example, we start with evaluating a. We first see
that a depends on b.
So we switch evaluating b. As we do so, our stack contains a and
b.
We see that b depends on c. So we switch to evaluate c.
Our stack becomes a, b, c.
We see that c depends on d. So we evaluate d.
Our stack is a, b, c, d.
You didn't give a definition for d. Let's assume it does not
depend on anything. So we successfully evaluated d. So we get
back to c.
Our stack is a, b, c.
We see that c also depends on e. So we evaluate e.
Our stack is a, b, c, e.
You didn't give a definition for e. Let's assume it does not
depend on anything. So we successfully evaluated e. So we get
back to c.
Our stack is a, b, c.
We see that c also depends on a. So we evaluate a.
Our stack becomes a, b, c, a.
Ops... Our stack contains a two times. This means that to
evaluate a we need the value of a. So we tell the user that we
cannot proceed further.
By the way, the stack also tells us how a depends on itself. In
fact, the stack a, b, c, a tells us that a depends on b which
depends on c which depends on a.
I hope this is a clear enough explanation. If not, feel free to
ask further.