Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
cb8f11b
Add enum union support and tests
MetaLang Aug 29, 2026
eb26827
Implement enum union pattern matching
MetaLang Sep 8, 2026
dc12fe5
Fix enum union discard pattern example
MetaLang Sep 8, 2026
1df717e
Add enum union POC and pattern matching
MetaLang Sep 10, 2026
8b43551
Extend enum union pattern matching POC
MetaLang Sep 10, 2026
1c1f683
Fix enum union payload access in CTFE
MetaLang Sep 13, 2026
2b9d6f2
Add enum union reflection and variant declarations
MetaLang Sep 13, 2026
f30fb32
Add enum union variantKind trait
MetaLang Sep 13, 2026
e187d6a
Add enum union variant reflection and splicing
MetaLang Sep 14, 2026
6e72c37
Require semicolons for enum union case declarations
MetaLang Sep 14, 2026
611d6c6
Support interleaved enum union declarations
MetaLang Sep 14, 2026
a204386
Update enum union syntax tests and specification
MetaLang Sep 14, 2026
158a8d0
Improve enum union diagnostics, parse recovery, and variant resolution
MetaLang Sep 23, 2026
1380b4f
Refactor and harden enum union diagnostics, codegen, and lifecycle ha…
MetaLang Sep 24, 2026
14da1a2
Support static foreach and static if inside switch expressions
MetaLang Sep 24, 2026
0b6f020
Fix C++ interop tests
MetaLang Sep 25, 2026
197164d
Fix trailing whitespace and missing EOF newlines in enum union tests
MetaLang Sep 25, 2026
e2cd9a2
Fix CaseExpArm syntaxCopy in ASTBase for StaticForeach and Condition
MetaLang Sep 25, 2026
d95b348
Restore overloadSet check in findStructConstructorRoot
MetaLang Sep 25, 2026
b236973
Fix Azure CI Windows 64 test failures: parser recovery, call semantic…
MetaLang Sep 25, 2026
b06921c
Fix Linux 64 CI test failures: alias variant resolution, parser recov…
MetaLang Sep 25, 2026
318d309
Stabilize enum union test baseline
MetaLang Sep 25, 2026
042c061
Expose enum union tag as a read-only property
MetaLang Sep 25, 2026
e2625f6
Restore enum union construction lifecycle
MetaLang Sep 25, 2026
bd13c3f
Restrict enum union payload patterns to bindings
MetaLang Sep 25, 2026
e77d7aa
Preserve pattern matrix for variant coverage
MetaLang Sep 25, 2026
5f397b7
Reuse unpack declarations for tuple patterns
MetaLang Sep 25, 2026
38d926b
Account for switch pattern side effects
MetaLang Sep 25, 2026
6d50f0e
Harden enum union parsing and header generation
MetaLang Sep 25, 2026
66a9c8e
Reconcile enum union grammar and documentation
MetaLang Sep 25, 2026
5eb2c02
Audit enum union AST ownership and visitors
MetaLang Sep 25, 2026
2d763a5
Fix enum union transitive traversal
MetaLang Sep 25, 2026
8c5fbeb
Avoid stale foreach parameter access
MetaLang Sep 25, 2026
4622ea5
Remove internal enum union plans
MetaLang Sep 25, 2026
2945355
Rename enum union tag trait
MetaLang Sep 25, 2026
0624e0e
Consolidate enum union test suite redundancies
MetaLang Sep 25, 2026
6996d8c
Clean up enum union files
MetaLang Sep 25, 2026
87eb1be
Add enum union variant reflection
MetaLang Sep 25, 2026
85b8356
Fix duplicate enumUnion in location_offset unit test
MetaLang Sep 29, 2026
c859678
Fix CaseExpArm in ASTCodegen and declare EnumUnionDeclaration in C++ …
MetaLang Sep 29, 2026
d236749
Fix template instance lookup regression in member expressions
MetaLang Sep 29, 2026
3341aa8
Fix with-scope template member calls and null scope handling in toDsy…
MetaLang Sep 29, 2026
7e8deb8
Fix cxxfrontend visitor vtable alignment and 32-bit x86 cdcond regist…
MetaLang Sep 30, 2026
aaa8646
Fix circular selective import of dmd.cond in expression.d
MetaLang Sep 30, 2026
26efb2a
Unify EnumUnionDeclaration inheritance across ASTBase and ASTCodegen
MetaLang Sep 30, 2026
face0b6
Complete Visitor support for EnumUnion, EnumUnionCaseDeclaration, and…
MetaLang Sep 30, 2026
c64d128
Fix D-Scanner style warnings in parse.d and astbase.d
MetaLang Sep 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions compiler/include/dmd/aggregate.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,15 @@ class UnionDeclaration final : public StructDeclaration
void accept(Visitor *v) override { v->visit(this); }
};

