| |
| /* Compiler implementation of the D programming language |
| * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved |
| * written by Walter Bright |
| * http://www.digitalmars.com |
| * Distributed under the Boost Software License, Version 1.0. |
| * http://www.boost.org/LICENSE_1_0.txt |
| * https://github.com/dlang/dmd/blob/master/src/dmd/expression.h |
| */ |
| |
| #pragma once |
| |
| #include "complex_t.h" |
| #include "globals.h" |
| #include "identifier.h" |
| #include "arraytypes.h" |
| #include "intrange.h" |
| #include "visitor.h" |
| #include "tokens.h" |
| |
| #include "root/rmem.h" |
| |
| class Type; |
| class TypeVector; |
| struct Scope; |
| class TupleDeclaration; |
| class VarDeclaration; |
| class FuncDeclaration; |
| class FuncLiteralDeclaration; |
| class Declaration; |
| class CtorDeclaration; |
| class NewDeclaration; |
| class Dsymbol; |
| class Import; |
| class Module; |
| class ScopeDsymbol; |
| class Expression; |
| class Declaration; |
| class AggregateDeclaration; |
| class StructDeclaration; |
| class TemplateInstance; |
| class TemplateDeclaration; |
| class ClassDeclaration; |
| class BinExp; |
| class OverloadSet; |
| class Initializer; |
| class StringExp; |
| class ArrayExp; |
| class SliceExp; |
| struct UnionExp; |
| #ifdef IN_GCC |
| typedef union tree_node Symbol; |
| #else |
| struct Symbol; // back end symbol |
| #endif |
| |
| Expression *resolveProperties(Scope *sc, Expression *e); |
| Expression *resolvePropertiesOnly(Scope *sc, Expression *e1); |
| bool checkAccess(Loc loc, Scope *sc, Expression *e, Declaration *d); |
| bool checkAccess(Loc loc, Scope *sc, Package *p); |
| Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Dsymbol *d); |
| Dsymbol *search_function(ScopeDsymbol *ad, Identifier *funcid); |
| void expandTuples(Expressions *exps); |
| TupleDeclaration *isAliasThisTuple(Expression *e); |
| int expandAliasThisTuples(Expressions *exps, size_t starti = 0); |
| FuncDeclaration *hasThis(Scope *sc); |
| Expression *fromConstInitializer(int result, Expression *e); |
| bool arrayExpressionSemantic(Expressions *exps, Scope *sc, bool preserveErrors = false); |
| TemplateDeclaration *getFuncTemplateDecl(Dsymbol *s); |
| Expression *valueNoDtor(Expression *e); |
| int modifyFieldVar(Loc loc, Scope *sc, VarDeclaration *var, Expression *e1); |
| Expression *resolveAliasThis(Scope *sc, Expression *e, bool gag = false); |
| Expression *doCopyOrMove(Scope *sc, Expression *e); |
| Expression *resolveOpDollar(Scope *sc, ArrayExp *ae, Expression **pe0); |
| Expression *resolveOpDollar(Scope *sc, ArrayExp *ae, IntervalExp *ie, Expression **pe0); |
| Expression *integralPromotions(Expression *e, Scope *sc); |
| bool discardValue(Expression *e); |
| bool isTrivialExp(Expression *e); |
| |
| int isConst(Expression *e); |
| Expression *toDelegate(Expression *e, Type* t, Scope *sc); |
| AggregateDeclaration *isAggregate(Type *t); |
| IntRange getIntRange(Expression *e); |
| bool checkNonAssignmentArrayOp(Expression *e, bool suggestion = false); |
| bool isUnaArrayOp(TOK op); |
| bool isBinArrayOp(TOK op); |
| bool isBinAssignArrayOp(TOK op); |
| bool isArrayOpOperand(Expression *e); |
| Expression *arrayOp(BinExp *e, Scope *sc); |
| Expression *arrayOp(BinAssignExp *e, Scope *sc); |
| bool hasSideEffect(Expression *e); |
| bool canThrow(Expression *e, FuncDeclaration *func, bool mustNotThrow); |
| Expression *Expression_optimize(Expression *e, int result, bool keepLvalue); |
| MATCH implicitConvTo(Expression *e, Type *t); |
| Expression *implicitCastTo(Expression *e, Scope *sc, Type *t); |
| Expression *castTo(Expression *e, Scope *sc, Type *t); |
| Expression *ctfeInterpret(Expression *); |
| Expression *inlineCopy(Expression *e, Scope *sc); |
| Expression *op_overload(Expression *e, Scope *sc); |
| Type *toStaticArrayType(SliceExp *e); |
| Expression *scaleFactor(BinExp *be, Scope *sc); |
| Expression *typeCombine(BinExp *be, Scope *sc); |
| Expression *inferType(Expression *e, Type *t, int flag = 0); |
| Expression *semanticTraits(TraitsExp *e, Scope *sc); |
| Type *getIndirection(Type *t); |
| |
| Expression *checkGC(Scope *sc, Expression *e); |
| |
| /* Run CTFE on the expression, but allow the expression to be a TypeExp |
| * or a tuple containing a TypeExp. (This is required by pragma(msg)). |
| */ |
| Expression *ctfeInterpretForPragmaMsg(Expression *e); |
| |
| enum OwnedBy |
| { |
| 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 |
| |
| class Expression : public RootObject |
| { |
| public: |
| Loc loc; // file location |
| Type *type; // !=NULL means that semantic() has been run |
| TOK 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 |
| |
| Expression(Loc loc, TOK op, int size); |
| static void _init(); |
| Expression *copy(); |
| virtual Expression *syntaxCopy(); |
| |
| // kludge for template.isExpression() |
| int dyncast() const { return DYNCAST_EXPRESSION; } |
| |
| void print(); |
| const char *toChars(); |
| void error(const char *format, ...) const; |
| void warning(const char *format, ...) const; |
| void deprecation(const char *format, ...) const; |
| |
| // creates a single expression which is effectively (e1, e2) |
| // this new expression does not necessarily need to have valid D source code representation, |
| // for example, it may include declaration expressions |
| static Expression *combine(Expression *e1, Expression *e2); |
| static Expression *extractLast(Expression *e, Expression **pe0); |
| static Expressions *arraySyntaxCopy(Expressions *exps); |
| |
| 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) |
| { |
| return ::implicitCastTo(this, sc, t); |
| } |
| MATCH implicitConvTo(Type *t) |
| { |
| return ::implicitConvTo(this, t); |
| } |
| Expression *castTo(Scope *sc, Type *t) |
| { |
| return ::castTo(this, sc, t); |
| } |
| virtual Expression *resolveLoc(Loc loc, Scope *sc); |
| virtual bool checkType(); |
| virtual bool checkValue(); |
| bool checkScalar(); |
| bool checkNoBool(); |
| bool checkIntegral(); |
| bool checkArithmetic(); |
| void checkDeprecated(Scope *sc, Dsymbol *s); |
| bool checkPurity(Scope *sc, FuncDeclaration *f); |
| bool checkPurity(Scope *sc, VarDeclaration *v); |
| bool checkSafety(Scope *sc, FuncDeclaration *f); |
| bool checkNogc(Scope *sc, FuncDeclaration *f); |
| bool checkPostblit(Scope *sc, Type *t); |
| bool checkRightThis(Scope *sc); |
| bool checkReadModifyWrite(TOK rmwOp, Expression *ex = NULL); |
| virtual int checkModifiable(Scope *sc, int flag = 0); |
| virtual Expression *toBoolean(Scope *sc); |
| virtual Expression *addDtorHook(Scope *sc); |
| Expression *addressOf(); |
| Expression *deref(); |
| |
| Expression *optimize(int result, bool keepLvalue = false) |
| { |
| return Expression_optimize(this, result, keepLvalue); |
| } |
| |
| // Entry point for CTFE. |
| // A compile-time result is required. Give an error if not possible |
| Expression *ctfeInterpret() |
| { |
| return ::ctfeInterpret(this); |
| } |
| |
| int isConst() { return ::isConst(this); } |
| virtual bool isBool(bool result); |
| Expression *op_overload(Scope *sc) |
| { |
| return ::op_overload(this, sc); |
| } |
| |
| virtual bool hasCode() |
| { |
| return true; |
| } |
| |
| virtual void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class IntegerExp : public Expression |
| { |
| public: |
| dinteger_t value; |
| |
| IntegerExp(Loc loc, dinteger_t value, Type *type); |
| IntegerExp(dinteger_t value); |
| static IntegerExp *create(Loc loc, dinteger_t value, Type *type); |
| bool equals(RootObject *o); |
| dinteger_t toInteger(); |
| real_t toReal(); |
| real_t toImaginary(); |
| complex_t toComplex(); |
| bool isBool(bool result); |
| Expression *toLvalue(Scope *sc, Expression *e); |
| void accept(Visitor *v) { v->visit(this); } |
| dinteger_t getInteger() { return value; } |
| void setInteger(dinteger_t value); |
| void normalize(); |
| }; |
| |
| class ErrorExp : public Expression |
| { |
| public: |
| ErrorExp(); |
| 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; |
| |
| RealExp(Loc loc, real_t value, Type *type); |
| static RealExp *create(Loc loc, real_t value, Type *type); |
| bool equals(RootObject *o); |
| dinteger_t toInteger(); |
| uinteger_t toUInteger(); |
| real_t toReal(); |
| real_t toImaginary(); |
| complex_t toComplex(); |
| bool isBool(bool result); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class ComplexExp : public Expression |
| { |
| public: |
| complex_t value; |
| |
| ComplexExp(Loc loc, complex_t value, Type *type); |
| static ComplexExp *create(Loc loc, complex_t value, Type *type); |
| bool equals(RootObject *o); |
| dinteger_t toInteger(); |
| uinteger_t toUInteger(); |
| real_t toReal(); |
| real_t toImaginary(); |
| complex_t toComplex(); |
| bool isBool(bool result); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class IdentifierExp : public Expression |
| { |
| public: |
| Identifier *ident; |
| |
| IdentifierExp(Loc loc, Identifier *ident); |
| static IdentifierExp *create(Loc loc, Identifier *ident); |
| bool isLvalue(); |
| Expression *toLvalue(Scope *sc, Expression *e); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class DollarExp : public IdentifierExp |
| { |
| public: |
| DollarExp(Loc loc); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class DsymbolExp : public Expression |
| { |
| public: |
| Dsymbol *s; |
| bool hasOverloads; |
| |
| DsymbolExp(Loc loc, Dsymbol *s, bool hasOverloads = true); |
| bool isLvalue(); |
| Expression *toLvalue(Scope *sc, Expression *e); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class ThisExp : public Expression |
| { |
| public: |
| VarDeclaration *var; |
| |
| ThisExp(Loc loc); |
| bool isBool(bool result); |
| bool isLvalue(); |
| Expression *toLvalue(Scope *sc, Expression *e); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class SuperExp : public ThisExp |
| { |
| public: |
| SuperExp(Loc loc); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class NullExp : public Expression |
| { |
| public: |
| unsigned char committed; // !=0 if type is committed |
| |
| NullExp(Loc loc, Type *t = NULL); |
| bool equals(RootObject *o); |
| bool isBool(bool result); |
| 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; |
| |
| StringExp(Loc loc, char *s); |
| StringExp(Loc loc, void *s, size_t len); |
| StringExp(Loc loc, void *s, size_t len, utf8_t postfix); |
| static StringExp *create(Loc loc, char *s); |
| static StringExp *create(Loc loc, void *s, size_t len); |
| bool equals(RootObject *o); |
| StringExp *toStringExp(); |
| StringExp *toUTF8(Scope *sc); |
| int compare(RootObject *obj); |
| bool isBool(bool result); |
| bool isLvalue(); |
| Expression *toLvalue(Scope *sc, Expression *e); |
| Expression *modifiableLvalue(Scope *sc, Expression *e); |
| unsigned charAt(uinteger_t i) const; |
| void accept(Visitor *v) { v->visit(this); } |
| size_t numberOfCodeUnits(int tynto = 0) const; |
| void writeTo(void* dest, bool zero, int tyto = 0) const; |
| char *toPtr(); |
| }; |
| |
| // 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; |
| |
| TupleExp(Loc loc, Expression *e0, Expressions *exps); |
| TupleExp(Loc loc, Expressions *exps); |
| TupleExp(Loc loc, TupleDeclaration *tup); |
| Expression *syntaxCopy(); |
| bool equals(RootObject *o); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class ArrayLiteralExp : public Expression |
| { |
| public: |
| Expression *basis; |
| Expressions *elements; |
| OwnedBy ownedByCtfe; |
| |
| ArrayLiteralExp(Loc loc, Type *type, Expressions *elements); |
| ArrayLiteralExp(Loc loc, Type *type, Expression *e); |
| ArrayLiteralExp(Loc loc, Type *type, Expression *basis, Expressions *elements); |
| static ArrayLiteralExp *create(Loc loc, Expressions *elements); |
| Expression *syntaxCopy(); |
| bool equals(RootObject *o); |
| Expression *getElement(d_size_t i); |
| static Expressions* copyElements(Expression *e1, Expression *e2 = NULL); |
| bool isBool(bool result); |
| StringExp *toStringExp(); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class AssocArrayLiteralExp : public Expression |
| { |
| public: |
| Expressions *keys; |
| Expressions *values; |
| OwnedBy ownedByCtfe; |
| |
| AssocArrayLiteralExp(Loc loc, Expressions *keys, Expressions *values); |
| bool equals(RootObject *o); |
| Expression *syntaxCopy(); |
| bool isBool(bool result); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| // scrubReturnValue is running |
| #define stageScrub 0x1 |
| // hasNonConstPointers is running |
| #define stageSearchPointers 0x2 |
| // optimize is running |
| #define stageOptimize 0x4 |
| // apply is running |
| #define stageApply 0x8 |
| //inlineScan is running |
| #define stageInlineScan 0x10 |
| // toCBuffer is running |
| #define stageToCBuffer 0x20 |
| |
| 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) |
| |
| bool useStaticInit; // if this is true, use the StructDeclaration's init symbol |
| Symbol *sym; // back end symbol to initialize with literal |
| |
| OwnedBy ownedByCtfe; |
| |
| // 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; |
| |
| StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements, Type *stype = NULL); |
| static StructLiteralExp *create(Loc loc, StructDeclaration *sd, void *elements, Type *stype = NULL); |
| bool equals(RootObject *o); |
| Expression *syntaxCopy(); |
| Expression *getField(Type *type, unsigned offset); |
| int getFieldIndex(Type *type, unsigned offset); |
| Expression *addDtorHook(Scope *sc); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class DotIdExp; |
| DotIdExp *typeDotIdExp(Loc loc, Type *type, Identifier *ident); |
| |
| class TypeExp : public Expression |
| { |
| public: |
| TypeExp(Loc loc, Type *type); |
| Expression *syntaxCopy(); |
| bool checkType(); |
| bool checkValue(); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class ScopeExp : public Expression |
| { |
| public: |
| ScopeDsymbol *sds; |
| |
| ScopeExp(Loc loc, ScopeDsymbol *sds); |
| Expression *syntaxCopy(); |
| bool checkType(); |
| bool checkValue(); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class TemplateExp : public Expression |
| { |
| public: |
| TemplateDeclaration *td; |
| FuncDeclaration *fd; |
| |
| TemplateExp(Loc loc, TemplateDeclaration *td, FuncDeclaration *fd = NULL); |
| bool isLvalue(); |
| Expression *toLvalue(Scope *sc, Expression *e); |
| bool checkType(); |
| bool checkValue(); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class NewExp : public Expression |
| { |
| public: |
| /* thisexp.new(newargs) newtype(arguments) |
| */ |
| Expression *thisexp; // if !NULL, 'this' for class being allocated |
| Expressions *newargs; // Array of Expression's to call new operator |
| Type *newtype; |
| Expressions *arguments; // Array of Expression's |
| |
| Expression *argprefix; // expression to be evaluated just before arguments[] |
| |
| CtorDeclaration *member; // constructor function |
| NewDeclaration *allocator; // allocator function |
| int onstack; // allocate on stack |
| |
| NewExp(Loc loc, Expression *thisexp, Expressions *newargs, |
| Type *newtype, Expressions *arguments); |
| static NewExp *create(Loc loc, Expression *thisexp, Expressions *newargs, Type *newtype, Expressions *arguments); |
| Expression *syntaxCopy(); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class NewAnonClassExp : public Expression |
| { |
| public: |
| /* thisexp.new(newargs) class baseclasses { } (arguments) |
| */ |
| Expression *thisexp; // if !NULL, 'this' for class being allocated |
| Expressions *newargs; // Array of Expression's to call new operator |
| ClassDeclaration *cd; // class being instantiated |
| Expressions *arguments; // Array of Expression's to call class constructor |
| |
| NewAnonClassExp(Loc loc, Expression *thisexp, Expressions *newargs, |
| ClassDeclaration *cd, Expressions *arguments); |
| Expression *syntaxCopy(); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class SymbolExp : public Expression |
| { |
| public: |
| Declaration *var; |
| bool hasOverloads; |
| SymbolExp(Loc loc, TOK op, int size, Declaration *var, bool hasOverloads); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| // Offset from symbol |
| |
| class SymOffExp : public SymbolExp |
| { |
| public: |
| dinteger_t offset; |
| |
| SymOffExp(Loc loc, Declaration *var, dinteger_t offset, bool hasOverloads = true); |
| bool isBool(bool result); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| // Variable |
| |
| class VarExp : public SymbolExp |
| { |
| public: |
| VarExp(Loc loc, Declaration *var, bool hasOverloads = true); |
| static VarExp *create(Loc loc, Declaration *var, bool hasOverloads = true); |
| bool equals(RootObject *o); |
| int checkModifiable(Scope *sc, int flag); |
| bool checkReadModifyWrite(); |
| 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; |
| |
| OverExp(Loc loc, OverloadSet *s); |
| 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; |
| |
| FuncExp(Loc loc, Dsymbol *s); |
| bool equals(RootObject *o); |
| void genIdent(Scope *sc); |
| Expression *syntaxCopy(); |
| MATCH matchType(Type *to, Scope *sc, FuncExp **pfe, int flag = 0); |
| const char *toChars(); |
| 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(Loc loc, Dsymbol *declaration); |
| Expression *syntaxCopy(); |
| |
| bool hasCode(); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class TypeidExp : public Expression |
| { |
| public: |
| RootObject *obj; |
| |
| TypeidExp(Loc loc, RootObject *obj); |
| Expression *syntaxCopy(); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class TraitsExp : public Expression |
| { |
| public: |
| Identifier *ident; |
| Objects *args; |
| |
| TraitsExp(Loc loc, Identifier *ident, Objects *args); |
| Expression *syntaxCopy(); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class HaltExp : public Expression |
| { |
| public: |
| HaltExp(Loc loc); |
| |
| 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 |
| TOK tok; // ':' or '==' |
| Type *tspec; // can be NULL |
| TOK tok2; // 'struct', 'union', etc. |
| TemplateParameters *parameters; |
| |
| IsExp(Loc loc, Type *targ, Identifier *id, TOK tok, Type *tspec, |
| TOK tok2, TemplateParameters *parameters); |
| Expression *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(Loc loc, TOK op, int size, Expression *e1); |
| Expression *syntaxCopy(); |
| Expression *incompatibleTypes(); |
| Expression *resolveLoc(Loc loc, Scope *sc); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| typedef UnionExp (*fp_t)(Loc loc, Type *, Expression *, Expression *); |
| typedef int (*fp2_t)(Loc loc, TOK, Expression *, Expression *); |
| |
| 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(Loc loc, TOK op, int size, Expression *e1, Expression *e2); |
| Expression *syntaxCopy(); |
| Expression *incompatibleTypes(); |
| Expression *checkOpAssignTypes(Scope *sc); |
| bool checkIntegralBin(); |
| bool checkArithmeticBin(); |
| |
| Expression *reorderSettingAAElem(Scope *sc); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class BinAssignExp : public BinExp |
| { |
| public: |
| BinAssignExp(Loc loc, TOK op, int size, Expression *e1, Expression *e2); |
| |
| bool isLvalue(); |
| Expression *toLvalue(Scope *sc, Expression *ex); |
| Expression *modifiableLvalue(Scope *sc, Expression *e); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| /****************************************************************/ |
| |
| class CompileExp : public UnaExp |
| { |
| public: |
| CompileExp(Loc loc, Expression *e); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class ImportExp : public UnaExp |
| { |
| public: |
| ImportExp(Loc loc, Expression *e); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class AssertExp : public UnaExp |
| { |
| public: |
| Expression *msg; |
| |
| AssertExp(Loc loc, Expression *e, Expression *msg = NULL); |
| Expression *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() |
| |
| DotIdExp(Loc loc, Expression *e, Identifier *ident); |
| static DotIdExp *create(Loc loc, Expression *e, Identifier *ident); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class DotTemplateExp : public UnaExp |
| { |
| public: |
| TemplateDeclaration *td; |
| |
| DotTemplateExp(Loc loc, Expression *e, TemplateDeclaration *td); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class DotVarExp : public UnaExp |
| { |
| public: |
| Declaration *var; |
| bool hasOverloads; |
| |
| DotVarExp(Loc loc, Expression *e, Declaration *var, bool hasOverloads = true); |
| int checkModifiable(Scope *sc, int flag); |
| bool checkReadModifyWrite(); |
| 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(Loc loc, Expression *e, Identifier *name, Objects *tiargs); |
| DotTemplateInstanceExp(Loc loc, Expression *e, TemplateInstance *ti); |
| Expression *syntaxCopy(); |
| bool findTempDecl(Scope *sc); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class DelegateExp : public UnaExp |
| { |
| public: |
| FuncDeclaration *func; |
| bool hasOverloads; |
| |
| DelegateExp(Loc loc, Expression *e, FuncDeclaration *func, bool hasOverloads = true); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class DotTypeExp : public UnaExp |
| { |
| public: |
| Dsymbol *sym; // symbol that represents a type |
| |
| DotTypeExp(Loc loc, Expression *e, Dsymbol *sym); |
| 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 |
| CallExp(Loc loc, Expression *e, Expressions *exps); |
| CallExp(Loc loc, Expression *e); |
| CallExp(Loc loc, Expression *e, Expression *earg1); |
| CallExp(Loc loc, Expression *e, Expression *earg1, Expression *earg2); |
| |
| static CallExp *create(Loc loc, Expression *e, Expressions *exps); |
| static CallExp *create(Loc loc, Expression *e); |
| static CallExp *create(Loc loc, Expression *e, Expression *earg1); |
| |
| Expression *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: |
| AddrExp(Loc loc, Expression *e); |
| AddrExp(Loc loc, Expression *e, Type *t); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class PtrExp : public UnaExp |
| { |
| public: |
| PtrExp(Loc loc, Expression *e); |
| PtrExp(Loc loc, Expression *e, Type *t); |
| int checkModifiable(Scope *sc, int flag); |
| 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: |
| NegExp(Loc loc, Expression *e); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class UAddExp : public UnaExp |
| { |
| public: |
| UAddExp(Loc loc, Expression *e); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class ComExp : public UnaExp |
| { |
| public: |
| ComExp(Loc loc, Expression *e); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class NotExp : public UnaExp |
| { |
| public: |
| NotExp(Loc loc, Expression *e); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class DeleteExp : public UnaExp |
| { |
| public: |
| bool isRAII; |
| DeleteExp(Loc loc, Expression *e, bool isRAII); |
| Expression *toBoolean(Scope *sc); |
| 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(Loc loc, Expression *e, Type *t); |
| CastExp(Loc loc, Expression *e, unsigned char mod); |
| Expression *syntaxCopy(); |
| |
| 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; |
| |
| VectorExp(Loc loc, Expression *e, Type *t); |
| static VectorExp *create(Loc loc, Expression *e, Type *t); |
| Expression *syntaxCopy(); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class VectorArrayExp : public UnaExp |
| { |
| public: |
| VectorArrayExp(Loc loc, Expression *e1); |
| 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(Loc loc, Expression *e1, IntervalExp *ie); |
| SliceExp(Loc loc, Expression *e1, Expression *lwr, Expression *upr); |
| Expression *syntaxCopy(); |
| int checkModifiable(Scope *sc, int flag); |
| bool isLvalue(); |
| Expression *toLvalue(Scope *sc, Expression *e); |
| Expression *modifiableLvalue(Scope *sc, Expression *e); |
| bool isBool(bool result); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class ArrayLengthExp : public UnaExp |
| { |
| public: |
| ArrayLengthExp(Loc loc, Expression *e1); |
| |
| static Expression *rewriteOpAssign(BinExp *exp); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class IntervalExp : public Expression |
| { |
| public: |
| Expression *lwr; |
| Expression *upr; |
| |
| IntervalExp(Loc loc, Expression *lwr, Expression *upr); |
| Expression *syntaxCopy(); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class DelegatePtrExp : public UnaExp |
| { |
| public: |
| DelegatePtrExp(Loc loc, Expression *e1); |
| 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: |
| DelegateFuncptrExp(Loc loc, Expression *e1); |
| 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(Loc loc, Expression *e1, Expression *index = NULL); |
| ArrayExp(Loc loc, Expression *e1, Expressions *args); |
| Expression *syntaxCopy(); |
| bool isLvalue(); |
| Expression *toLvalue(Scope *sc, Expression *e); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| /****************************************************************/ |
| |
| class DotExp : public BinExp |
| { |
| public: |
| DotExp(Loc loc, Expression *e1, Expression *e2); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class CommaExp : public BinExp |
| { |
| public: |
| bool isGenerated; |
| bool allowCommaExp; |
| CommaExp(Loc loc, Expression *e1, Expression *e2, bool generated = true); |
| int checkModifiable(Scope *sc, int flag); |
| bool isLvalue(); |
| Expression *toLvalue(Scope *sc, Expression *e); |
| Expression *modifiableLvalue(Scope *sc, Expression *e); |
| bool isBool(bool result); |
| Expression *toBoolean(Scope *sc); |
| 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(Loc loc, Expression *e1, Expression *e2); |
| Expression *syntaxCopy(); |
| int checkModifiable(Scope *sc, int flag); |
| bool isLvalue(); |
| Expression *toLvalue(Scope *sc, Expression *e); |
| Expression *modifiableLvalue(Scope *sc, Expression *e); |
| |
| Expression *markSettingAAElem(); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| /* For both i++ and i-- |
| */ |
| class PostExp : public BinExp |
| { |
| public: |
| PostExp(TOK op, Loc loc, Expression *e); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| /* For both ++i and --i |
| */ |
| class PreExp : public UnaExp |
| { |
| public: |
| PreExp(TOK op, Loc loc, Expression *e); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| enum MemorySet |
| { |
| blockAssign = 1, // setting the contents of an array |
| referenceInit = 2 // setting the reference of STCref variable |
| }; |
| |
| class AssignExp : public BinExp |
| { |
| public: |
| int memset; // combination of MemorySet flags |
| |
| AssignExp(Loc loc, Expression *e1, Expression *e2); |
| bool isLvalue(); |
| Expression *toLvalue(Scope *sc, Expression *ex); |
| Expression *toBoolean(Scope *sc); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class ConstructExp : public AssignExp |
| { |
| public: |
| ConstructExp(Loc loc, Expression *e1, Expression *e2); |
| ConstructExp(Loc loc, VarDeclaration *v, Expression *e2); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class BlitExp : public AssignExp |
| { |
| public: |
| BlitExp(Loc loc, Expression *e1, Expression *e2); |
| BlitExp(Loc loc, VarDeclaration *v, Expression *e2); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class AddAssignExp : public BinAssignExp |
| { |
| public: |
| AddAssignExp(Loc loc, Expression *e1, Expression *e2); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class MinAssignExp : public BinAssignExp |
| { |
| public: |
| MinAssignExp(Loc loc, Expression *e1, Expression *e2); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class MulAssignExp : public BinAssignExp |
| { |
| public: |
| MulAssignExp(Loc loc, Expression *e1, Expression *e2); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class DivAssignExp : public BinAssignExp |
| { |
| public: |
| DivAssignExp(Loc loc, Expression *e1, Expression *e2); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class ModAssignExp : public BinAssignExp |
| { |
| public: |
| ModAssignExp(Loc loc, Expression *e1, Expression *e2); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class AndAssignExp : public BinAssignExp |
| { |
| public: |
| AndAssignExp(Loc loc, Expression *e1, Expression *e2); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class OrAssignExp : public BinAssignExp |
| { |
| public: |
| OrAssignExp(Loc loc, Expression *e1, Expression *e2); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class XorAssignExp : public BinAssignExp |
| { |
| public: |
| XorAssignExp(Loc loc, Expression *e1, Expression *e2); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class PowAssignExp : public BinAssignExp |
| { |
| public: |
| PowAssignExp(Loc loc, Expression *e1, Expression *e2); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class ShlAssignExp : public BinAssignExp |
| { |
| public: |
| ShlAssignExp(Loc loc, Expression *e1, Expression *e2); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class ShrAssignExp : public BinAssignExp |
| { |
| public: |
| ShrAssignExp(Loc loc, Expression *e1, Expression *e2); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class UshrAssignExp : public BinAssignExp |
| { |
| public: |
| UshrAssignExp(Loc loc, Expression *e1, Expression *e2); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class CatAssignExp : public BinAssignExp |
| { |
| public: |
| CatAssignExp(Loc loc, Expression *e1, Expression *e2); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class AddExp : public BinExp |
| { |
| public: |
| AddExp(Loc loc, Expression *e1, Expression *e2); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class MinExp : public BinExp |
| { |
| public: |
| MinExp(Loc loc, Expression *e1, Expression *e2); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class CatExp : public BinExp |
| { |
| public: |
| CatExp(Loc loc, Expression *e1, Expression *e2); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class MulExp : public BinExp |
| { |
| public: |
| MulExp(Loc loc, Expression *e1, Expression *e2); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class DivExp : public BinExp |
| { |
| public: |
| DivExp(Loc loc, Expression *e1, Expression *e2); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class ModExp : public BinExp |
| { |
| public: |
| ModExp(Loc loc, Expression *e1, Expression *e2); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class PowExp : public BinExp |
| { |
| public: |
| PowExp(Loc loc, Expression *e1, Expression *e2); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class ShlExp : public BinExp |
| { |
| public: |
| ShlExp(Loc loc, Expression *e1, Expression *e2); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class ShrExp : public BinExp |
| { |
| public: |
| ShrExp(Loc loc, Expression *e1, Expression *e2); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class UshrExp : public BinExp |
| { |
| public: |
| UshrExp(Loc loc, Expression *e1, Expression *e2); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class AndExp : public BinExp |
| { |
| public: |
| AndExp(Loc loc, Expression *e1, Expression *e2); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class OrExp : public BinExp |
| { |
| public: |
| OrExp(Loc loc, Expression *e1, Expression *e2); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class XorExp : public BinExp |
| { |
| public: |
| XorExp(Loc loc, Expression *e1, Expression *e2); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class OrOrExp : public BinExp |
| { |
| public: |
| OrOrExp(Loc loc, Expression *e1, Expression *e2); |
| Expression *toBoolean(Scope *sc); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class AndAndExp : public BinExp |
| { |
| public: |
| AndAndExp(Loc loc, Expression *e1, Expression *e2); |
| Expression *toBoolean(Scope *sc); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class CmpExp : public BinExp |
| { |
| public: |
| CmpExp(TOK op, Loc loc, Expression *e1, Expression *e2); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class InExp : public BinExp |
| { |
| public: |
| InExp(Loc loc, Expression *e1, Expression *e2); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class RemoveExp : public BinExp |
| { |
| public: |
| RemoveExp(Loc loc, Expression *e1, Expression *e2); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| // == and != |
| |
| class EqualExp : public BinExp |
| { |
| public: |
| EqualExp(TOK op, Loc loc, Expression *e1, Expression *e2); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| // is and !is |
| |
| class IdentityExp : public BinExp |
| { |
| public: |
| IdentityExp(TOK op, Loc loc, Expression *e1, Expression *e2); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| /****************************************************************/ |
| |
| class CondExp : public BinExp |
| { |
| public: |
| Expression *econd; |
| |
| CondExp(Loc loc, Expression *econd, Expression *e1, Expression *e2); |
| Expression *syntaxCopy(); |
| int checkModifiable(Scope *sc, int flag); |
| bool isLvalue(); |
| Expression *toLvalue(Scope *sc, Expression *e); |
| Expression *modifiableLvalue(Scope *sc, Expression *e); |
| Expression *toBoolean(Scope *sc); |
| void hookDtors(Scope *sc); |
| |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| /****************************************************************/ |
| |
| class DefaultInitExp : public Expression |
| { |
| public: |
| TOK subop; // which of the derived classes this is |
| |
| DefaultInitExp(Loc loc, TOK subop, int size); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class FileInitExp : public DefaultInitExp |
| { |
| public: |
| FileInitExp(Loc loc, TOK tok); |
| Expression *resolveLoc(Loc loc, Scope *sc); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class LineInitExp : public DefaultInitExp |
| { |
| public: |
| LineInitExp(Loc loc); |
| Expression *resolveLoc(Loc loc, Scope *sc); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class ModuleInitExp : public DefaultInitExp |
| { |
| public: |
| ModuleInitExp(Loc loc); |
| Expression *resolveLoc(Loc loc, Scope *sc); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class FuncInitExp : public DefaultInitExp |
| { |
| public: |
| FuncInitExp(Loc loc); |
| Expression *resolveLoc(Loc loc, Scope *sc); |
| void accept(Visitor *v) { v->visit(this); } |
| }; |
| |
| class PrettyFuncInitExp : public DefaultInitExp |
| { |
| public: |
| PrettyFuncInitExp(Loc loc); |
| Expression *resolveLoc(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 |
| }; |
| |
| /****************************************************************/ |
| |
| /* Special values used by the interpreter |
| */ |
| |
| Expression *expType(Type *type, Expression *e); |
| |
| UnionExp Neg(Type *type, Expression *e1); |
| UnionExp Com(Type *type, Expression *e1); |
| UnionExp Not(Type *type, Expression *e1); |
| UnionExp Bool(Type *type, Expression *e1); |
| UnionExp Cast(Loc loc, Type *type, Type *to, Expression *e1); |
| UnionExp ArrayLength(Type *type, Expression *e1); |
| UnionExp Ptr(Type *type, Expression *e1); |
| |
| UnionExp Add(Loc loc, Type *type, Expression *e1, Expression *e2); |
| UnionExp Min(Loc loc, Type *type, Expression *e1, Expression *e2); |
| UnionExp Mul(Loc loc, Type *type, Expression *e1, Expression *e2); |
| UnionExp Div(Loc loc, Type *type, Expression *e1, Expression *e2); |
| UnionExp Mod(Loc loc, Type *type, Expression *e1, Expression *e2); |
| UnionExp Pow(Loc loc, Type *type, Expression *e1, Expression *e2); |
| UnionExp Shl(Loc loc, Type *type, Expression *e1, Expression *e2); |
| UnionExp Shr(Loc loc, Type *type, Expression *e1, Expression *e2); |
| UnionExp Ushr(Loc loc, Type *type, Expression *e1, Expression *e2); |
| UnionExp And(Loc loc, Type *type, Expression *e1, Expression *e2); |
| UnionExp Or(Loc loc, Type *type, Expression *e1, Expression *e2); |
| UnionExp Xor(Loc loc, Type *type, Expression *e1, Expression *e2); |
| UnionExp Index(Type *type, Expression *e1, Expression *e2); |
| UnionExp Cat(Type *type, Expression *e1, Expression *e2); |
| |
| UnionExp Equal(TOK op, Loc loc, Type *type, Expression *e1, Expression *e2); |
| UnionExp Cmp(TOK op, Loc loc, Type *type, Expression *e1, Expression *e2); |
| UnionExp Identity(TOK op, Loc loc, Type *type, Expression *e1, Expression *e2); |
| |
| UnionExp Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr); |
| |
| // Const-folding functions used by CTFE |
| |
| void sliceAssignArrayLiteralFromString(ArrayLiteralExp *existingAE, StringExp *newval, size_t firstIndex); |
| void sliceAssignStringFromArrayLiteral(StringExp *existingSE, ArrayLiteralExp *newae, size_t firstIndex); |
| void sliceAssignStringFromString(StringExp *existingSE, StringExp *newstr, size_t firstIndex); |
| |
| int sliceCmpStringWithString(StringExp *se1, StringExp *se2, size_t lo1, size_t lo2, size_t len); |
| int sliceCmpStringWithArray(StringExp *se1, ArrayLiteralExp *ae2, size_t lo1, size_t lo2, size_t len); |