| /* Compiler implementation of the D programming language | |
| * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved | |
| * written by Walter Bright | |
| * https://www.digitalmars.com | |
| * Distributed under the Boost Software License, Version 1.0. | |
| * https://www.boost.org/LICENSE_1_0.txt | |
| * https://github.com/dlang/dmd/blob/master/src/dmd/expression.h | |
| */ | |
| #pragma once | |
| #include "ast_node.h" | |
| #include "globals.h" | |
| #include "arraytypes.h" | |
| #include "visitor.h" | |
| #include "tokens.h" | |
| #include "root/complex_t.h" | |
| #include "root/dcompat.h" | |
| #include "root/optional.h" | |
| class Type; | |
| class TypeVector; | |
| struct Scope; | |
| class TupleDeclaration; | |
| class VarDeclaration; | |
| class FuncDeclaration; | |
| class FuncLiteralDeclaration; | |
| class CtorDeclaration; | |
| class Dsymbol; | |
| class ScopeDsymbol; | |
| class Expression; | |
| class Declaration; | |
| class StructDeclaration; | |
| class TemplateInstance; | |
| class TemplateDeclaration; | |
| class ClassDeclaration; | |
| class OverloadSet; | |
| class StringExp; | |
| struct UnionExp; | |
| #ifdef IN_GCC | |
| typedef union tree_node Symbol; | |
| #else | |
| struct Symbol; // back end symbol | |
| #endif | |
| void expandTuples(Expressions *exps); | |
| bool isTrivialExp(Expression *e); | |
| bool hasSideEffect(Expression *e, bool assumeImpureCalls = false); | |
| enum BE : int32_t; | |
| BE canThrow(Expression *e, FuncDeclaration *func, bool mustNotThrow); | |
| typedef unsigned char OwnedBy; | |
| enum | |
| { | |
| OWNEDcode, // normal code expression in AST | |
| OWNEDctfe, // value expression for CTFE | |
| OWNEDcache // constant value cached for CTFE | |
| }; | |
| #define WANTvalue 0 // default | |
| #define WANTexpand 1 // expand const/immutable variables if possible | |
| /** | |
| * Specifies how the checkModify deals with certain situations | |
| */ | |
| enum class ModifyFlags | |
| { | |
| /// Issue error messages on invalid modifications of the variable | |
| none, | |
| /// No errors are emitted for invalid modifications | |
| noError = 0x1, | |
| /// The modification occurs for a subfield of the current variable | |
| fieldAssign = 0x2, | |
| }; | |
| class Expression : public ASTNode | |
| { | |
| public: | |
| EXP op; // to minimize use of dynamic_cast | |
| unsigned char size; // # of bytes in Expression so we can copy() it | |
| unsigned char parens; // if this is a parenthesized expression | |
| Type *type; // !=NULL means that semantic() has been run | |
| Loc loc; // file location | |
| static void _init(); | |
| Expression *copy(); | |
| virtual Expression *syntaxCopy(); | |
| // kludge for template.isExpression() | |
| DYNCAST dyncast() const { return DYNCAST_EXPRESSION; } | |
| const char *toChars() const; | |
| void error(const char *format, ...) const; | |
| void warning(const char *format, ...) const; | |
| void deprecation(const char *format, ...) const; | |
| virtual dinteger_t toInteger(); | |
| virtual uinteger_t toUInteger(); | |
| virtual real_t toReal(); | |
| virtual real_t toImaginary(); | |
| virtual complex_t toComplex(); | |
| virtual StringExp *toStringExp(); | |
| virtual bool isLvalue(); | |
| virtual Expression *toLvalue(Scope *sc, Expression *e); | |
| virtual Expression *modifiableLvalue(Scope *sc, Expression *e); | |
| Expression *implicitCastTo(Scope *sc, Type *t); | |
| MATCH implicitConvTo(Type *t); | |
| Expression *castTo(Scope *sc, Type *t); | |
| virtual Expression *resolveLoc(const Loc &loc, Scope *sc); | |
| virtual bool checkType(); | |
| virtual bool checkValue(); | |
| bool checkDeprecated(Scope *sc, Dsymbol *s); | |
| virtual Expression *addDtorHook(Scope *sc); | |
| Expression *addressOf(); | |
| Expression *deref(); | |
| Expression *optimize(int result, bool keepLvalue = false); | |
| // Entry point for CTFE. | |
| // A compile-time result is required. Give an error if not possible | |
| Expression *ctfeInterpret(); | |
| int isConst(); | |
| virtual Optional<bool> toBool(); | |
| virtual bool hasCode() | |
| { | |
| return true; | |
| } | |
| IntegerExp* isIntegerExp(); | |
| ErrorExp* isErrorExp(); | |
| VoidInitExp* isVoidInitExp(); | |
| RealExp* isRealExp(); | |
| ComplexExp* isComplexExp(); | |
| IdentifierExp* isIdentifierExp(); | |
| DollarExp* isDollarExp(); | |
| DsymbolExp* isDsymbolExp(); | |
| ThisExp* isThisExp(); | |
| SuperExp* isSuperExp(); | |
| NullExp* isNullExp(); | |
| StringExp* isStringExp(); | |
| TupleExp* isTupleExp(); | |
| ArrayLiteralExp* isArrayLiteralExp(); | |
| AssocArrayLiteralExp* isAssocArrayLiteralExp(); | |
| StructLiteralExp* isStructLiteralExp(); | |
| TypeExp* isTypeExp(); | |
| ScopeExp* isScopeExp(); | |
| TemplateExp* isTemplateExp(); | |
| NewExp* isNewExp(); | |
| NewAnonClassExp* isNewAnonClassExp(); | |
| SymOffExp* isSymOffExp(); | |
| VarExp* isVarExp(); | |
| OverExp* isOverExp(); | |
| FuncExp* isFuncExp(); | |
| DeclarationExp* isDeclarationExp(); | |
| TypeidExp* isTypeidExp(); | |
| TraitsExp* isTraitsExp(); | |
| HaltExp* isHaltExp(); | |
| IsExp* isExp(); | |
| MixinExp* isMixinExp(); | |
| ImportExp* isImportExp(); | |
| AssertExp* isAssertExp(); | |
| DotIdExp* isDotIdExp(); | |
| DotTemplateExp* isDotTemplateExp(); | |
| DotVarExp* isDotVarExp(); | |
| DotTemplateInstanceExp* isDotTemplateInstanceExp(); | |
| DelegateExp* isDelegateExp(); | |
| DotTypeExp* isDotTypeExp(); | |
| CallExp* isCallExp(); | |
| AddrExp* isAddrExp(); | |
| PtrExp* isPtrExp(); | |
| NegExp* isNegExp(); | |
| UAddExp* isUAddExp(); | |
| ComExp* isComExp(); | |
| NotExp* isNotExp(); | |
| DeleteExp* isDeleteExp(); | |
| CastExp* isCastExp(); | |
| VectorExp* isVectorExp(); | |
| VectorArrayExp* isVectorArrayExp(); | |
| SliceExp* isSliceExp(); | |
| ArrayLengthExp* isArrayLengthExp(); | |
| ArrayExp* isArrayExp(); | |
| DotExp* isDotExp(); | |
| CommaExp* isCommaExp(); | |
| IntervalExp* isIntervalExp(); | |
| DelegatePtrExp* isDelegatePtrExp(); | |
| DelegateFuncptrExp* isDelegateFuncptrExp(); | |
| IndexExp* isIndexExp(); | |
| PostExp* isPostExp(); | |
| PreExp* isPreExp(); | |
| AssignExp* isAssignExp(); | |
| ConstructExp* isConstructExp(); | |
| BlitExp* isBlitExp(); | |
| AddAssignExp* isAddAssignExp(); | |
| MinAssignExp* isMinAssignExp(); | |
| MulAssignExp* isMulAssignExp(); | |
| DivAssignExp* isDivAssignExp(); | |
| ModAssignExp* isModAssignExp(); | |
| AndAssignExp* isAndAssignExp(); | |
| OrAssignExp* isOrAssignExp(); | |
| XorAssignExp* isXorAssignExp(); | |
| PowAssignExp* isPowAssignExp(); | |
| ShlAssignExp* isShlAssignExp(); | |
| ShrAssignExp* isShrAssignExp(); | |
| UshrAssignExp* isUshrAssignExp(); | |
| CatAssignExp* isCatAssignExp(); | |
| AddExp* isAddExp(); | |
| MinExp* isMinExp(); | |
| CatExp* isCatExp(); | |
| MulExp* isMulExp(); | |
| DivExp* isDivExp(); | |
| ModExp* isModExp(); | |
| PowExp* isPowExp(); | |
| ShlExp* isShlExp(); | |
| ShrExp* isShrExp(); | |
| UshrExp* isUshrExp(); | |
| AndExp* isAndExp(); | |
| OrExp* isOrExp(); | |
| XorExp* isXorExp(); | |
| LogicalExp* isLogicalExp(); | |
| InExp* isInExp(); | |
| RemoveExp* isRemoveExp(); | |
| EqualExp* isEqualExp(); | |
| IdentityExp* isIdentityExp(); | |
| CondExp* isCondExp(); | |
| GenericExp* isGenericExp(); | |
| DefaultInitExp* isDefaultInitExp(); | |
| FileInitExp* isFileInitExp(); | |
| LineInitExp* isLineInitExp(); | |
| ModuleInitExp* isModuleInitExp(); | |
| FuncInitExp* isFuncInitExp(); | |
| PrettyFuncInitExp* isPrettyFuncInitExp(); | |
| ClassReferenceExp* isClassReferenceExp(); | |
| ThrownExceptionExp* isThrownExceptionExp(); | |
| UnaExp* isUnaExp(); | |
| BinExp* isBinExp(); | |
| BinAssignExp* isBinAssignExp(); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class IntegerExp : public Expression | |
| { | |
| public: | |
| dinteger_t value; | |
| static IntegerExp *create(const Loc &loc, dinteger_t value, Type *type); | |
| static void emplace(UnionExp *pue, const Loc &loc, dinteger_t value, Type *type); | |
| bool equals(const RootObject *o) const; | |
| dinteger_t toInteger(); | |
| real_t toReal(); | |
| real_t toImaginary(); | |
| complex_t toComplex(); | |
| Optional<bool> toBool(); | |
| Expression *toLvalue(Scope *sc, Expression *e); | |
| void accept(Visitor *v) { v->visit(this); } | |
| dinteger_t getInteger() { return value; } | |
| void setInteger(dinteger_t value); | |
| template<int v> | |
| static IntegerExp literal(); | |
| }; | |
| class ErrorExp : public Expression | |
| { | |
| public: | |
| Expression *toLvalue(Scope *sc, Expression *e); | |
| void accept(Visitor *v) { v->visit(this); } | |
| static ErrorExp *errorexp; // handy shared value | |
| }; | |
| class RealExp : public Expression | |
| { | |
| public: | |
| real_t value; | |
| static RealExp *create(const Loc &loc, real_t value, Type *type); | |
| static void emplace(UnionExp *pue, const Loc &loc, real_t value, Type *type); | |
| bool equals(const RootObject *o) const; | |
| dinteger_t toInteger(); | |
| uinteger_t toUInteger(); | |
| real_t toReal(); | |
| real_t toImaginary(); | |
| complex_t toComplex(); | |
| Optional<bool> toBool(); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class ComplexExp : public Expression | |
| { | |
| public: | |
| complex_t value; | |
| static ComplexExp *create(const Loc &loc, complex_t value, Type *type); | |
| static void emplace(UnionExp *pue, const Loc &loc, complex_t value, Type *type); | |
| bool equals(const RootObject *o) const; | |
| dinteger_t toInteger(); | |
| uinteger_t toUInteger(); | |
| real_t toReal(); | |
| real_t toImaginary(); | |
| complex_t toComplex(); | |
| Optional<bool> toBool(); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class IdentifierExp : public Expression | |
| { | |
| public: | |
| Identifier *ident; | |
| static IdentifierExp *create(const Loc &loc, Identifier *ident); | |
| bool isLvalue(); | |
| Expression *toLvalue(Scope *sc, Expression *e); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class DollarExp : public IdentifierExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class DsymbolExp : public Expression | |
| { | |
| public: | |
| Dsymbol *s; | |
| bool hasOverloads; | |
| DsymbolExp *syntaxCopy(); | |
| bool isLvalue(); | |
| Expression *toLvalue(Scope *sc, Expression *e); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class ThisExp : public Expression | |
| { | |
| public: | |
| VarDeclaration *var; | |
| ThisExp *syntaxCopy(); | |
| Optional<bool> toBool(); | |
| bool isLvalue(); | |
| Expression *toLvalue(Scope *sc, Expression *e); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class SuperExp : public ThisExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class NullExp : public Expression | |
| { | |
| public: | |
| bool equals(const RootObject *o) const; | |
| Optional<bool> toBool(); | |
| StringExp *toStringExp(); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class StringExp : public Expression | |
| { | |
| public: | |
| void *string; // char, wchar, or dchar data | |
| size_t len; // number of chars, wchars, or dchars | |
| unsigned char sz; // 1: char, 2: wchar, 4: dchar | |
| unsigned char committed; // !=0 if type is committed | |
| utf8_t postfix; // 'c', 'w', 'd' | |
| OwnedBy ownedByCtfe; | |
| static StringExp *create(const Loc &loc, const char *s); | |
| static StringExp *create(const Loc &loc, const void *s, d_size_t len); | |
| static void emplace(UnionExp *pue, const Loc &loc, const char *s); | |
| bool equals(const RootObject *o) const; | |
| char32_t getCodeUnit(d_size_t i) const; | |
| void setCodeUnit(d_size_t i, char32_t c); | |
| StringExp *toStringExp(); | |
| StringExp *toUTF8(Scope *sc); | |
| Optional<bool> toBool(); | |
| bool isLvalue(); | |
| Expression *toLvalue(Scope *sc, Expression *e); | |
| Expression *modifiableLvalue(Scope *sc, Expression *e); | |
| void accept(Visitor *v) { v->visit(this); } | |
| size_t numberOfCodeUnits(int tynto = 0) const; | |
| void writeTo(void* dest, bool zero, int tyto = 0) const; | |
| }; | |
| // Tuple | |
| class TupleExp : public Expression | |
| { | |
| public: | |
| Expression *e0; // side-effect part | |
| /* Tuple-field access may need to take out its side effect part. | |
| * For example: | |
| * foo().tupleof | |
| * is rewritten as: | |
| * (ref __tup = foo(); tuple(__tup.field0, __tup.field1, ...)) | |
| * The declaration of temporary variable __tup will be stored in TupleExp::e0. | |
| */ | |
| Expressions *exps; | |
| static TupleExp *create(const Loc &loc, Expressions *exps); | |
| TupleExp *syntaxCopy(); | |
| bool equals(const RootObject *o) const; | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class ArrayLiteralExp : public Expression | |
| { | |
| public: | |
| Expression *basis; | |
| Expressions *elements; | |
| OwnedBy ownedByCtfe; | |
| static ArrayLiteralExp *create(const Loc &loc, Expressions *elements); | |
| static void emplace(UnionExp *pue, const Loc &loc, Expressions *elements); | |
| ArrayLiteralExp *syntaxCopy(); | |
| bool equals(const RootObject *o) const; | |
| Expression *getElement(d_size_t i); // use opIndex instead | |
| Expression *opIndex(d_size_t i); | |
| Optional<bool> toBool(); | |
| StringExp *toStringExp(); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class AssocArrayLiteralExp : public Expression | |
| { | |
| public: | |
| Expressions *keys; | |
| Expressions *values; | |
| OwnedBy ownedByCtfe; | |
| bool equals(const RootObject *o) const; | |
| AssocArrayLiteralExp *syntaxCopy(); | |
| Optional<bool> toBool(); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class StructLiteralExp : public Expression | |
| { | |
| public: | |
| StructDeclaration *sd; // which aggregate this is for | |
| Expressions *elements; // parallels sd->fields[] with NULL entries for fields to skip | |
| Type *stype; // final type of result (can be different from sd's type) | |
| Symbol *sym; // back end symbol to initialize with literal | |
| /** pointer to the origin instance of the expression. | |
| * once a new expression is created, origin is set to 'this'. | |
| * anytime when an expression copy is created, 'origin' pointer is set to | |
| * 'origin' pointer value of the original expression. | |
| */ | |
| StructLiteralExp *origin; | |
| // those fields need to prevent a infinite recursion when one field of struct initialized with 'this' pointer. | |
| StructLiteralExp *inlinecopy; | |
| /** anytime when recursive function is calling, 'stageflags' marks with bit flag of | |
| * current stage and unmarks before return from this function. | |
| * 'inlinecopy' uses similar 'stageflags' and from multiple evaluation 'doInline' | |
| * (with infinite recursion) of this expression. | |
| */ | |
| int stageflags; | |
| bool useStaticInit; // if this is true, use the StructDeclaration's init symbol | |
| bool isOriginal; // used when moving instances to indicate `this is this.origin` | |
| OwnedBy ownedByCtfe; | |
| static StructLiteralExp *create(const Loc &loc, StructDeclaration *sd, void *elements, Type *stype = NULL); | |
| bool equals(const RootObject *o) const; | |
| StructLiteralExp *syntaxCopy(); | |
| Expression *getField(Type *type, unsigned offset); | |
| int getFieldIndex(Type *type, unsigned offset); | |
| Expression *addDtorHook(Scope *sc); | |
| Expression *toLvalue(Scope *sc, Expression *e); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class TypeExp : public Expression | |
| { | |
| public: | |
| TypeExp *syntaxCopy(); | |
| bool checkType(); | |
| bool checkValue(); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class ScopeExp : public Expression | |
| { | |
| public: | |
| ScopeDsymbol *sds; | |
| ScopeExp *syntaxCopy(); | |
| bool checkType(); | |
| bool checkValue(); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class TemplateExp : public Expression | |
| { | |
| public: | |
| TemplateDeclaration *td; | |
| FuncDeclaration *fd; | |
| bool isLvalue(); | |
| Expression *toLvalue(Scope *sc, Expression *e); | |
| bool checkType(); | |
| bool checkValue(); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class NewExp : public Expression | |
| { | |
| public: | |
| /* newtype(arguments) | |
| */ | |
| Expression *thisexp; // if !NULL, 'this' for class being allocated | |
| Type *newtype; | |
| Expressions *arguments; // Array of Expression's | |
| Expression *argprefix; // expression to be evaluated just before arguments[] | |
| CtorDeclaration *member; // constructor function | |
| bool onstack; // allocate on stack | |
| bool thrownew; // this NewExp is the expression of a ThrowStatement | |
| static NewExp *create(const Loc &loc, Expression *thisexp, Type *newtype, Expressions *arguments); | |
| NewExp *syntaxCopy(); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class NewAnonClassExp : public Expression | |
| { | |
| public: | |
| /* class baseclasses { } (arguments) | |
| */ | |
| Expression *thisexp; // if !NULL, 'this' for class being allocated | |
| ClassDeclaration *cd; // class being instantiated | |
| Expressions *arguments; // Array of Expression's to call class constructor | |
| NewAnonClassExp *syntaxCopy(); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class SymbolExp : public Expression | |
| { | |
| public: | |
| Declaration *var; | |
| Dsymbol *originalScope; | |
| bool hasOverloads; | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| // Offset from symbol | |
| class SymOffExp : public SymbolExp | |
| { | |
| public: | |
| dinteger_t offset; | |
| Optional<bool> toBool(); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| // Variable | |
| class VarExp : public SymbolExp | |
| { | |
| public: | |
| bool delegateWasExtracted; | |
| static VarExp *create(const Loc &loc, Declaration *var, bool hasOverloads = true); | |
| bool equals(const RootObject *o) const; | |
| bool isLvalue(); | |
| Expression *toLvalue(Scope *sc, Expression *e); | |
| Expression *modifiableLvalue(Scope *sc, Expression *e); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| // Overload Set | |
| class OverExp : public Expression | |
| { | |
| public: | |
| OverloadSet *vars; | |
| bool isLvalue(); | |
| Expression *toLvalue(Scope *sc, Expression *e); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| // Function/Delegate literal | |
| class FuncExp : public Expression | |
| { | |
| public: | |
| FuncLiteralDeclaration *fd; | |
| TemplateDeclaration *td; | |
| TOK tok; | |
| bool equals(const RootObject *o) const; | |
| FuncExp *syntaxCopy(); | |
| const char *toChars() const; | |
| bool checkType(); | |
| bool checkValue(); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| // Declaration of a symbol | |
| // D grammar allows declarations only as statements. However in AST representation | |
| // it can be part of any expression. This is used, for example, during internal | |
| // syntax re-writes to inject hidden symbols. | |
| class DeclarationExp : public Expression | |
| { | |
| public: | |
| Dsymbol *declaration; | |
| DeclarationExp *syntaxCopy(); | |
| bool hasCode(); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class TypeidExp : public Expression | |
| { | |
| public: | |
| RootObject *obj; | |
| TypeidExp *syntaxCopy(); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class TraitsExp : public Expression | |
| { | |
| public: | |
| Identifier *ident; | |
| Objects *args; | |
| TraitsExp *syntaxCopy(); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class HaltExp : public Expression | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class IsExp : public Expression | |
| { | |
| public: | |
| /* is(targ id tok tspec) | |
| * is(targ id == tok2) | |
| */ | |
| Type *targ; | |
| Identifier *id; // can be NULL | |
| Type *tspec; // can be NULL | |
| TemplateParameters *parameters; | |
| TOK tok; // ':' or '==' | |
| TOK tok2; // 'struct', 'union', etc. | |
| IsExp *syntaxCopy(); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| /****************************************************************/ | |
| class UnaExp : public Expression | |
| { | |
| public: | |
| Expression *e1; | |
| Type *att1; // Save alias this type to detect recursion | |
| UnaExp *syntaxCopy(); | |
| Expression *incompatibleTypes(); | |
| Expression *resolveLoc(const Loc &loc, Scope *sc); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class BinExp : public Expression | |
| { | |
| public: | |
| Expression *e1; | |
| Expression *e2; | |
| Type *att1; // Save alias this type to detect recursion | |
| Type *att2; // Save alias this type to detect recursion | |
| BinExp *syntaxCopy(); | |
| Expression *incompatibleTypes(); | |
| Expression *reorderSettingAAElem(Scope *sc); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class BinAssignExp : public BinExp | |
| { | |
| public: | |
| bool isLvalue(); | |
| Expression *toLvalue(Scope *sc, Expression *ex); | |
| Expression *modifiableLvalue(Scope *sc, Expression *e); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| /****************************************************************/ | |
| class MixinExp : public UnaExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class ImportExp : public UnaExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class AssertExp : public UnaExp | |
| { | |
| public: | |
| Expression *msg; | |
| AssertExp *syntaxCopy(); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class ThrowExp : public UnaExp | |
| { | |
| public: | |
| ThrowExp *syntaxCopy(); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class DotIdExp : public UnaExp | |
| { | |
| public: | |
| Identifier *ident; | |
| bool noderef; // true if the result of the expression will never be dereferenced | |
| bool wantsym; // do not replace Symbol with its initializer during semantic() | |
| bool arrow; // ImportC: if -> instead of . | |
| static DotIdExp *create(const Loc &loc, Expression *e, Identifier *ident); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class DotTemplateExp : public UnaExp | |
| { | |
| public: | |
| TemplateDeclaration *td; | |
| bool checkType(); | |
| bool checkValue(); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class DotVarExp : public UnaExp | |
| { | |
| public: | |
| Declaration *var; | |
| bool hasOverloads; | |
| bool isLvalue(); | |
| Expression *toLvalue(Scope *sc, Expression *e); | |
| Expression *modifiableLvalue(Scope *sc, Expression *e); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class DotTemplateInstanceExp : public UnaExp | |
| { | |
| public: | |
| TemplateInstance *ti; | |
| DotTemplateInstanceExp *syntaxCopy(); | |
| bool findTempDecl(Scope *sc); | |
| bool checkType(); | |
| bool checkValue(); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class DelegateExp : public UnaExp | |
| { | |
| public: | |
| FuncDeclaration *func; | |
| bool hasOverloads; | |
| VarDeclaration *vthis2; // container for multi-context | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class DotTypeExp : public UnaExp | |
| { | |
| public: | |
| Dsymbol *sym; // symbol that represents a type | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class CallExp : public UnaExp | |
| { | |
| public: | |
| Expressions *arguments; // function arguments | |
| FuncDeclaration *f; // symbol to call | |
| bool directcall; // true if a virtual call is devirtualized | |
| bool inDebugStatement; // true if this was in a debug statement | |
| bool ignoreAttributes; // don't enforce attributes (e.g. call @gc function in @nogc code) | |
| VarDeclaration *vthis2; // container for multi-context | |
| static CallExp *create(const Loc &loc, Expression *e, Expressions *exps); | |
| static CallExp *create(const Loc &loc, Expression *e); | |
| static CallExp *create(const Loc &loc, Expression *e, Expression *earg1); | |
| static CallExp *create(const Loc &loc, FuncDeclaration *fd, Expression *earg1); | |
| CallExp *syntaxCopy(); | |
| bool isLvalue(); | |
| Expression *toLvalue(Scope *sc, Expression *e); | |
| Expression *addDtorHook(Scope *sc); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class AddrExp : public UnaExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class PtrExp : public UnaExp | |
| { | |
| public: | |
| bool isLvalue(); | |
| Expression *toLvalue(Scope *sc, Expression *e); | |
| Expression *modifiableLvalue(Scope *sc, Expression *e); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class NegExp : public UnaExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class UAddExp : public UnaExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class ComExp : public UnaExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class NotExp : public UnaExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class DeleteExp : public UnaExp | |
| { | |
| public: | |
| bool isRAII; | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class CastExp : public UnaExp | |
| { | |
| public: | |
| // Possible to cast to one type while painting to another type | |
| Type *to; // type to cast to | |
| unsigned char mod; // MODxxxxx | |
| CastExp *syntaxCopy(); | |
| bool isLvalue(); | |
| Expression *toLvalue(Scope *sc, Expression *e); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class VectorExp : public UnaExp | |
| { | |
| public: | |
| TypeVector *to; // the target vector type before semantic() | |
| unsigned dim; // number of elements in the vector | |
| OwnedBy ownedByCtfe; | |
| static VectorExp *create(const Loc &loc, Expression *e, Type *t); | |
| static void emplace(UnionExp *pue, const Loc &loc, Expression *e, Type *t); | |
| VectorExp *syntaxCopy(); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class VectorArrayExp : public UnaExp | |
| { | |
| public: | |
| bool isLvalue(); | |
| Expression *toLvalue(Scope *sc, Expression *e); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class SliceExp : public UnaExp | |
| { | |
| public: | |
| Expression *upr; // NULL if implicit 0 | |
| Expression *lwr; // NULL if implicit [length - 1] | |
| VarDeclaration *lengthVar; | |
| bool upperIsInBounds; // true if upr <= e1.length | |
| bool lowerIsLessThanUpper; // true if lwr <= upr | |
| bool arrayop; // an array operation, rather than a slice | |
| SliceExp *syntaxCopy(); | |
| bool isLvalue(); | |
| Expression *toLvalue(Scope *sc, Expression *e); | |
| Expression *modifiableLvalue(Scope *sc, Expression *e); | |
| Optional<bool> toBool(); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class ArrayLengthExp : public UnaExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class IntervalExp : public Expression | |
| { | |
| public: | |
| Expression *lwr; | |
| Expression *upr; | |
| IntervalExp *syntaxCopy(); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class DelegatePtrExp : public UnaExp | |
| { | |
| public: | |
| bool isLvalue(); | |
| Expression *toLvalue(Scope *sc, Expression *e); | |
| Expression *modifiableLvalue(Scope *sc, Expression *e); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class DelegateFuncptrExp : public UnaExp | |
| { | |
| public: | |
| bool isLvalue(); | |
| Expression *toLvalue(Scope *sc, Expression *e); | |
| Expression *modifiableLvalue(Scope *sc, Expression *e); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| // e1[a0,a1,a2,a3,...] | |
| class ArrayExp : public UnaExp | |
| { | |
| public: | |
| Expressions *arguments; // Array of Expression's | |
| size_t currentDimension; // for opDollar | |
| VarDeclaration *lengthVar; | |
| ArrayExp *syntaxCopy(); | |
| bool isLvalue(); | |
| Expression *toLvalue(Scope *sc, Expression *e); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| /****************************************************************/ | |
| class DotExp : public BinExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class CommaExp : public BinExp | |
| { | |
| public: | |
| bool isGenerated; | |
| bool allowCommaExp; | |
| bool isLvalue(); | |
| Expression *toLvalue(Scope *sc, Expression *e); | |
| Expression *modifiableLvalue(Scope *sc, Expression *e); | |
| Optional<bool> toBool(); | |
| Expression *addDtorHook(Scope *sc); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class IndexExp : public BinExp | |
| { | |
| public: | |
| VarDeclaration *lengthVar; | |
| bool modifiable; | |
| bool indexIsInBounds; // true if 0 <= e2 && e2 <= e1.length - 1 | |
| IndexExp *syntaxCopy(); | |
| bool isLvalue(); | |
| Expression *toLvalue(Scope *sc, Expression *e); | |
| Expression *modifiableLvalue(Scope *sc, Expression *e); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| /* For both i++ and i-- | |
| */ | |
| class PostExp : public BinExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| /* For both ++i and --i | |
| */ | |
| class PreExp : public UnaExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| enum class MemorySet | |
| { | |
| none = 0, // simple assignment | |
| blockAssign = 1, // setting the contents of an array | |
| referenceInit = 2 // setting the reference of STCref variable | |
| }; | |
| class AssignExp : public BinExp | |
| { | |
| public: | |
| MemorySet memset; | |
| bool isLvalue(); | |
| Expression *toLvalue(Scope *sc, Expression *ex); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class ConstructExp : public AssignExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class BlitExp : public AssignExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class AddAssignExp : public BinAssignExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class MinAssignExp : public BinAssignExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class MulAssignExp : public BinAssignExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class DivAssignExp : public BinAssignExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class ModAssignExp : public BinAssignExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class AndAssignExp : public BinAssignExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class OrAssignExp : public BinAssignExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class XorAssignExp : public BinAssignExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class PowAssignExp : public BinAssignExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class ShlAssignExp : public BinAssignExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class ShrAssignExp : public BinAssignExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class UshrAssignExp : public BinAssignExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class CatAssignExp : public BinAssignExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class AddExp : public BinExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class MinExp : public BinExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class CatExp : public BinExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class MulExp : public BinExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class DivExp : public BinExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class ModExp : public BinExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class PowExp : public BinExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class ShlExp : public BinExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class ShrExp : public BinExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class UshrExp : public BinExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class AndExp : public BinExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class OrExp : public BinExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class XorExp : public BinExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class LogicalExp : public BinExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class CmpExp : public BinExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class InExp : public BinExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class RemoveExp : public BinExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| // == and != | |
| class EqualExp : public BinExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| // is and !is | |
| class IdentityExp : public BinExp | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| /****************************************************************/ | |
| class CondExp : public BinExp | |
| { | |
| public: | |
| Expression *econd; | |
| CondExp *syntaxCopy(); | |
| bool isLvalue(); | |
| Expression *toLvalue(Scope *sc, Expression *e); | |
| Expression *modifiableLvalue(Scope *sc, Expression *e); | |
| void hookDtors(Scope *sc); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class GenericExp : Expression | |
| { | |
| Expression *cntlExp; | |
| Types *types; | |
| Expressions *exps; | |
| GenericExp *syntaxCopy(); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| /****************************************************************/ | |
| class DefaultInitExp : public Expression | |
| { | |
| public: | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class FileInitExp : public DefaultInitExp | |
| { | |
| public: | |
| Expression *resolveLoc(const Loc &loc, Scope *sc); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class LineInitExp : public DefaultInitExp | |
| { | |
| public: | |
| Expression *resolveLoc(const Loc &loc, Scope *sc); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class ModuleInitExp : public DefaultInitExp | |
| { | |
| public: | |
| Expression *resolveLoc(const Loc &loc, Scope *sc); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class FuncInitExp : public DefaultInitExp | |
| { | |
| public: | |
| Expression *resolveLoc(const Loc &loc, Scope *sc); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| class PrettyFuncInitExp : public DefaultInitExp | |
| { | |
| public: | |
| Expression *resolveLoc(const Loc &loc, Scope *sc); | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; | |
| /****************************************************************/ | |
| /* A type meant as a union of all the Expression types, | |
| * to serve essentially as a Variant that will sit on the stack | |
| * during CTFE to reduce memory consumption. | |
| */ | |
| struct UnionExp | |
| { | |
| UnionExp() { } // yes, default constructor does nothing | |
| UnionExp(Expression *e) | |
| { | |
| memcpy(this, (void *)e, e->size); | |
| } | |
| /* Extract pointer to Expression | |
| */ | |
| Expression *exp() { return (Expression *)&u; } | |
| /* Convert to an allocated Expression | |
| */ | |
| Expression *copy(); | |
| private: | |
| // Ensure that the union is suitably aligned. | |
| #if defined(__GNUC__) || defined(__clang__) | |
| __attribute__((aligned(8))) | |
| #elif defined(_MSC_VER) | |
| __declspec(align(8)) | |
| #elif defined(__DMC__) | |
| #pragma pack(8) | |
| #endif | |
| union | |
| { | |
| char exp [sizeof(Expression)]; | |
| char integerexp[sizeof(IntegerExp)]; | |
| char errorexp [sizeof(ErrorExp)]; | |
| char realexp [sizeof(RealExp)]; | |
| char complexexp[sizeof(ComplexExp)]; | |
| char symoffexp [sizeof(SymOffExp)]; | |
| char stringexp [sizeof(StringExp)]; | |
| char arrayliteralexp [sizeof(ArrayLiteralExp)]; | |
| char assocarrayliteralexp [sizeof(AssocArrayLiteralExp)]; | |
| char structliteralexp [sizeof(StructLiteralExp)]; | |
| char nullexp [sizeof(NullExp)]; | |
| char dotvarexp [sizeof(DotVarExp)]; | |
| char addrexp [sizeof(AddrExp)]; | |
| char indexexp [sizeof(IndexExp)]; | |
| char sliceexp [sizeof(SliceExp)]; | |
| char vectorexp [sizeof(VectorExp)]; | |
| } u; | |
| #if defined(__DMC__) | |
| #pragma pack() | |
| #endif | |
| }; | |
| /****************************************************************/ | |
| class ObjcClassReferenceExp : public Expression | |
| { | |
| public: | |
| ClassDeclaration* classDeclaration; | |
| void accept(Visitor *v) { v->visit(this); } | |
| }; |