class EnumUnionDeclaration final : public StructDeclaration
{
public:
EnumUnionDeclaration *syntaxCopy(Dsymbol *s) override;
const char *kind() const override;

void accept(Visitor *v) override { v->visit(this); }
};

struct BaseClass
{
Type *type; // (before semantic processing)
Expand Down
9 changes: 9 additions & 0 deletions compiler/include/dmd/declaration.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,15 @@ class TupleDeclaration final : public Declaration
void accept(Visitor *v) override { v->visit(this); }
};

class EnumUnionCaseDeclaration final : public Declaration
{
public:
EnumUnionCaseDeclaration *syntaxCopy(Dsymbol *) override;
const char *kind() const override;

void accept(Visitor *v) override { v->visit(this); }
};

/**************************************************************/

class AliasDeclaration final : public Declaration
Expand Down
6 changes: 4 additions & 2 deletions compiler/include/dmd/dsymbol.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ class AggregateDeclaration;
class EnumDeclaration;
class ClassDeclaration;
class StructDeclaration;
class InterfaceDeclaration;
class StructDeclaration;
class UnionDeclaration;
class EnumUnionDeclaration;
class EnumUnionCaseDeclaration;
class FuncDeclaration;
class FuncAliasDeclaration;
class OverDeclaration;
Expand Down Expand Up @@ -290,6 +290,7 @@ class Dsymbol : public ASTNode
ClassDeclaration *isClassDeclaration();
StructDeclaration *isStructDeclaration();
UnionDeclaration *isUnionDeclaration();
EnumUnionDeclaration *isEnumUnionDeclaration();
InterfaceDeclaration *isInterfaceDeclaration();
ScopeDsymbol *isScopeDsymbol();
ForwardingScopeDsymbol *isForwardingScopeDsymbol();
Expand All @@ -307,6 +308,7 @@ class Dsymbol : public ASTNode
StaticAssert *isStaticAssert();
StaticIfDeclaration *isStaticIfDeclaration();
CAsmDeclaration *isCAsmDeclaration();
EnumUnionCaseDeclaration *isEnumUnionCaseDeclaration();
void accept(Visitor *v) override { v->visit(this); }
};

Expand Down
15 changes: 15 additions & 0 deletions compiler/include/dmd/expression.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class OverloadSet;
class StringExp;
class InterpExp;
class LoweredAssignExp;
class SwitchExp;
class StaticForeach;
#ifdef IN_GCC
typedef union tree_node Symbol;
Expand Down Expand Up @@ -215,6 +216,7 @@ class Expression : public ASTNode
EqualExp* isEqualExp();
IdentityExp* isIdentityExp();
CondExp* isCondExp();
SwitchExp* isSwitchExp();
GenericExp* isGenericExp();
DefaultInitExp* isDefaultInitExp();
ClassReferenceExp* isClassReferenceExp();
Expand Down Expand Up @@ -1243,6 +1245,19 @@ class CondExp final : public BinExp
void accept(Visitor *v) override { v->visit(this); }
};

struct CaseExpArm;

class SwitchExp final : public Expression
{
public:
Expression *condition;
DArray<CaseExpArm> arms;
bool hasDefault;

SwitchExp *syntaxCopy() override;
void accept(Visitor *v) override { v->visit(this); }
};

