blob: 3c8d90dd7eb61534133d6fa3b2c85a1125acb441 [file] [log] [blame]
/* Compiler implementation of the D programming language
* Copyright (C) 1999-2025 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;
class InterpExp;
class LoweredAssignExp;
class StaticForeach;
#ifdef IN_GCC
typedef union tree_node Symbol;
#else
struct Symbol; // back end symbol
#endif
namespace dmd
{
// in expressionsem.d
Expression *expressionSemantic(Expression *e, Scope *sc);
void lowerNonArrayAggregate(StaticForeach *sfe, Scope *sc);
// in typesem.d
Expression *defaultInit(Type *mt, Loc loc, const bool isCfile = false);
// Entry point for CTFE.
// A compile-time result is required. Give an error if not possible
Expression *ctfeInterpret(Expression *e);
void expandTuples(Expressions *exps, Identifiers *names = nullptr);
Expression *optimize(Expression *exp, int result, bool keepLvalue = false);
}
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
class Expression : public ASTNode
{
public:
Type *type; // !=NULL means that semantic() has been run
Loc loc; // file location
EXP op; // to minimize use of dynamic_cast
uint8_t bitFields;
bool parens() const;
bool parens(bool v);
bool rvalue() const;
bool rvalue(bool v);
size_t size() const;
static void _init();
virtual Expression *syntaxCopy();
// kludge for template.isExpression()
DYNCAST dyncast() const override final { return DYNCAST_EXPRESSION; }
const char* toChars() const final override;
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 bool checkType();
Expression *addressOf();
Expression *deref();
int isConst();
virtual bool isIdentical(const Expression *e) const;
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();
InterpExp* isInterpExp();
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* isIsExp();
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();
CatElemAssignExp* isCatElemAssignExp();
CatDcharAssignExp* isCatDcharAssignExp();
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();
LoweredAssignExp* isLoweredAssignExp();
void accept(Visitor *v) override { v->visit(this); }
};
class IntegerExp final : public Expression
{
public:
dinteger_t value;
static IntegerExp *create(Loc loc, dinteger_t value, Type *type);
bool equals(const RootObject * const o) const override;
dinteger_t toInteger() override;
real_t toReal() override;
real_t toImaginary() override;
complex_t toComplex() override;
Optional<bool> toBool() override;
void accept(Visitor *v) override { v->visit(this); }
dinteger_t getInteger() { return value; }
template<int v>
static IntegerExp literal();
};
class ErrorExp final : public Expression
{
public:
void accept(Visitor *v) override { v->visit(this); }
static ErrorExp *errorexp; // handy shared value
};
class RealExp final : public Expression
{
public:
real_t value;
static RealExp *create(Loc loc, real_t value, Type *type);
bool equals(const RootObject * const o) const override;
bool isIdentical(const Expression *e) const override;
dinteger_t toInteger() override;
uinteger_t toUInteger() override;
real_t toReal() override;
real_t toImaginary() override;
complex_t toComplex() override;
Optional<bool> toBool() override;
void accept(Visitor *v) override { v->visit(this); }
};
class ComplexExp final : public Expression
{
public:
complex_t value;
static ComplexExp *create(Loc loc, complex_t value, Type *type);
bool equals(const RootObject * const o) const override;
bool isIdentical(const Expression *e) const override;
dinteger_t toInteger() override;
uinteger_t toUInteger() override;
real_t toReal() override;
real_t toImaginary() override;
complex_t toComplex() override;
Optional<bool> toBool() override;
void accept(Visitor *v) override { v->visit(this); }
};
class IdentifierExp : public Expression
{
public:
Identifier *ident;
static IdentifierExp *create(Loc loc, Identifier *ident);
bool isLvalue() override final;
void accept(Visitor *v) override { v->visit(this); }
};
class DollarExp final : public IdentifierExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class DsymbolExp final : public Expression
{
public:
Dsymbol *s;
d_bool hasOverloads;
DsymbolExp *syntaxCopy() override;
bool isLvalue() override;
void accept(Visitor *v) override { v->visit(this); }
};
class ThisExp : public Expression
{
public:
VarDeclaration *var;
ThisExp *syntaxCopy() override;
Optional<bool> toBool() override;
bool isLvalue() override;
void accept(Visitor *v) override { v->visit(this); }
};
class SuperExp final : public ThisExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class NullExp final : public Expression
{
public:
bool equals(const RootObject * const o) const override;
Optional<bool> toBool() override;
StringExp *toStringExp() override;
void accept(Visitor *v) override { v->visit(this); }
};
class StringExp final : public Expression
{
public:
utf8_t postfix; // 'c', 'w', 'd'
OwnedBy ownedByCtfe;
void *string; // char, wchar, dchar, or long data
size_t len; // number of chars, wchars, or dchars
unsigned char sz; // 1: char, 2: wchar, 4: dchar
d_bool committed; // if type is committed
d_bool hexString; // if string is parsed from a hex string literal
static StringExp *create(Loc loc, const char *s);
static StringExp *create(Loc loc, const void *s, d_size_t len);
bool equals(const RootObject * const o) const override;
char32_t getCodeUnit(d_size_t i) const;
dinteger_t getIndex(d_size_t i) const;
StringExp *toStringExp() override;
Optional<bool> toBool() override;
bool isLvalue() override;
void accept(Visitor *v) override { v->visit(this); }
size_t numberOfCodeUnits(int tynto = 0) const;
void writeTo(void* dest, bool zero, int tyto = 0) const;
};
class InterpExp final : public Expression
{
public:
utf8_t postfix; // 'c', 'w', 'd'
OwnedBy ownedByCtfe;
void* interpolatedSet;
void accept(Visitor* v) override { v->visit(this); }
};
// Tuple
class TupleExp final : 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(Loc loc, Expressions *exps);
TupleExp *syntaxCopy() override;
bool equals(const RootObject * const o) const override;
void accept(Visitor *v) override { v->visit(this); }
};
class ArrayLiteralExp final : public Expression
{
public:
OwnedBy ownedByCtfe;
d_bool onstack;
Expression *basis;
Expressions *elements;
static ArrayLiteralExp *create(Loc loc, Expressions *elements);
ArrayLiteralExp *syntaxCopy() override;
bool equals(const RootObject * const o) const override;
Expression *getElement(d_size_t i);
Optional<bool> toBool() override;
StringExp *toStringExp() override;
void accept(Visitor *v) override { v->visit(this); }
};
class AssocArrayLiteralExp final : public Expression
{
public:
OwnedBy ownedByCtfe;
Expressions *keys;
Expressions *values;
Expression* lowering;
bool equals(const RootObject * const o) const override;
AssocArrayLiteralExp *syntaxCopy() override;
Optional<bool> toBool() override;
void accept(Visitor *v) override { v->visit(this); }
};
class StructLiteralExp final : public Expression
{
public:
uint8_t bitFields;
// if this is true, use the StructDeclaration's init symbol
bool useStaticInit() const;
bool useStaticInit(bool v);
// used when moving instances to indicate `this is this.origin`
bool isOriginal() const;
bool isOriginal(bool v);
OwnedBy ownedByCtfe() const;
OwnedBy ownedByCtfe(OwnedBy v);
/** 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.
*/
uint8_t stageflags;
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)
union
{
Symbol *sym; // back end symbol to initialize with literal (used as a Symbol*)
// those fields need to prevent a infinite recursion when one field of struct initialized with 'this' pointer.
StructLiteralExp *inlinecopy;
};
/** 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;
static StructLiteralExp *create(Loc loc, StructDeclaration *sd, void *elements, Type *stype = nullptr);
bool equals(const RootObject * const o) const override;
StructLiteralExp *syntaxCopy() override;
void accept(Visitor *v) override { v->visit(this); }
};
class TypeExp final : public Expression
{
public:
TypeExp *syntaxCopy() override;
bool checkType() override;
void accept(Visitor *v) override { v->visit(this); }
};
class ScopeExp final : public Expression
{
public:
ScopeDsymbol *sds;
ScopeExp *syntaxCopy() override;
bool checkType() override;
void accept(Visitor *v) override { v->visit(this); }
};
class TemplateExp final : public Expression
{
public:
TemplateDeclaration *td;
FuncDeclaration *fd;
bool isLvalue() override;
bool checkType() override;
void accept(Visitor *v) override { v->visit(this); }
};
class NewExp final : public Expression
{
public:
/* newtype(arguments)
*/
Expression *thisexp; // if !NULL, 'this' for class being allocated
Type *newtype;
Expressions *arguments; // Array of Expression's
Identifiers *names; // Array of names corresponding to expressions
Expression *placement; // if !NULL, placement expression
Expression *argprefix; // expression to be evaluated just before arguments[]
CtorDeclaration *member; // constructor function
d_bool onstack; // allocate on stack
d_bool thrownew; // this NewExp is the expression of a ThrowStatement
Expression *lowering; // lowered druntime hook: `_d_newclass`
static NewExp *create(Loc loc, Expression *placement, Expression *thisexp, Type *newtype, Expressions *arguments);
NewExp *syntaxCopy() override;
void accept(Visitor *v) override { v->visit(this); }
};
class NewAnonClassExp final : 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
Expression *placement; // if !NULL, placement expression
NewAnonClassExp *syntaxCopy() override;
void accept(Visitor *v) override { v->visit(this); }
};
class SymbolExp : public Expression
{
public:
Declaration *var;
Dsymbol *originalScope;
d_bool hasOverloads;
void accept(Visitor *v) override { v->visit(this); }
};
// Offset from symbol
class SymOffExp final : public SymbolExp
{
public:
dinteger_t offset;
Optional<bool> toBool() override;
void accept(Visitor *v) override { v->visit(this); }
};
// Variable
class VarExp final : public SymbolExp
{
public:
d_bool delegateWasExtracted;
static VarExp *create(Loc loc, Declaration *var, bool hasOverloads = true);
bool equals(const RootObject * const o) const override;
bool isLvalue() override;
void accept(Visitor *v) override { v->visit(this); }
};
// Overload Set
class OverExp final : public Expression
{
public:
OverloadSet *vars;
bool isLvalue() override;
void accept(Visitor *v) override { v->visit(this); }
};
// Function/Delegate literal
class FuncExp final : public Expression
{
public:
FuncLiteralDeclaration *fd;
TemplateDeclaration *td;
TOK tok;
bool equals(const RootObject * const o) const override;
FuncExp *syntaxCopy() override;
bool checkType() override;
void accept(Visitor *v) override { 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 final : public Expression
{
public:
Dsymbol *declaration;
DeclarationExp *syntaxCopy() override;
bool hasCode() override;
void accept(Visitor *v) override { v->visit(this); }
};
class TypeidExp final : public Expression
{
public:
RootObject *obj;
TypeidExp *syntaxCopy() override;
void accept(Visitor *v) override { v->visit(this); }
};
class TraitsExp final : public Expression
{
public:
Identifier *ident;
Objects *args;
TraitsExp *syntaxCopy() override;
void accept(Visitor *v) override { v->visit(this); }
};
class HaltExp final : public Expression
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class IsExp final : 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() override;
void accept(Visitor *v) override { v->visit(this); }
};
/****************************************************************/
class UnaExp : public Expression
{
public:
Expression *e1;
UnaExp *syntaxCopy() override;
void accept(Visitor *v) override { v->visit(this); }
};
class BinExp : public Expression
{
public:
Expression *e1;
Expression *e2;
BinExp *syntaxCopy() override;
void accept(Visitor *v) override { v->visit(this); }
};
class BinAssignExp : public BinExp
{
public:
bool isLvalue() override final;
void accept(Visitor *v) override { v->visit(this); }
};
/****************************************************************/
class MixinExp final : public UnaExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class ImportExp final : public UnaExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class AssertExp final : public UnaExp
{
public:
Expression *msg;
AssertExp *syntaxCopy() override;
void accept(Visitor *v) override { v->visit(this); }
};
class ThrowExp final : public UnaExp
{
public:
ThrowExp *syntaxCopy() override;
void accept(Visitor *v) override { v->visit(this); }
};
class DotIdExp final : public UnaExp
{
public:
Identifier *ident;
d_bool noderef; // true if the result of the expression will never be dereferenced
d_bool wantsym; // do not replace Symbol with its initializer during semantic()
d_bool arrow; // ImportC: if -> instead of .
static DotIdExp *create(Loc loc, Expression *e, Identifier *ident);
void accept(Visitor *v) override { v->visit(this); }
};
class DotTemplateExp final : public UnaExp
{
public:
TemplateDeclaration *td;
bool checkType() override;
void accept(Visitor *v) override { v->visit(this); }
};
class DotVarExp final : public UnaExp
{
public:
Declaration *var;
d_bool hasOverloads;
bool isLvalue() override;
void accept(Visitor *v) override { v->visit(this); }
};
class DotTemplateInstanceExp final : public UnaExp
{
public:
TemplateInstance *ti;
DotTemplateInstanceExp *syntaxCopy() override;
bool checkType() override;
void accept(Visitor *v) override { v->visit(this); }
};
class DelegateExp final : public UnaExp
{
public:
FuncDeclaration *func;
d_bool hasOverloads;
VarDeclaration *vthis2; // container for multi-context
void accept(Visitor *v) override { v->visit(this); }
};
class DotTypeExp final : public UnaExp
{
public:
Dsymbol *sym; // symbol that represents a type
void accept(Visitor *v) override { v->visit(this); }
};
struct ArgumentList final
{
Expressions* arguments;
Identifiers* names;
ArgumentList() :
arguments(),
names()
{
}
ArgumentList(Expressions* arguments, Identifiers* names = nullptr) :
arguments(arguments),
names(names)
{}
};
class CallExp final : public UnaExp
{
public:
Expressions *arguments; // function arguments
Identifiers *names;
FuncDeclaration *f; // symbol to call
d_bool directcall; // true if a virtual call is devirtualized
d_bool inDebugStatement; // true if this was in a debug statement
d_bool ignoreAttributes; // don't enforce attributes (e.g. call @gc function in @nogc code)
d_bool isUfcsRewrite; // the first argument was pushed in here by a UFCS rewrite
VarDeclaration *vthis2; // container for multi-context
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);
static CallExp *create(Loc loc, FuncDeclaration *fd, Expression *earg1);
CallExp *syntaxCopy() override;
bool isLvalue() override;
void accept(Visitor *v) override { v->visit(this); }
};
class AddrExp final : public UnaExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class PtrExp final : public UnaExp
{
public:
bool isLvalue() override;
void accept(Visitor *v) override { v->visit(this); }
};
class NegExp final : public UnaExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class UAddExp final : public UnaExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class ComExp final : public UnaExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class NotExp final : public UnaExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class DeleteExp final : public UnaExp
{
public:
d_bool isRAII;
void accept(Visitor *v) override { v->visit(this); }
};
class CastExp final : public UnaExp
{
public:
// Possible to cast to one type while painting to another type
Type *to; // type to cast to
unsigned char mod; // MODxxxxx
d_bool trusted; // assume cast is safe
CastExp *syntaxCopy() override;
bool isLvalue() override;
void accept(Visitor *v) override { v->visit(this); }
};
class VectorExp final : public UnaExp
{
public:
TypeVector *to; // the target vector type before semantic()
unsigned dim; // number of elements in the vector
OwnedBy ownedByCtfe;
static VectorExp *create(Loc loc, Expression *e, Type *t);
VectorExp *syntaxCopy() override;
void accept(Visitor *v) override { v->visit(this); }
};
class VectorArrayExp final : public UnaExp
{
public:
bool isLvalue() override;
void accept(Visitor *v) override { v->visit(this); }
};
class SliceExp final : public UnaExp
{
public:
Expression *upr; // NULL if implicit 0
Expression *lwr; // NULL if implicit [length - 1]
VarDeclaration *lengthVar;
bool upperIsInBounds() const; // true if upr <= e1.length
bool upperIsInBounds(bool v);
bool lowerIsLessThanUpper() const; // true if lwr <= upr
bool lowerIsLessThanUpper(bool v);
bool arrayop() const; // an array operation, rather than a slice
bool arrayop(bool v);
private:
uint8_t bitFields;
public:
SliceExp *syntaxCopy() override;
bool isLvalue() override;
Optional<bool> toBool() override;
void accept(Visitor *v) override { v->visit(this); }
};
class ArrayLengthExp final : public UnaExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class IntervalExp final : public Expression
{
public:
Expression *lwr;
Expression *upr;
IntervalExp *syntaxCopy() override;
void accept(Visitor *v) override { v->visit(this); }
};
class DelegatePtrExp final : public UnaExp
{
public:
bool isLvalue() override;
void accept(Visitor *v) override { v->visit(this); }
};
class DelegateFuncptrExp final : public UnaExp
{
public:
bool isLvalue() override;
void accept(Visitor *v) override { v->visit(this); }
};
// e1[a0,a1,a2,a3,...]
class ArrayExp final : public UnaExp
{
public:
Expressions *arguments; // Array of Expression's
size_t currentDimension; // for opDollar
VarDeclaration *lengthVar;
ArrayExp *syntaxCopy() override;
bool isLvalue() override;
void accept(Visitor *v) override { v->visit(this); }
};
/****************************************************************/
class DotExp final : public BinExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class CommaExp final : public BinExp
{
public:
d_bool isGenerated;
d_bool allowCommaExp;
bool isLvalue() override;
Optional<bool> toBool() override;
void accept(Visitor *v) override { v->visit(this); }
};
class IndexExp final : public BinExp
{
public:
VarDeclaration *lengthVar;
d_bool modifiable;
d_bool indexIsInBounds; // true if 0 <= e2 && e2 <= e1.length - 1
IndexExp *syntaxCopy() override;
bool isLvalue() override;
void accept(Visitor *v) override { v->visit(this); }
};
/* For both i++ and i--
*/
class PostExp final : public BinExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
/* For both ++i and --i
*/
class PreExp final : public UnaExp
{
public:
void accept(Visitor *v) override { 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() override final;
void accept(Visitor *v) override { v->visit(this); }
};
class ConstructExp final : public AssignExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class LoweredAssignExp final : public AssignExp
{
public:
Expression *lowering;
void accept(Visitor *v) override { v->visit(this); }
};
class BlitExp final : public AssignExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class AddAssignExp final : public BinAssignExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class MinAssignExp final : public BinAssignExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class MulAssignExp final : public BinAssignExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class DivAssignExp final : public BinAssignExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class ModAssignExp final : public BinAssignExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class AndAssignExp final : public BinAssignExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class OrAssignExp final : public BinAssignExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class XorAssignExp final : public BinAssignExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class PowAssignExp final : public BinAssignExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class ShlAssignExp final : public BinAssignExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class ShrAssignExp final : public BinAssignExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class UshrAssignExp final : public BinAssignExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class CatAssignExp : public BinAssignExp
{
public:
Expression *lowering; // lowered druntime hook `_d_arrayappend{cTX,T}`
void accept(Visitor *v) override { v->visit(this); }
};
class CatElemAssignExp final : public CatAssignExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class CatDcharAssignExp final : public CatAssignExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class AddExp final : public BinExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class MinExp final : public BinExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class CatExp final : public BinExp
{
public:
Expression *lowering; // call to druntime hook `_d_arraycatnTX`
void accept(Visitor *v) override { v->visit(this); }
};
class MulExp final : public BinExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class DivExp final : public BinExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class ModExp final : public BinExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class PowExp final : public BinExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class ShlExp final : public BinExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class ShrExp final : public BinExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class UshrExp final : public BinExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class AndExp final : public BinExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class OrExp final : public BinExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class XorExp final : public BinExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class LogicalExp final : public BinExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class CmpExp final : public BinExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class InExp final : public BinExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class RemoveExp final : public BinExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
// == and !=
class EqualExp final : public BinExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
// is and !is
class IdentityExp final : public BinExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
/****************************************************************/
class CondExp final : public BinExp
{
public:
Expression *econd;
CondExp *syntaxCopy() override;
bool isLvalue() override;
void accept(Visitor *v) override { v->visit(this); }
};
class GenericExp final : Expression
{
Expression *cntlExp;
Types *types;
Expressions *exps;
GenericExp *syntaxCopy() override;
void accept(Visitor *v) override { v->visit(this); }
};
/****************************************************************/
class DefaultInitExp : public Expression
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class FileInitExp final : public DefaultInitExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class LineInitExp final : public DefaultInitExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class ModuleInitExp final : public DefaultInitExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class FuncInitExp final : public DefaultInitExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
class PrettyFuncInitExp final : public DefaultInitExp
{
public:
void accept(Visitor *v) override { v->visit(this); }
};
/****************************************************************/
class ObjcClassReferenceExp final : public Expression
{
public:
ClassDeclaration* classDeclaration;
void accept(Visitor *v) override { v->visit(this); }
};