Re: Mutually recursive template expansion

2021-10-04 Thread Paul Backus via Digitalmars-d-learn

On Monday, 4 October 2021 at 11:38:04 UTC, bauss wrote:

Actually it is covered by the spec.

See:

https://dlang.org/spec/expression.html#mixin_expressions

It clearly says:

```
Each AssignExpression in the ArgumentList is evaluated at 
compile time

```

Which means that Br cannot be used in Ar since it cannot be 
evaluated at compile time during the mixin of Ar.


That's not what that sentence means. Here's the full version, 
without the part you cut off:


Each AssignExpression in the ArgumentList is evaluated at 
compile time, and the result must be representable as a string. 
The resulting strings are concatenated to form a string. The 
text contents of the string must be compilable as a valid 
Expression, and is compiled as such.


In other words: the string being mixed in is what's evaluated at 
compile-time. The code *inside* the string is treated the same 
way as any other code.


Re: Mutually recursive template expansion

2021-10-04 Thread bauss via Digitalmars-d-learn

On Friday, 1 October 2021 at 14:26:39 UTC, jfondren wrote:

On Friday, 1 October 2021 at 14:03:06 UTC, Stephen wrote:

This code should work should mutual recursion be supported.


It still wouldn't work, because structs are value types and 
it's impossible to say how large either struct is:


Error: struct `mutualrec.Ar` no size because of forward 
reference


With s/struct/class/ it still wouldn't work because this is a 
mixin problem rather than a problem of template mutual 
recursion:


```d
mixin(q{ class Ar { Br b; } });
mixin(q{ class Br { Ar b; } });
```

mutualrec2.d-mixin-1(1): Error: undefined identifier `Br`, did 
you mean class `Ar`?


This seems like a surprising limitation of mixin, though, which 
isn't highlighted by the spec.


Actually it is covered by the spec.

See:

https://dlang.org/spec/expression.html#mixin_expressions

It clearly says:

```
Each AssignExpression in the ArgumentList is evaluated at compile 
time

```

Which means that Br cannot be used in Ar since it cannot be 
evaluated at compile time during the mixin of Ar.


Re: Mutually recursive template expansion

2021-10-02 Thread Imperatorn via Digitalmars-d-learn

On Friday, 1 October 2021 at 14:03:06 UTC, Stephen wrote:
I've been trying out templates in more depth and one thing I 
was wondering was whether template expansions with circular 
dependencies might work.

Here is an example that doesn't work:
```d
mixin(A!());
mixin(B!());

void main() {}

template A() {
const char[] A = q{
struct Ar {
Br b;
}
};
}

template B() {
const char[] B = q{
struct Br {
Ar a;
}
};
}
```
This code should work should mutual recursion be supported. How 
might I get it to work properly (without sacrificing recursion 
or templates)?


Just curious since I haven't found a use case for this myself, 
what's the benefit rather than having a separate struct?


Re: Mutually recursive template expansion

2021-10-02 Thread Basile B. via Digitalmars-d-learn

On Saturday, 2 October 2021 at 08:48:24 UTC, Stephen wrote:

Is this by design?


No but it's easily explainable.

## without mixins

```d
struct Ar { Br b; ubyte a; }
struct Br { ubyte b; }
```

`Ar` semantic starts, members are analyzed, that begins with the 
variable declaration `Br b`. `Br` type needs to be resolved. `Br` 
can be found in the AST as it is declared manually. Now `Br` is 
run and finally `Ar` sema continues.


## with mixins

```d
mixin(q{struct Ar { Br b; ubyte a; }});
mixin(q{struct Br { ubyte b; }});
```

The first mixin is compiled (`compileIt()` in dmd code base).

The AST is now the same as obtained by parsing

```d
struct Ar { Br b; ubyte a; }
mixin(q{struct Br { ubyte b; }});
```

`Ar` semantic starts, members are analyzed, that begins with the 
variable declaration`Br b`. But `Br` cannot be resolved because 
**it is not yet in the AST** and the symbol tables.


Re: Mutually recursive template expansion

2021-10-02 Thread Stephen via Digitalmars-d-learn

On Friday, 1 October 2021 at 14:26:39 UTC, jfondren wrote:

On Friday, 1 October 2021 at 14:03:06 UTC, Stephen wrote:

This code should work should mutual recursion be supported.


It still wouldn't work, because structs are value types and 
it's impossible to say how large either struct is:


Error: struct `mutualrec.Ar` no size because of forward 
reference


With s/struct/class/ it still wouldn't work because this is a 
mixin problem rather than a problem of template mutual 
recursion:


```d
mixin(q{ class Ar { Br b; } });
mixin(q{ class Br { Ar b; } });
```

mutualrec2.d-mixin-1(1): Error: undefined identifier `Br`, did 
you mean class `Ar`?


This seems like a surprising limitation of mixin, though, which 
isn't highlighted by the spec.


All right I'll try to design without mutual recursion but mixins 
don't seem to work if they're put out of order.

(i.e. this works:
```d
struct Ar { Br b; ubyte a; }
struct Br { ubyte b; }
```
but not this:
```d
mixin(q{struct Ar { Br b; ubyte a; }});
mixin(q{struct Br { ubyte b; }});
```
).
Is this by design?


Re: Mutually recursive template expansion

2021-10-01 Thread jfondren via Digitalmars-d-learn

On Friday, 1 October 2021 at 14:03:06 UTC, Stephen wrote:

This code should work should mutual recursion be supported.


It still wouldn't work, because structs are value types and it's 
impossible to say how large either struct is:


Error: struct `mutualrec.Ar` no size because of forward reference

With s/struct/class/ it still wouldn't work because this is a 
mixin problem rather than a problem of template mutual recursion:


```d
mixin(q{ class Ar { Br b; } });
mixin(q{ class Br { Ar b; } });
```

mutualrec2.d-mixin-1(1): Error: undefined identifier `Br`, did 
you mean class `Ar`?


This seems like a surprising limitation of mixin, though, which 
isn't highlighted by the spec.


Mutually recursive template expansion

2021-10-01 Thread Stephen via Digitalmars-d-learn
I've been trying out templates in more depth and one thing I was 
wondering was whether template expansions with circular 
dependencies might work.

Here is an example that doesn't work:
```d
mixin(A!());
mixin(B!());

void main() {}

template A() {
const char[] A = q{
struct Ar {
Br b;
}
};
}

template B() {
const char[] B = q{
struct Br {
Ar a;
}
};
}
```
This code should work should mutual recursion be supported. How 
might I get it to work properly (without sacrificing recursion or 
templates)?