class GenericExp final : Expression
{
Expression *cntlExp;
Expand Down
2 changes: 2 additions & 0 deletions compiler/include/dmd/tokens.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ enum class TOK : unsigned char
interface_,
union_,
enum_,
enumUnion,
import_,
alias_,
override_,
Expand Down Expand Up @@ -384,6 +385,7 @@ enum class EXP : unsigned char
dot,
comma,
question,
switchExpression,
andAnd,
orOr,
prePlusPlus,
Expand Down
6 changes: 6 additions & 0 deletions compiler/include/dmd/visitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ class CAsmDeclaration;
class AggregateDeclaration;
class StructDeclaration;
class UnionDeclaration;
class EnumUnionDeclaration;
class ClassDeclaration;
class InterfaceDeclaration;

Expand All @@ -140,6 +141,7 @@ class TupleDeclaration;
class AliasDeclaration;
class OverDeclaration;
class VarDeclaration;
class EnumUnionCaseDeclaration;
class SymbolDeclaration;
class ThisDeclaration;
class BitFieldDeclaration;
Expand Down Expand Up @@ -298,6 +300,7 @@ class ClassReferenceExp;
class VoidInitExp;
class ThrownExceptionExp;
class GenericExp;
class SwitchExp;

class TemplateParameter;
class TemplateTypeParameter;
Expand Down Expand Up @@ -351,6 +354,7 @@ class ParseTimeVisitor
virtual void visit(FuncDeclaration *s) { visit((Declaration *)s); }
virtual void visit(AliasDeclaration *s) { visit((Declaration *)s); }
virtual void visit(TupleDeclaration *s) { visit((Declaration *)s); }
virtual void visit(EnumUnionCaseDeclaration *s) { visit((Declaration *)s); }

// FuncDeclarations
virtual void visit(FuncLiteralDeclaration *s) { visit((FuncDeclaration *)s); }
Expand Down Expand Up @@ -387,6 +391,7 @@ class ParseTimeVisitor
virtual void visit(Module *s) { visit((Package *)s); }
virtual void visit(StructDeclaration *s) { visit((AggregateDeclaration *)s); }
virtual void visit(UnionDeclaration *s) { visit((StructDeclaration *)s); }
virtual void visit(EnumUnionDeclaration *s) { visit((StructDeclaration *)s); }
virtual void visit(ClassDeclaration *s) { visit((AggregateDeclaration *)s); }
virtual void visit(InterfaceDeclaration *s) { visit((ClassDeclaration *)s); }
virtual void visit(TemplateMixin *s) { visit((TemplateInstance *)s); }
Expand Down Expand Up @@ -499,6 +504,7 @@ class ParseTimeVisitor
virtual void visit(TupleExp *e) { visit((Expression *)e); }
virtual void visit(ThisExp *e) { visit((Expression *)e); }
virtual void visit(GenericExp *e) { visit((Expression *)e); }
virtual void visit(SwitchExp *e) { visit((Expression *)e); }

// Miscellaneous
virtual void visit(VarExp *e) { visit((SymbolExp *)e); }
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/build.d
Original file line number Diff line number Diff line change
Expand Up @@ -1392,7 +1392,7 @@ auto sourceFiles()
access.d aggregate.d aliasthis.d argtypes_x86.d argtypes_sysv_x64.d argtypes_aarch64.d arrayop.d
arraytypes.d astenums.d ast_node.d astcodegen.d asttypename.d attrib.d attribsem.d blockexit.d builtin.d canthrow.d chkformat.d
cli.d clone.d compiler.d cond.d constfold.d cpreprocess.d ctfeexpr.d
ctorflow.d dcast.d dclass.d declaration.d delegatize.d denum.d deps.d dimport.d
ctorflow.d dcast.d dclass.d declaration.d decisiontree.d delegatize.d denum.d deps.d dimport.d
dinterpret.d dmacro.d dmodule.d doc.d dscope.d dstruct.d dsymbol.d dsymbolsem.d
dtemplate.d dtoh.d dversion.d enumsem.d escape.d expression.d expressionsem.d func.d funcsem.d hdrgen.d
impcnvtab.d imphint.d importc.d init.d initsem.d inline.d inlinecost.d intrange.d json.d lambdacomp.d
Expand Down
148 changes: 148 additions & 0 deletions compiler/src/dmd/astbase.d
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ struct ASTBase

alias Visitor = ParseTimeVisitor!ASTBase;


extern (C++) abstract class ASTNode : RootObject
{
abstract void accept(Visitor v);
Expand Down Expand Up @@ -228,6 +229,16 @@ struct ASTBase
return null;
}

inout(EnumUnionDeclaration) isEnumUnionDeclaration() inout
{
return null;
}

inout(EnumUnionCaseDeclaration) isEnumUnionCaseDeclaration() inout
{
return null;
}

inout(ClassDeclaration) isClassDeclaration() inout
{
return null;
Expand Down Expand Up @@ -893,6 +904,40 @@ struct ASTBase
}
}

struct EnumUnionVariant
{
Loc loc;
Identifier ident;
bool isTypeAlias;
Expressions* udas;
Type[] payload;
Identifier[] payloadNames;
Dsymbols* members;
TraitsExp variantSplice;
}

extern (C++) final class EnumUnionCaseDeclaration : Declaration
{
EnumUnionVariant variant;

extern (D) this(Loc loc, EnumUnionVariant variant)
{
super(null);
this.loc = loc;
this.variant = variant;
}

override void accept(Visitor v)
{
v.visit(this);
}

override inout(EnumUnionCaseDeclaration) isEnumUnionCaseDeclaration() inout
{
return this;
}
}

extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
{
Visibility visibility;
Expand Down Expand Up @@ -1491,6 +1536,28 @@ struct ASTBase
}
}

extern (C++) final class EnumUnionDeclaration : StructDeclaration
{
EnumUnionVariant[] variants;
VarDeclaration tagVar;
UnionDeclaration payloadUnion;

extern (D) this(Loc loc, Identifier id)
{
super(loc, id, false);
}

override void accept(Visitor v)
{
v.visit(this);
}

override inout(EnumUnionDeclaration) isEnumUnionDeclaration() inout
{
return this;
}
}

