www.digitalmars.com         C & C++   DMDScript  

digitalmars.dip.ideas - Named Variables with Anonymous Structs (Inline Struct Variable

reply libxmoc <libxmoc gmail.com> writes:
Problem: Unlike C/C++ (and other recent languages), D does not 
support anonymous nested structures instantiated inline. We must 
invent throwaway type names for single use nested variables, its 
causing boilerplate, visual noise when reading code, and naming 
bugs (eg: InputStat input).

Proposed Solution: Allow variable identifiers to directly follow 
an anonymous struct definition to enable clean, native dot 
notation.

Restriction: Strictly context dependnat grammar rule, only to 
instantiation on definition sites (variable declarations).

```d
struct AppContext {
     struct {
         int width;
         int height;
         bool fullscreen;
     } window; // ctx.window.width

     struct {
         double mouseX;
         double mouseY;
         bool leftClicks;
     } input; // ctx.input.mouseX

     float deltaTime;
}
```

Benefits: Eliminates transient types, keeps layout and 
instantiation together, and enables clean dot notation without 
boilerplate.


I have a patch ready for PR, only touches the parser.
May 28
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Thursday, 28 May 2026 at 07:44:28 UTC, libxmoc wrote:
 I have a patch ready for PR, only touches the parser.
does your patch also work for template args? i'd be interested in seeing it
May 28
next sibling parent libxmoc <libxmoc gmail.com> writes:
On Thursday, 28 May 2026 at 13:18:45 UTC, Adam D. Ruppe wrote:
 On Thursday, 28 May 2026 at 07:44:28 UTC, libxmoc wrote:
 I have a patch ready for PR, only touches the parser.
does your patch also work for template args? i'd be interested in seeing it
You mean this? ```d struct Foo(T) { struct { T x; T y; } vec; } void main() { Foo!int f; f.vec.x = 10; f.vec.y = 20; } ``` Yes it works, if you meant `Wrapper!(struct { int x; int y; }) w;`, then no, I don't see the benefit for this, besides it would make the patch more complex. Here my current patch: ```patch diff --git a/compiler/src/dmd/parse.d b/compiler/src/dmd/parse.d index ef93b59..f250a4f 100644 --- a/compiler/src/dmd/parse.d +++ b/compiler/src/dmd/parse.d -4507,6 +4507,7 class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer bool setAlignment = false; AST.Expression ealign; AST.Expressions* udas = null; + AST.Dsymbol anonStructDecl = null; //printf("parseDeclarations() %s\n", token.toChars()); if (!comment) -4532,7 +4533,7 class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer } const typeLoc = token.loc; - AST.Type ts; + AST.Type ts = null; if (!autodecl) { -4560,36 +4561,57 class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer token.value == TOK.interface_) { AST.Dsymbol s = parseAggregate(); - auto a = new AST.Dsymbols(); - a.push(s); + auto ad = s.isAnonDeclaration(); + if (ad && (token.value == TOK.mul || token.value == TOK.leftParenthesis || + token.value == TOK.leftBracket || + (token.value == TOK.identifier && + (peekNext() == TOK.semicolon || peekNext() == TOK.comma || + peekNext() == TOK.assign)))) + { + auto id = Identifier.generateIdWithLoc("__AnonStruct", s.loc); + bool inObject = md && !md.packages && md.id == Id.object; + if (ad.isunion) + s = new AST.UnionDeclaration(s.loc, id); + else + s = new AST.StructDeclaration(s.loc, id, inObject); + (cast(AST.AggregateDeclaration)s).members = ad.decl; - if (storage_class) - { - s = new AST.StorageClassDeclaration(storage_class, a); - a = new AST.Dsymbols(); - a.push(s); + anonStructDecl = s; + ts = new AST.TypeIdentifier(s.loc, id); } - if (setAlignment) - { - s = new AST.AlignDeclaration(s.loc, ealign, a); - a = new AST.Dsymbols(); - a.push(s); - } - if (link != linkage) - { - s = new AST.LinkDeclaration(linkloc, link, a); - a = new AST.Dsymbols(); - a.push(s); - } - if (udas) + else { - s = new AST.UserAttributeDeclaration(udas, a); - a = new AST.Dsymbols(); + auto a = new AST.Dsymbols(); a.push(s); - } - addComment(s, comment); - return a; + if (storage_class) + { + s = new AST.StorageClassDeclaration(storage_class, a); + a = new AST.Dsymbols(); + a.push(s); + } + if (setAlignment) + { + s = new AST.AlignDeclaration(s.loc, ealign, a); + a = new AST.Dsymbols(); + a.push(s); + } + if (link != linkage) + { + s = new AST.LinkDeclaration(linkloc, link, a); + a = new AST.Dsymbols(); + a.push(s); + } + if (udas) + { + s = new AST.UserAttributeDeclaration(udas, a); + a = new AST.Dsymbols(); + a.push(s); + } + + addComment(s, comment); + return a; + } } /* Look for auto initializers: -4635,7 +4657,8 class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer } else { - ts = parseBasicType(); + if (!ts) + ts = parseBasicType(); ts = parseTypeSuffixes(ts); } } -4651,6 +4674,38 class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer AST.Type tfirst = null; auto a = new AST.Dsymbols(); + if (anonStructDecl) + { + auto ax = new AST.Dsymbols(); + ax.push(anonStructDecl); + AST.Dsymbol s = anonStructDecl; + if (storage_class) + { + s = new AST.StorageClassDeclaration(storage_class, ax); + ax = new AST.Dsymbols(); + ax.push(s); + } + if (setAlignment) + { + s = new AST.AlignDeclaration(s.loc, ealign, ax); + ax = new AST.Dsymbols(); + ax.push(s); + } + if (link != linkage) + { + s = new AST.LinkDeclaration(linkloc, link, ax); + ax = new AST.Dsymbols(); + ax.push(s); + } + if (udas) + { + s = new AST.UserAttributeDeclaration(udas, ax); + ax = new AST.Dsymbols(); + ax.push(s); + } + a.push(s); + } + while (1) { AST.TemplateParameters* tpl = null; ```
May 28
prev sibling parent libxmoc <libxmoc gmail.com> writes:
On Thursday, 28 May 2026 at 13:18:45 UTC, Adam D. Ruppe wrote:
 On Thursday, 28 May 2026 at 07:44:28 UTC, libxmoc wrote:
 I have a patch ready for PR, only touches the parser.
does your patch also work for template args? i'd be interested in seeing it
What do you think about the patch? I'm thinking about writing a formal DIP.
Jun 06