From 7f7a9cea78e738fb19cdba8044c31c9e2bbcf626 Mon Sep 17 00:00:00 2001 From: WebFreak001 Date: Wed, 22 Mar 2023 04:46:51 +0100 Subject: [PATCH] make Statement, StatementNoCaseNoDefault and Declaration use SumType old Declaration code used algebraic, which is more efficiently replaced with sumtype. I replaced the mixin-generated properties with manual properties, since the code is very small for them anyway and helps them being shown in DCD Since SumType works with well-defiend types, opEquals and visitIfNotNull was trivial to implement. Saves around 0-3 MB of actual peak RAM in a ~170 MB test environment (could just be fluctuations how much it actually is, but it _will_ definitely include some RAM savings, since we no longer store a bunch of nulls for common types) Easy backwards-compatible improvement I think. Made setters backwards-incompatible on purpose, since we don't want accidental assignment of 2 different types on the same sumtype. --- src/dparse/ast.d | 439 +++++++++++++++++++++++++++++++++----------- src/dparse/parser.d | 144 +++++++-------- 2 files changed, 403 insertions(+), 180 deletions(-) diff --git a/src/dparse/ast.d b/src/dparse/ast.d index c10f80c8..89b06219 100644 --- a/src/dparse/ast.d +++ b/src/dparse/ast.d @@ -16,10 +16,11 @@ module dparse.ast; import dparse.lexer; -import std.traits; import std.algorithm; import std.array; import std.string; +import std.sumtype; +import std.traits; private immutable uint[TypeInfo] typeMap; @@ -392,6 +393,8 @@ template visitIfNotNull(fields ...) immutable visitIfNotNull = "if (" ~ fields[0].stringof ~ " !is null) visitor.visit(" ~ fields[0].stringof ~ ");\n"; else static if (is(Unqual!(typeof(fields[0])) == Token)) immutable visitIfNotNull = "if (" ~ fields[0].stringof ~ ` != tok!""` ~ ") visitor.visit(" ~ fields[0].stringof ~ ");\n"; + else static if (isSumType!(typeof(fields[0]))) + immutable visitIfNotNull = fields[0].stringof ~ ".match!((typeof(null)) {}, v => visitor.visit(v));\n"; else immutable visitIfNotNull = "visitor.visit(" ~ fields[0].stringof ~ ");\n"; } @@ -1290,32 +1293,15 @@ final class DebugSpecification : BaseNode /// final class Declaration : BaseNode { - override void accept(ASTVisitor visitor) const { - - foreach (attr; attributes) - visitor.visit(attr); - foreach (dec; declarations) - visitor.visit(dec); - foreach (Type; DeclarationTypes) - { - const(Type)* value = storage.peek!Type; - if (value !is null) - { - static if (isArray!Type) - foreach (item; *(cast(Type*) value)) - visitor.visit(item); - else if (*value !is null) - visitor.visit(*(cast(Type*) value)); - } - } + mixin (visitIfNotNull!(attributes, declarations, unionType)); } - private import std.variant:Algebraic; - private import std.typetuple:TypeTuple; + private import std.meta : AliasSeq; - alias DeclarationTypes = TypeTuple!(AliasDeclaration, AliasAssign, AliasThisDeclaration, + alias DeclarationTypes = AliasSeq!(typeof(null), + AliasDeclaration, AliasAssign, AliasThisDeclaration, AnonymousEnumDeclaration, AttributeDeclaration, ClassDeclaration, ConditionalDeclaration, Constructor, DebugSpecification, Destructor, EnumDeclaration, EponymousTemplateDeclaration, @@ -1326,58 +1312,152 @@ final class Declaration : BaseNode TemplateDeclaration, UnionDeclaration, Unittest, VariableDeclaration, VersionSpecification, StaticForeachDeclaration); - private Algebraic!(DeclarationTypes) storage; - - private static string generateProperty(string type, string name) - { - return "const(" ~ type ~ ") " ~ name ~ "() const @property { auto p = storage.peek!" ~ type ~ "; return p is null? null : *p;}\n" - ~ "const(" ~ type ~ ") " ~ name ~ "(" ~ type ~ " node) @property { storage = node; return node; }"; - } + /// Use `std.sumtype : match` on this type if you want to check multiple + /// options at once, or use one of the properties below to access single + /// types that return null if they are not of the requested type. + SumType!(DeclarationTypes) unionType; /** */ Attribute[] attributes; /** */ Declaration[] declarations; - mixin(generateProperty("AliasDeclaration", "aliasDeclaration")); - mixin(generateProperty("AliasAssign", "aliasAssign")); - mixin(generateProperty("AliasThisDeclaration", "aliasThisDeclaration")); - mixin(generateProperty("AnonymousEnumDeclaration", "anonymousEnumDeclaration")); - mixin(generateProperty("AttributeDeclaration", "attributeDeclaration")); - mixin(generateProperty("ClassDeclaration", "classDeclaration")); - mixin(generateProperty("ConditionalDeclaration", "conditionalDeclaration")); - mixin(generateProperty("Constructor", "constructor")); - mixin(generateProperty("DebugSpecification", "debugSpecification")); - mixin(generateProperty("Destructor", "destructor")); - mixin(generateProperty("EnumDeclaration", "enumDeclaration")); - mixin(generateProperty("EponymousTemplateDeclaration", "eponymousTemplateDeclaration")); - mixin(generateProperty("FunctionDeclaration", "functionDeclaration")); - mixin(generateProperty("ImportDeclaration", "importDeclaration")); - mixin(generateProperty("InterfaceDeclaration", "interfaceDeclaration")); - mixin(generateProperty("Invariant", "invariant_")); - mixin(generateProperty("MixinDeclaration", "mixinDeclaration")); - mixin(generateProperty("MixinTemplateDeclaration", "mixinTemplateDeclaration")); - mixin(generateProperty("Postblit", "postblit")); - mixin(generateProperty("PragmaDeclaration", "pragmaDeclaration")); - mixin(generateProperty("SharedStaticConstructor", "sharedStaticConstructor")); - mixin(generateProperty("SharedStaticDestructor", "sharedStaticDestructor")); - mixin(generateProperty("StaticAssertDeclaration", "staticAssertDeclaration")); - mixin(generateProperty("StaticConstructor", "staticConstructor")); - mixin(generateProperty("StaticDestructor", "staticDestructor")); - mixin(generateProperty("StructDeclaration", "structDeclaration")); - mixin(generateProperty("TemplateDeclaration", "templateDeclaration")); - mixin(generateProperty("UnionDeclaration", "unionDeclaration")); - mixin(generateProperty("Unittest", "unittest_")); - mixin(generateProperty("VariableDeclaration", "variableDeclaration")); - mixin(generateProperty("VersionSpecification", "versionSpecification")); - mixin(generateProperty("StaticForeachDeclaration", "staticForeachDeclaration")); + /// Getter if this class is of this type. To set, use `setUnionType` + inout(AliasDeclaration) aliasDeclaration() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } - override bool opEquals(Object other) const + /// Getter if this class is of this type. To set, use `setUnionType` + inout(AliasAssign) aliasAssign() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(AliasThisDeclaration) aliasThisDeclaration() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(AnonymousEnumDeclaration) anonymousEnumDeclaration() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(AttributeDeclaration) attributeDeclaration() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(ClassDeclaration) classDeclaration() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(ConditionalDeclaration) conditionalDeclaration() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(Constructor) constructor() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(DebugSpecification) debugSpecification() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(Destructor) destructor() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(EnumDeclaration) enumDeclaration() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(EponymousTemplateDeclaration) eponymousTemplateDeclaration() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(FunctionDeclaration) functionDeclaration() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(ImportDeclaration) importDeclaration() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(InterfaceDeclaration) interfaceDeclaration() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(Invariant) invariant_() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(MixinDeclaration) mixinDeclaration() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(MixinTemplateDeclaration) mixinTemplateDeclaration() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(Postblit) postblit() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(PragmaDeclaration) pragmaDeclaration() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(SharedStaticConstructor) sharedStaticConstructor() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(SharedStaticDestructor) sharedStaticDestructor() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(StaticAssertDeclaration) staticAssertDeclaration() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(StaticConstructor) staticConstructor() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(StaticDestructor) staticDestructor() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(StructDeclaration) structDeclaration() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(TemplateDeclaration) templateDeclaration() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(UnionDeclaration) unionDeclaration() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(Unittest) unittest_() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(VariableDeclaration) variableDeclaration() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(VersionSpecification) versionSpecification() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(StaticForeachDeclaration) staticForeachDeclaration() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + mixin OpEquals; + + /// + T setUnionType(T)(T value) { - auto otherDeclaration = cast(Declaration) other; - if (otherDeclaration is null) - return false; - return attributes == otherDeclaration.attributes - && declarations == otherDeclaration.declarations - && storage == otherDeclaration.storage; + if (value) + unionType = value; + else + unionType = null; + return value; } } @@ -2482,43 +2562,154 @@ final class StatementNoCaseNoDefault : BaseNode { override void accept(ASTVisitor visitor) const { - mixin (visitIfNotNull!(labeledStatement, blockStatement, ifStatement, - whileStatement, doStatement, forStatement, foreachStatement, - switchStatement, finalSwitchStatement, continueStatement, - breakStatement, returnStatement, gotoStatement, withStatement, - synchronizedStatement, tryStatement, - scopeGuardStatement, asmStatement, pragmaStatement, - conditionalStatement, staticAssertStatement, versionSpecification, - debugSpecification, expressionStatement, staticForeachStatement)); - } - /** */ LabeledStatement labeledStatement; - /** */ BlockStatement blockStatement; - /** */ IfStatement ifStatement; - /** */ WhileStatement whileStatement; - /** */ DoStatement doStatement; - /** */ ForStatement forStatement; - /** */ ForeachStatement foreachStatement; - /** */ StaticForeachStatement staticForeachStatement; - /** */ SwitchStatement switchStatement; - /** */ FinalSwitchStatement finalSwitchStatement; - /** */ ContinueStatement continueStatement; - /** */ BreakStatement breakStatement; - /** */ ReturnStatement returnStatement; - /** */ GotoStatement gotoStatement; - /** */ WithStatement withStatement; - /** */ SynchronizedStatement synchronizedStatement; - /** */ TryStatement tryStatement; - /** */ ScopeGuardStatement scopeGuardStatement; - /** */ AsmStatement asmStatement; - /** */ PragmaStatement pragmaStatement; - /** */ ConditionalStatement conditionalStatement; - /** */ StaticAssertStatement staticAssertStatement; - /** */ VersionSpecification versionSpecification; - /** */ DebugSpecification debugSpecification; - /** */ ExpressionStatement expressionStatement; + mixin (visitIfNotNull!(unionType)); + } + + /// Use `std.sumtype : match` on this type if you want to check multiple + /// options at once, or use one of the properties below to access single + /// types that return null if they are not of the requested type. + SumType!( + typeof(null), + LabeledStatement, + BlockStatement, + IfStatement, + WhileStatement, + DoStatement, + ForStatement, + ForeachStatement, + StaticForeachStatement, + SwitchStatement, + FinalSwitchStatement, + ContinueStatement, + BreakStatement, + ReturnStatement, + GotoStatement, + WithStatement, + SynchronizedStatement, + TryStatement, + ScopeGuardStatement, + AsmStatement, + PragmaStatement, + ConditionalStatement, + StaticAssertStatement, + VersionSpecification, + DebugSpecification, + ExpressionStatement + ) unionType; + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(LabeledStatement) labeledStatement() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(BlockStatement) blockStatement() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(IfStatement) ifStatement() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(WhileStatement) whileStatement() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(DoStatement) doStatement() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(ForStatement) forStatement() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(ForeachStatement) foreachStatement() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(StaticForeachStatement) staticForeachStatement() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(SwitchStatement) switchStatement() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(FinalSwitchStatement) finalSwitchStatement() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(ContinueStatement) continueStatement() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(BreakStatement) breakStatement() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(ReturnStatement) returnStatement() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(GotoStatement) gotoStatement() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(WithStatement) withStatement() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(SynchronizedStatement) synchronizedStatement() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(TryStatement) tryStatement() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(ScopeGuardStatement) scopeGuardStatement() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(AsmStatement) asmStatement() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(PragmaStatement) pragmaStatement() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(ConditionalStatement) conditionalStatement() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(StaticAssertStatement) staticAssertStatement() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(VersionSpecification) versionSpecification() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(DebugSpecification) debugSpecification() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(ExpressionStatement) expressionStatement() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + /** */ size_t startLocation; /** */ size_t endLocation; mixin OpEquals; + + /// + T setUnionType(T)(T value) + { + if (value) + unionType = value; + else + unionType = null; + return value; + } } /// @@ -2868,14 +3059,46 @@ final class Statement : BaseNode { override void accept(ASTVisitor visitor) const { - mixin (visitIfNotNull!(statementNoCaseNoDefault, caseStatement, - caseRangeStatement, defaultStatement)); + mixin (visitIfNotNull!(unionType)); } - /** */ StatementNoCaseNoDefault statementNoCaseNoDefault; - /** */ CaseStatement caseStatement; - /** */ CaseRangeStatement caseRangeStatement; - /** */ DefaultStatement defaultStatement; + + /// Use `std.sumtype : match` on this type if you want to check multiple + /// options at once, or use one of the properties below to access single + /// types that return null if they are not of the requested type. + SumType!( + typeof(null), + StatementNoCaseNoDefault, + CaseStatement, + CaseRangeStatement, + DefaultStatement + ) unionType; mixin OpEquals; + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(StatementNoCaseNoDefault) statementNoCaseNoDefault() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(CaseStatement) caseStatement() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(CaseRangeStatement) caseRangeStatement() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// Getter if this class is of this type. To set, use `setUnionType` + inout(DefaultStatement) defaultStatement() inout @safe nothrow pure @nogc + { alias T = typeof(return); return unionType.match!((T ret) => ret, _ => null); } + + /// + T setUnionType(T)(T value) + { + if (value) + unionType = value; + else + unionType = null; + return value; + } } /// diff --git a/src/dparse/parser.d b/src/dparse/parser.d index 0aee2ed3..d820a1b1 100644 --- a/src/dparse/parser.d +++ b/src/dparse/parser.d @@ -2158,7 +2158,7 @@ class Parser } if (currentIs(tok!":")) { - node.attributeDeclaration = parseAttributeDeclaration(attr); + node.setUnionType = parseAttributeDeclaration(attr); mixin(nullCheck!`node.attributeDeclaration`); ownArray(node.attributes, attributes); node.tokens = tokens[startIndex .. index]; @@ -2179,13 +2179,13 @@ class Parser { if (isAuto == DecType.autoVar) { - mixin(nullCheck!`node.variableDeclaration = parseVariableDeclaration(null, true)`); + mixin(nullCheck!`node.setUnionType = parseVariableDeclaration(null, true)`); node.tokens = tokens[startIndex .. index]; return node; } else if (isAuto == DecType.autoFun) { - mixin(nullCheck!`node.functionDeclaration = parseFunctionDeclaration(null, true)`); + mixin(nullCheck!`node.setUnionType = parseFunctionDeclaration(null, true)`); node.tokens = tokens[startIndex .. index]; return node; } @@ -2238,12 +2238,12 @@ class Parser break; case tok!"alias": if (startsWith(tok!"alias", tok!"identifier", tok!"this")) - mixin(parseNodeQ!(`node.aliasThisDeclaration`, `AliasThisDeclaration`)); + mixin(parseNodeQ!(`node.setUnionType`, `AliasThisDeclaration`)); else - mixin(parseNodeQ!(`node.aliasDeclaration`, `AliasDeclaration`)); + mixin(parseNodeQ!(`node.setUnionType`, `AliasDeclaration`)); break; case tok!"class": - mixin(parseNodeQ!(`node.classDeclaration`, `ClassDeclaration`)); + mixin(parseNodeQ!(`node.setUnionType`, `ClassDeclaration`)); break; case tok!"this": if (!mustBeDeclaration && peekIs(tok!"(")) @@ -2256,12 +2256,12 @@ class Parser return null; } if (startsWith(tok!"this", tok!"(", tok!"this", tok!")")) - mixin(parseNodeQ!(`node.postblit`, `Postblit`)); + mixin(parseNodeQ!(`node.setUnionType`, `Postblit`)); else - mixin(parseNodeQ!(`node.constructor`, `Constructor`)); + mixin(parseNodeQ!(`node.setUnionType`, `Constructor`)); break; case tok!"~": - mixin(parseNodeQ!(`node.destructor`, `Destructor`)); + mixin(parseNodeQ!(`node.setUnionType`, `Destructor`)); break; case tok!"enum": immutable b = setBookmark(); @@ -2269,7 +2269,7 @@ class Parser if (currentIsOneOf(tok!":", tok!"{")) { goToBookmark(b); - mixin(parseNodeQ!(`node.anonymousEnumDeclaration`, `AnonymousEnumDeclaration`)); + mixin(parseNodeQ!(`node.setUnionType`, `AnonymousEnumDeclaration`)); } else if (currentIs(tok!"identifier")) { @@ -2282,43 +2282,43 @@ class Parser if (!currentIs(tok!"=")) { goToBookmark(b); - node.functionDeclaration = parseFunctionDeclaration(null, true, node.attributes); + node.setUnionType = parseFunctionDeclaration(null, true, node.attributes); mixin (nullCheck!`node.functionDeclaration`); } else { goToBookmark(b); - mixin(parseNodeQ!(`node.eponymousTemplateDeclaration`, `EponymousTemplateDeclaration`)); + mixin(parseNodeQ!(`node.setUnionType`, `EponymousTemplateDeclaration`)); } } else if (currentIsOneOf(tok!":", tok!"{", tok!";")) { goToBookmark(b); - mixin(parseNodeQ!(`node.enumDeclaration`, `EnumDeclaration`)); + mixin(parseNodeQ!(`node.setUnionType`, `EnumDeclaration`)); } else { immutable bool eq = currentIs(tok!"="); goToBookmark(b); - mixin (nullCheck!`node.variableDeclaration = parseVariableDeclaration(null, eq)`); + mixin (nullCheck!`node.setUnionType = parseVariableDeclaration(null, eq)`); } } else { immutable bool s = isStorageClass(); goToBookmark(b); - mixin (nullCheck!`node.variableDeclaration = parseVariableDeclaration(null, s)`); + mixin (nullCheck!`node.setUnionType = parseVariableDeclaration(null, s)`); } break; case tok!"import": - mixin(parseNodeQ!(`node.importDeclaration`, `ImportDeclaration`)); + mixin(parseNodeQ!(`node.setUnionType`, `ImportDeclaration`)); break; case tok!"interface": - mixin(parseNodeQ!(`node.interfaceDeclaration`, `InterfaceDeclaration`)); + mixin(parseNodeQ!(`node.setUnionType`, `InterfaceDeclaration`)); break; case tok!"mixin": if (peekIs(tok!"template")) - mixin(parseNodeQ!(`node.mixinTemplateDeclaration`, `MixinTemplateDeclaration`)); + mixin(parseNodeQ!(`node.setUnionType`, `MixinTemplateDeclaration`)); else { immutable b = setBookmark(); @@ -2329,7 +2329,7 @@ class Parser if (t !is null && t.type == tok!";") { goToBookmark(b); - mixin(parseNodeQ!(`node.mixinDeclaration`, `MixinDeclaration`)); + mixin(parseNodeQ!(`node.setUnionType`, `MixinDeclaration`)); } else { @@ -2341,54 +2341,54 @@ class Parser else { goToBookmark(b); - mixin(parseNodeQ!(`node.mixinDeclaration`, `MixinDeclaration`)); + mixin(parseNodeQ!(`node.setUnionType`, `MixinDeclaration`)); } } break; case tok!"pragma": - mixin(parseNodeQ!(`node.pragmaDeclaration`, `PragmaDeclaration`)); + mixin(parseNodeQ!(`node.setUnionType`, `PragmaDeclaration`)); break; case tok!"shared": if (startsWith(tok!"shared", tok!"static", tok!"this")) - mixin(parseNodeQ!(`node.sharedStaticConstructor`, `SharedStaticConstructor`)); + mixin(parseNodeQ!(`node.setUnionType`, `SharedStaticConstructor`)); else if (startsWith(tok!"shared", tok!"static", tok!"~")) - mixin(parseNodeQ!(`node.sharedStaticDestructor`, `SharedStaticDestructor`)); + mixin(parseNodeQ!(`node.setUnionType`, `SharedStaticDestructor`)); else goto type; break; case tok!"static": if (peekIs(tok!"this")) - mixin(parseNodeQ!(`node.staticConstructor`, `StaticConstructor`)); + mixin(parseNodeQ!(`node.setUnionType`, `StaticConstructor`)); else if (peekIs(tok!"~")) - mixin(parseNodeQ!(`node.staticDestructor`, `StaticDestructor`)); + mixin(parseNodeQ!(`node.setUnionType`, `StaticDestructor`)); else if (peekIs(tok!"if")) - mixin (nullCheck!`node.conditionalDeclaration = parseConditionalDeclaration(strict, inTemplateDeclaration)`); + mixin (nullCheck!`node.setUnionType = parseConditionalDeclaration(strict, inTemplateDeclaration)`); else if (peekIs(tok!"assert")) - mixin(parseNodeQ!(`node.staticAssertDeclaration`, `StaticAssertDeclaration`)); + mixin(parseNodeQ!(`node.setUnionType`, `StaticAssertDeclaration`)); else if (peekIs(tok!"foreach") || peekIs(tok!"foreach_reverse")) - mixin(nullCheck!(`node.staticForeachDeclaration = parseStaticForeachDeclaration(inTemplateDeclaration)`)); + mixin(nullCheck!(`node.setUnionType = parseStaticForeachDeclaration(inTemplateDeclaration)`)); else goto type; break; case tok!"struct": - mixin(parseNodeQ!(`node.structDeclaration`, `StructDeclaration`)); + mixin(parseNodeQ!(`node.setUnionType`, `StructDeclaration`)); break; case tok!"template": - mixin(parseNodeQ!(`node.templateDeclaration`, `TemplateDeclaration`)); + mixin(parseNodeQ!(`node.setUnionType`, `TemplateDeclaration`)); break; case tok!"union": - mixin(parseNodeQ!(`node.unionDeclaration`, `UnionDeclaration`)); + mixin(parseNodeQ!(`node.setUnionType`, `UnionDeclaration`)); break; case tok!"invariant": - mixin(parseNodeQ!(`node.invariant_`, `Invariant`)); + mixin(parseNodeQ!(`node.setUnionType`, `Invariant`)); break; case tok!"unittest": - mixin(parseNodeQ!(`node.unittest_`, `Unittest`)); + mixin(parseNodeQ!(`node.setUnionType`, `Unittest`)); break; case tok!"identifier": if (inTemplateDeclaration && peekIs(tok!"=")) { - mixin(parseNodeQ!(`node.aliasAssign`, `AliasAssign`)); + mixin(parseNodeQ!(`node.setUnionType`, `AliasAssign`)); break; } else @@ -2412,13 +2412,13 @@ class Parser } const b2 = setBookmark(); auto savedComment = comment; - node.variableDeclaration = parseVariableDeclaration(t, false); + node.setUnionType = parseVariableDeclaration(t, false); if (node.variableDeclaration is null) { goToBookmark(b2); if (savedComment && comment is null) comment = savedComment; - node.functionDeclaration = parseFunctionDeclaration(t, false); + node.setUnionType = parseFunctionDeclaration(t, false); } else abandonBookmark(b2); if (!node.variableDeclaration && !node.functionDeclaration) @@ -2429,9 +2429,9 @@ class Parser break; case tok!"version": if (peekIs(tok!"(")) - mixin (nullCheck!`node.conditionalDeclaration = parseConditionalDeclaration(strict, inTemplateDeclaration)`); + mixin (nullCheck!`node.setUnionType = parseConditionalDeclaration(strict, inTemplateDeclaration)`); else if (peekIs(tok!"=")) - mixin(parseNodeQ!(`node.versionSpecification`, `VersionSpecification`)); + mixin(parseNodeQ!(`node.setUnionType`, `VersionSpecification`)); else { error("`=` or `(` expected following `version`"); @@ -2440,9 +2440,9 @@ class Parser break; case tok!"debug": if (peekIs(tok!"=")) - mixin(parseNodeQ!(`node.debugSpecification`, `DebugSpecification`)); + mixin(parseNodeQ!(`node.setUnionType`, `DebugSpecification`)); else - mixin (nullCheck!`node.conditionalDeclaration = parseConditionalDeclaration(strict, inTemplateDeclaration)`); + mixin (nullCheck!`node.setUnionType = parseConditionalDeclaration(strict, inTemplateDeclaration)`); break; default: error("Declaration expected"); @@ -6097,15 +6097,15 @@ class Parser if (argumentList is null) return null; if (argumentList.items.length == 1 && startsWith(tok!":", tok!"..")) - node.caseRangeStatement = parseCaseRangeStatement(argumentList.items[0]); + node.setUnionType = parseCaseRangeStatement(argumentList.items[0]); else - node.caseStatement = parseCaseStatement(argumentList); + node.setUnionType = parseCaseStatement(argumentList); break; case tok!"default": - mixin(parseNodeQ!(`node.defaultStatement`, `DefaultStatement`)); + mixin(parseNodeQ!(`node.setUnionType`, `DefaultStatement`)); break; default: - mixin(parseNodeQ!(`node.statementNoCaseNoDefault`, `StatementNoCaseNoDefault`)); + mixin(parseNodeQ!(`node.setUnionType`, `StatementNoCaseNoDefault`)); break; } node.tokens = tokens[startIndex .. index]; @@ -6153,61 +6153,61 @@ class Parser switch (current.type) { case tok!"{": - mixin(parseNodeQ!(`node.blockStatement`, `BlockStatement`)); + mixin(parseNodeQ!(`node.setUnionType`, `BlockStatement`)); break; case tok!"if": - mixin(parseNodeQ!(`node.ifStatement`, `IfStatement`)); + mixin(parseNodeQ!(`node.setUnionType`, `IfStatement`)); break; case tok!"while": - mixin(parseNodeQ!(`node.whileStatement`, `WhileStatement`)); + mixin(parseNodeQ!(`node.setUnionType`, `WhileStatement`)); break; case tok!"do": - mixin(parseNodeQ!(`node.doStatement`, `DoStatement`)); + mixin(parseNodeQ!(`node.setUnionType`, `DoStatement`)); break; case tok!"for": - mixin(parseNodeQ!(`node.forStatement`, `ForStatement`)); + mixin(parseNodeQ!(`node.setUnionType`, `ForStatement`)); break; case tok!"foreach": case tok!"foreach_reverse": - mixin(parseNodeQ!(`node.foreachStatement`, `ForeachStatement`)); + mixin(parseNodeQ!(`node.setUnionType`, `ForeachStatement`)); break; case tok!"switch": - mixin(parseNodeQ!(`node.switchStatement`, `SwitchStatement`)); + mixin(parseNodeQ!(`node.setUnionType`, `SwitchStatement`)); break; case tok!"continue": - mixin(parseNodeQ!(`node.continueStatement`, `ContinueStatement`)); + mixin(parseNodeQ!(`node.setUnionType`, `ContinueStatement`)); break; case tok!"break": - mixin(parseNodeQ!(`node.breakStatement`, `BreakStatement`)); + mixin(parseNodeQ!(`node.setUnionType`, `BreakStatement`)); break; case tok!"return": - mixin(parseNodeQ!(`node.returnStatement`, `ReturnStatement`)); + mixin(parseNodeQ!(`node.setUnionType`, `ReturnStatement`)); break; case tok!"goto": - mixin(parseNodeQ!(`node.gotoStatement`, `GotoStatement`)); + mixin(parseNodeQ!(`node.setUnionType`, `GotoStatement`)); break; case tok!"with": - mixin(parseNodeQ!(`node.withStatement`, `WithStatement`)); + mixin(parseNodeQ!(`node.setUnionType`, `WithStatement`)); break; case tok!"synchronized": - mixin(parseNodeQ!(`node.synchronizedStatement`, `SynchronizedStatement`)); + mixin(parseNodeQ!(`node.setUnionType`, `SynchronizedStatement`)); break; case tok!"try": - mixin(parseNodeQ!(`node.tryStatement`, `TryStatement`)); + mixin(parseNodeQ!(`node.setUnionType`, `TryStatement`)); break; case tok!"scope": - mixin(parseNodeQ!(`node.scopeGuardStatement`, `ScopeGuardStatement`)); + mixin(parseNodeQ!(`node.setUnionType`, `ScopeGuardStatement`)); break; case tok!"asm": - mixin(parseNodeQ!(`node.asmStatement`, `AsmStatement`)); + mixin(parseNodeQ!(`node.setUnionType`, `AsmStatement`)); break; case tok!"pragma": - mixin(parseNodeQ!(`node.pragmaStatement`, `PragmaStatement`)); + mixin(parseNodeQ!(`node.setUnionType`, `PragmaStatement`)); break; case tok!"final": if (peekIs(tok!"switch")) { - mixin(parseNodeQ!(`node.finalSwitchStatement`, `FinalSwitchStatement`)); + mixin(parseNodeQ!(`node.setUnionType`, `FinalSwitchStatement`)); break; } else @@ -6217,23 +6217,23 @@ class Parser } case tok!"debug": if (peekIs(tok!"=")) - mixin(parseNodeQ!(`node.debugSpecification`, `DebugSpecification`)); + mixin(parseNodeQ!(`node.setUnionType`, `DebugSpecification`)); else - mixin(parseNodeQ!(`node.conditionalStatement`, `ConditionalStatement`)); + mixin(parseNodeQ!(`node.setUnionType`, `ConditionalStatement`)); break; case tok!"version": if (peekIs(tok!"=")) - mixin(parseNodeQ!(`node.versionSpecification`, `VersionSpecification`)); + mixin(parseNodeQ!(`node.setUnionType`, `VersionSpecification`)); else - mixin(parseNodeQ!(`node.conditionalStatement`, `ConditionalStatement`)); + mixin(parseNodeQ!(`node.setUnionType`, `ConditionalStatement`)); break; case tok!"static": if (peekIs(tok!"if")) - mixin(parseNodeQ!(`node.conditionalStatement`, `ConditionalStatement`)); + mixin(parseNodeQ!(`node.setUnionType`, `ConditionalStatement`)); else if (peekIs(tok!"assert")) - mixin(parseNodeQ!(`node.staticAssertStatement`, `StaticAssertStatement`)); + mixin(parseNodeQ!(`node.setUnionType`, `StaticAssertStatement`)); else if (peekIs(tok!"foreach") || peekIs(tok!"foreach_reverse")) - mixin(parseNodeQ!(`node.staticForeachStatement`, `StaticForeachStatement`)); + mixin(parseNodeQ!(`node.setUnionType`, `StaticForeachStatement`)); else { error("`if`, `assert`, `foreach` or `foreach_reverse` expected."); @@ -6243,14 +6243,14 @@ class Parser case tok!"identifier": if (peekIs(tok!":")) { - mixin(parseNodeQ!(`node.labeledStatement`, `LabeledStatement`)); + mixin(parseNodeQ!(`node.setUnionType`, `LabeledStatement`)); break; } goto default; case tok!"delete": case tok!"assert": default: - mixin(parseNodeQ!(`node.expressionStatement`, `ExpressionStatement`)); + mixin(parseNodeQ!(`node.setUnionType`, `ExpressionStatement`)); break; } node.endLocation = tokens[index - 1].index; @@ -6354,7 +6354,7 @@ class Parser * | $(LITERAL 'override') * | $(LITERAL 'pure') * | $(LITERAL 'ref') - * | $(LITERAL '___gshared') + * | $(LITERAL '__gshared') * | $(LITERAL 'scope') * | $(LITERAL 'static') * | $(LITERAL 'synchronized')