digitalmars.dip.ideas - Named Variables with Anonymous Structs (Inline Struct Variable
- libxmoc (29/29) May 28 Problem: Unlike C/C++ (and other recent languages), D does not
- Adam D. Ruppe (3/4) May 28 does your patch also work for template args? i'd be interested in
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
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
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: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; ```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
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:What do you think about the patch? I'm thinking about writing a formal DIP.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
Jun 06









libxmoc <libxmoc gmail.com> 