digitalmars.D.learn - Mutually recursive template expansion
- Stephen (26/26) Oct 01 2021 I've been trying out templates in more depth and one thing I was
- jfondren (14/15) Oct 01 2021 It still wouldn't work, because structs are value types and it's
- Stephen (15/32) Oct 02 2021 All right I'll try to design without mutual recursion but mixins
- Basile B. (25/26) Oct 02 2021 No but it's easily explainable.
- bauss (11/28) Oct 04 2021 Actually it is covered by the spec.
- Paul Backus (6/21) Oct 04 2021 That's not what that sentence means. Here's the full version,
- Imperatorn (3/29) Oct 02 2021 Just curious since I haven't found a use case for this myself,
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)?
Oct 01 2021
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.
Oct 01 2021
On Friday, 1 October 2021 at 14:26:39 UTC, jfondren wrote:On Friday, 1 October 2021 at 14:03:06 UTC, Stephen wrote: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?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.
Oct 02 2021
On Saturday, 2 October 2021 at 08:48:24 UTC, Stephen wrote:Is this by design?No but it's easily explainable. ```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. ```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.
Oct 02 2021
On Friday, 1 October 2021 at 14:26:39 UTC, jfondren wrote:On Friday, 1 October 2021 at 14:03:06 UTC, Stephen 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.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.
Oct 04 2021
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.
Oct 04 2021
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?
Oct 02 2021