extern (C++) class ClassDeclaration : AggregateDeclaration
{
extern (C++) __gshared
Expand Down Expand Up @@ -4604,6 +4671,7 @@ struct ASTBase
inout(DotIdExp) isDotIdExp() { return op == EXP.dotIdentifier ? cast(typeof(return))this : null; }
inout(DotTemplateInstanceExp) isDotTemplateInstanceExp() { return op == EXP.dotTemplateInstance ? cast(typeof(return))this : null; }
inout(CallExp) isCallExp() { return op == EXP.call ? cast(typeof(return))this : null; }
inout(SwitchExp) isSwitchExp() { return op == EXP.switchExpression ? cast(typeof(return))this : null; }
inout(AddrExp) isAddrExp() { return op == EXP.address ? cast(typeof(return))this : null; }
inout(PtrExp) isPtrExp() { return op == EXP.star ? cast(typeof(return))this : null; }
inout(NegExp) isNegExp() { return op == EXP.negate ? cast(typeof(return))this : null; }
Expand Down Expand Up @@ -5230,6 +5298,7 @@ struct ASTBase
{
Dsymbol s;
bool hasOverloads;
bool preserveSymbol;

extern (D) this(Loc loc, Dsymbol s, bool hasOverloads = true)
{
Expand Down Expand Up @@ -6022,6 +6091,85 @@ struct ASTBase
}
}

struct CaseExpArm
{
Loc loc;
Expression pattern;
Type typePattern;
Identifier typeBinding;
Identifier[] recordBindings;
bool hasRestPattern;
Identifier[] recordPatternNames;
Expression[] recordPatterns;
Identifier restBinding;
Expression guard;
bool isDefault;
Expression action;

StaticForeach sfe;
CaseExpArm[] nestedArms;
Condition staticIfCond;
CaseExpArm[] elseArms;

CaseExpArm syntaxCopy()
{
CaseExpArm copy = this;
copy.pattern = pattern ? pattern.syntaxCopy() : null;
copy.typePattern = typePattern ? typePattern.syntaxCopy() : null;
copy.recordBindings = recordBindings.dup;
copy.recordPatternNames = recordPatternNames.dup;
if (recordPatterns)
{
copy.recordPatterns = new Expression[](recordPatterns.length);
foreach (j, pat; recordPatterns)
copy.recordPatterns[j] = pat ? pat.syntaxCopy() : null;
}
copy.guard = guard ? guard.syntaxCopy() : null;
copy.action = action ? action.syntaxCopy() : null;
if (nestedArms)
{
copy.nestedArms = new CaseExpArm[](nestedArms.length);
foreach (j, ref na; nestedArms)
copy.nestedArms[j] = na.syntaxCopy();
}
if (elseArms)
{
copy.elseArms = new CaseExpArm[](elseArms.length);
foreach (j, ref ea; elseArms)
copy.elseArms[j] = ea.syntaxCopy();
}
return copy;
}
}

extern (C++) final class SwitchExp : Expression
{
Expression condition;
CaseExpArm[] arms;
bool hasDefault;

final extern (D) this(Loc loc, Expression condition, CaseExpArm[] arms, bool hasDefault)
{
super(loc, EXP.switchExpression, __traits(classInstanceSize, SwitchExp));
this.condition = condition;
this.arms = arms;
this.hasDefault = hasDefault;
}

override SwitchExp syntaxCopy()
{
auto copiedArms = new CaseExpArm[](arms.length);
foreach (i, arm; arms)
copiedArms[i] = arm.syntaxCopy();
return new SwitchExp(loc, condition.syntaxCopy(), copiedArms, hasDefault);
}

override void accept(Visitor v)
{
v.visit(this);
}
}

extern (C++) final class AssignExp : BinExp
{
extern (D) this(Loc loc, Expression e1, Expression e2)
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dmd/astcodegen.d
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ struct ASTCodegen
alias Ensure = dmd.func.Ensure; // workaround for bug in older DMD frontends
alias ErrorExp = dmd.expression.ErrorExp;
alias ArgumentLabel = dmd.expression.ArgumentLabel;
alias CaseExpArm = dmd.expression.CaseExpArm;

alias MODFlags = dmd.mtype.MODFlags;
alias Type = dmd.mtype.Type;
Expand Down
4 changes: 4 additions & 0 deletions compiler/src/dmd/backend/x86/cod2.d
Original file line number Diff line number Diff line change
Expand Up @@ -2543,7 +2543,11 @@ void cdcond(ref CGstate cg, ref CodeBuilder cdb,elem* e,ref regm_t pretregs)
fixresult(cg,cdb2,e22,retregs,pretregs);
}
else
{
if (pretregs == 0)
retregs = 0;
codelem(cg,cdb2,e22,retregs,false); // use same regs as E1
}
pretregs = retregs | psw;
andregcon(regconold);
andregcon(regconsave);
Expand Down
Loading
Loading