Report a bug
If you spot a problem with this page, click here to create a Bugzilla issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.

dmd.expression

Defines the bulk of the classes which represent the AST at the expression level.

Specification ($LINK2 https://dlang.org/spec/expression.html, Expressions)

Authors:

Source expression.d

enum Modifiable: int;
Return value for checkModifiable
no
Not modifiable
yes
Modifiable (the type is mutable)
initialization
Modifiable because it is initialization
enum ModifyFlags: int;
Specifies how the checkModify deals with certain situations
none
Issue error messages on invalid modifications of the variable
noError
No errors are emitted for invalid modifications
fieldAssign
The modification occurs for a subfield of the current variable
inout(Expression) lastComma(inout Expression e);
Find the last non-comma expression.
Parameters:
Expression e Expressions connected by commas
Returns:
right-most non-comma expression
void expandTuples(Expressions* exps, Identifiers* names = null);
Expand tuples in-place.

Example When there's a call f(10, pair: AliasSeq!(20, 30), single: 40), the input is: exps = [10, (20, 30), 40] names = [null, "pair", "single"] The arrays will be modified to: exps = [10, 20, 30, 40] names = [null, "pair", null, "single"]

Parameters:
Expressions* exps array of Expressions
Identifiers* names optional array of names corresponding to Expressions
TupleDeclaration isAliasThisTuple(Expression e);
Expand alias this tuples.
@safe TemplateDeclaration getFuncTemplateDecl(Dsymbol s);
If s is a function template, i.e. the only member of a template and that member is a function, return that template.
Parameters:
Dsymbol s symbol that might be a function template
Returns:
template for that function, otherwise null
@safe DotIdExp typeDotIdExp(const ref Loc loc, Type type, Identifier ident);
TypeDotIdExp
VarDeclaration expToVariable(Expression e);
Given an Expression, find the variable it really is.
For example, a[index] is really a, and s.f is really s.
Parameters:
Expression e Expression to look at
Returns:
variable if there is one, null if not
abstract class Expression: dmd.ast_node.ASTNode;
final const pure nothrow @nogc @safe size_t size();
Returns:
class instance size of this expression (implemented manually because extern(C++))
static void deinitialize();
Deinitializes the global state of the compiler.
This can be used to restore the state set by _init to its original state.
final Expression copy();
Does not do a deep copy.
static @safe Expression combine(Expression e1, Expression e2);
Combine e1 and e2 by CommaExp if both are not NULL.
static @safe Expression extractLast(Expression e, out Expression e0);
If 'e' is a tree of commas, returns the rightmost expression by stripping off it from the tree. The remained part of the tree is returned via e0. Otherwise 'e' is directly returned and e0 is set to NULL.
bool isLvalue();
Return !=0 if expression is an lvalue.
bool checkType();
Check that the expression has a valid type. If not, generates an error "... has no type".
Returns:
true if the expression is not valid.

Note When this function returns true, checkValue() should also return true.

bool checkValue();
Check that the expression has a valid value. If not, generates an error "... has no value".
Returns:
true if the expression is not valid or has void type.
final bool checkReadModifyWrite(EXP rmwOp, Expression ex = null);
Check whether the expression allows RMW operations, error with rmw operator diagnostic if not. ex is the RHS expression, or NULL if ++/-- is used (for diagnostics) Returns true if error occurs.
final Expression addressOf();
Take address of expression.
final Expression deref();
If this is a reference, dereference it.
const bool isIdentical(const Expression e);
Identical, not just equal. I.e. NaNs with different bit patterns are not identical
Optional!bool toBool();
Statically evaluate this expression to a bool if possible
Returns:
an optional thath either contains the value or is empty
class IntegerExp: dmd.expression.Expression;
A compile-time known integer value
IntegerExp literal(int v)();
Use this instead of creating new instances for commonly used literals such as 0 or 1.

Parameters v = The value of the expression

Returns:
A static instance of the expression, typed as Tint32.
static IntegerExp createBool(bool b);
Use this instead of creating new instances for commonly used bools.

Parameters b = The value of the expression

Returns:
A static instance of the expression, typed as Type.tbool.
class ErrorExp: dmd.expression.Expression;
Use this expression for error recovery.
It should behave as a 'sink' to prevent further cascaded error messages.
class VoidInitExp: dmd.expression.Expression;
An uninitialized value, generated from void initializers.
VarDeclaration var;
the variable from where the void value came from, null if not known
@safe this(VarDeclaration var);
Useful for error messages
class RealExp: dmd.expression.Expression;
A compile-time known floating point number
class ComplexExp: dmd.expression.Expression;
A compile-time complex number (deprecated)
class IdentifierExp: dmd.expression.Expression;
An identifier in the context of an expression (as opposed to a declaration)
int x; // VarDeclaration with Identifier
x++; // PostExp with IdentifierExp
class DollarExp: dmd.expression.IdentifierExp;
The dollar operator used when indexing or slicing an array. E.g a[$], a[1 .. $] etc.
class DsymbolExp: dmd.expression.Expression;
Won't be generated by parser.
class ThisExp: dmd.expression.Expression;
class SuperExp: dmd.expression.ThisExp;
class NullExp: dmd.expression.Expression;
A compile-time known null value
class StringExp: dmd.expression.Expression;
bool committed;
Whether the string literal's type is fixed

Example

wstring x = "abc"; // OK, string literal is flexible
wstring y = cast(string) "abc"; // Error: type was committed after cast

bool hexString;
If the string is parsed from a hex string literal
const size_t numberOfCodeUnits(int tynto = 0);
Return the number of code units the string would be if it were re-encoded as tynto.
Parameters:
int tynto code unit type of the target encoding
Returns:
number of code units
const void writeTo(void* dest, bool zero, int tyto = 0);
Write the contents of the string to dest. Use numberOfCodeUnits() to determine size of result.
Parameters:
void* dest destination
int tyto encoding type of the result
bool zero add terminating 0
const pure dchar getCodeUnit(size_t i);
Get the code unit at index i
Parameters:
size_t i index
Returns:
code unit at index i
void setCodeUnit(size_t i, dchar c);
Set the code unit at index i to c
Parameters:
size_t i index
dchar c code unit to set it to
const pure nothrow @nogc int compare(const StringExp se2);
Compare two StringExp by length, then value
The comparison is not the usual C-style comparison as seen with strcmp or memcmp, but instead first compare based on the length. This allows both faster lookup and sorting when comparing sparse data.
This ordering scheme is relied on by the string-switching feature. Code in Druntime's core.internal.switch_ relies on this ordering when doing a binary search among case statements.
Both StringExp should be of the same encoding.
Parameters:
StringExp se2 String expression to compare this to
Returns:
0 when this is equal to se2, a value greater than 0 if this should be considered greater than se2, and a value less than 0 if this is lesser than se2.
const const(char)[] toStringz();
Convert string contents to a 0 terminated string, allocated by mem.xmalloc().
const const(ubyte)[] peekData();
Get a slice of the data.
ubyte[] borrowData();
Borrow a slice of the data, so the caller can modify it in-place (!)
void setData(void* s, size_t len, ubyte sz);
Set new string data. this becomes the new owner of the data.
class TupleExp: dmd.expression.Expression;
A sequence of expressions
alias AliasSeq(T...) = T;
alias Tup = AliasSeq!(3, int, "abc");
class ArrayLiteralExp: dmd.expression.Expression;
[ e1, e2, e3, ... ]
Expression basis;
If !is null, elements[] can be sparse and basis is used for the "default" element value. In other words, non-null elements[i] overrides this 'basis' value.
class AssocArrayLiteralExp: dmd.expression.Expression;
[ key0 : value0, key1 : value1, ... ]
Expression lowering;
Lower to core.internal.newaa for static initializaton
enum int stageScrub;
scrubReturnValue is running
enum int stageSearchPointers;
hasNonConstPointers is running
enum int stageOptimize;
optimize is running
enum int stageApply;
apply is running
enum int stageInlineScan;
inlineScan is running
enum int stageToCBuffer;
toCBuffer is running
class StructLiteralExp: dmd.expression.Expression;
sd( e1, e2, e3, ... )
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)
void* sym;
back end symbol to initialize with literal (used as a Symbol*)
StructLiteralExp inlinecopy;
those fields need to prevent a infinite recursion when one field of struct initialized with 'this' pointer.
StructLiteralExp origin;
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.
ubyte stageflags;
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.
bool useStaticInit;
if this is true, use the StructDeclaration's init symbol
bool isOriginal;
used when moving instances to indicate this is this.origin
Expression getField(Type type, uint offset);
Gets expression at offset of type. Returns NULL if not found.
int getFieldIndex(Type type, uint offset);
Get index of field. Returns -1 if not found.
class CompoundLiteralExp: dmd.expression.Expression;
C11 6.5.2.5 ( type-name ) { initializer-list }
Initializer initializer;
initializer-list
class TypeExp: dmd.expression.Expression;
Mainly just a placeholder
class ScopeExp: dmd.expression.Expression;
Mainly just a placeholder of Package, Module, Nspace, and TemplateInstance (including TemplateMixin)
A template instance that requires IFTI: foo!tiargs(fargs) // foo!tiargs is left until CallExp::semantic() or resolveProperties()
class TemplateExp: dmd.expression.Expression;
Mainly just a placeholder
class NewExp: dmd.expression.Expression;
newtype(arguments)
ArgumentList argumentList();
Puts the arguments and names into an ArgumentList for easily passing them around. The fields are still separate for backwards compatibility
class NewAnonClassExp: dmd.expression.Expression;
class baseclasses { } (arguments)
class SymbolExp: dmd.expression.Expression;
class SymOffExp: dmd.expression.SymbolExp;
Offset from symbol
class VarExp: dmd.expression.SymbolExp;
Variable
class OverExp: dmd.expression.Expression;
Overload Set
class FuncExp: dmd.expression.Expression;
Function/Delegate literal
class DeclarationExp: dmd.expression.Expression;
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 TypeidExp: dmd.expression.Expression;
typeid(int)
class TraitsExp: dmd.expression.Expression;
_traits(identifier, args...)
class HaltExp: dmd.expression.Expression;
Generates a halt instruction
assert(0) gets rewritten to this with CHECKACTION.halt
class IsExp: dmd.expression.Expression;
is(targ id tok tspec) is(targ id == tok2)
abstract class UnaExp: dmd.expression.Expression;
Base class for unary operators
final Expression incompatibleTypes();
The type for a unary expression is incompatible. Print error message.
Returns:
ErrorExp
final void setNoderefOperand();
Mark the operand as will never be dereferenced, which is useful info for @safe checks. Do before semantic() on operands rewrites them.
abstract class BinExp: dmd.expression.Expression;
Base class for binary operators
final Expression incompatibleTypes();
The types for a binary expression are incompatible. Print error message.
Returns:
ErrorExp
final void setNoderefOperands();
Mark the operands as will never be dereferenced, which is useful info for @safe checks. Do before semantic() on operands rewrites them.
class BinAssignExp: dmd.expression.BinExp;
Binary operator assignment, += -= *= etc.
class MixinExp: dmd.expression.Expression;
A string mixin, mixin("x")
class ImportExp: dmd.expression.UnaExp;
An import expression, import("file.txt")
Not to be confused with module imports, import std.stdio, which is an ImportStatement
https://dlang.org/spec/expression.html#import_expressions
class AssertExp: dmd.expression.UnaExp;
An assert expression, assert(x == y)
class ThrowExp: dmd.expression.UnaExp;
throw <e1> as proposed by DIP 1034.
Replacement for the deprecated ThrowStatement that can be nested in other expression.
class DotIdExp: dmd.expression.UnaExp;
class DotTemplateExp: dmd.expression.UnaExp;
Mainly just a placeholder
class DotVarExp: dmd.expression.UnaExp;
class DotTemplateInstanceExp: dmd.expression.UnaExp;
foo.bar!(args)
class DelegateExp: dmd.expression.UnaExp;
class DotTypeExp: dmd.expression.UnaExp;
struct ArgumentList;
The arguments of a function call
Contains a list of expressions. If it is a named argument, the names list has a non-null entry at the same index.
const pure nothrow @nogc @safe bool hasNames();
Returns:
whether this argument list contains any named arguments
class CallExp: dmd.expression.UnaExp;
bool inDebugStatement;
true if this was in a debug statement
bool ignoreAttributes;
don't enforce attributes (e.g. call @gc function in @nogc code)
bool isUfcsRewrite;
the first argument was pushed in here by a UFCS rewrite
ArgumentList argumentList();
Puts the arguments and names into an ArgumentList for easily passing them around. The fields are still separate for backwards compatibility
this(const ref Loc loc, FuncDeclaration fd, Expression earg1);
Instatiates a new function call expression
Parameters:
Loc loc location
FuncDeclaration fd the declaration of the function to call
Expression earg1 the function argument
static CallExp create(const ref Loc loc, FuncDeclaration fd, Expression earg1);
Creates a new function call expression
Parameters:
Loc loc location
FuncDeclaration fd the declaration of the function to call
Expression earg1 the function argument
TypeFunction calledFunctionType(CallExp ce);
Get the called function type from a call expression
Parameters:
CallExp ce function call expression. Must have had semantic analysis done.
Returns:
called function type, or null if error / no semantic analysis done
class AddrExp: dmd.expression.UnaExp;
The 'address of' operator, &p
class PtrExp: dmd.expression.UnaExp;
The pointer dereference operator, *p
class NegExp: dmd.expression.UnaExp;
The negation operator, -x
class UAddExp: dmd.expression.UnaExp;
The unary add operator, +x
class ComExp: dmd.expression.UnaExp;
The bitwise complement operator, ~x
class NotExp: dmd.expression.UnaExp;
The logical not operator, !x
class DeleteExp: dmd.expression.UnaExp;
The delete operator, delete x (deprecated)
class CastExp: dmd.expression.UnaExp;
The type cast operator, cast(T) x
It's possible to cast to one type while painting to another type
https://dlang.org/spec/expression.html#cast_expressions
class VectorExp: dmd.expression.UnaExp;
class VectorArrayExp: dmd.expression.UnaExp;
e1.array property for vectors.
class SliceExp: dmd.expression.UnaExp;
e1 [lwr .. upr]
@safe this(const ref Loc loc, Expression e1, IntervalExp ie);
class ArrayLengthExp: dmd.expression.UnaExp;
The .length property of an array
class ArrayExp: dmd.expression.UnaExp;
e1 [ a0, a1, a2, a3 ,... ]
class DotExp: dmd.expression.BinExp;
class CommaExp: dmd.expression.BinExp;
const bool isGenerated;
This is needed because AssignExp rewrites CommaExp, hence it needs to trigger the deprecation.
bool allowCommaExp;
Temporary variable to enable / disable deprecation of comma expression depending on the context. Since most constructor calls are rewritting, the only place where false will be passed will be from the parser.
static @safe void allow(Expression exp);
If the argument is a CommaExp, set a flag to prevent deprecation messages
It's impossible to know from CommaExp.semantic if the result will be used, hence when there is a result (type != void), a deprecation message is always emitted. However, some construct can produce a result but won't use it (ExpStatement and for loop increment). Those should call this function to prevent unwanted deprecations to be emitted.
Parameters:
Expression exp An expression that discards its result. If the argument is null or not a CommaExp, nothing happens.
class IntervalExp: dmd.expression.Expression;
Mainly just a placeholder
class DelegatePtrExp: dmd.expression.UnaExp;
The dg.ptr property, pointing to the delegate's 'context'
c.f.DelegateFuncptrExp for the delegate's function pointer dg.funcptr
class DelegateFuncptrExp: dmd.expression.UnaExp;
The dg.funcptr property, pointing to the delegate's function
c.f.DelegatePtrExp for the delegate's function pointer dg.ptr
class IndexExp: dmd.expression.BinExp;
e1 [ e2 ]
class PostExp: dmd.expression.BinExp;
The postfix increment/decrement operator, i++ / i--
class PreExp: dmd.expression.UnaExp;
The prefix increment/decrement operator, ++i / --i
class AssignExp: dmd.expression.BinExp;
The assignment / initialization operator, =

Note operator assignment op= has a different base class, BinAssignExp

@safe this(const ref Loc loc, Expression e1, Expression e2);
class LoweredAssignExp: dmd.expression.AssignExp;
When an assignment expression is lowered to a druntime call this class is used to store the lowering. It essentially behaves the same as an AssignExp, but it is used to not waste space for other AssignExp that are not lowered to anything.
class ConstructExp: dmd.expression.AssignExp;
class BlitExp: dmd.expression.AssignExp;
A bit-for-bit copy from e2 to e1
class AddAssignExp: dmd.expression.BinAssignExp;
x += y
class MinAssignExp: dmd.expression.BinAssignExp;
x -= y
class MulAssignExp: dmd.expression.BinAssignExp;
x *= y
class DivAssignExp: dmd.expression.BinAssignExp;
x /= y
class ModAssignExp: dmd.expression.BinAssignExp;
x %= y
class AndAssignExp: dmd.expression.BinAssignExp;
x &= y
class OrAssignExp: dmd.expression.BinAssignExp;
x |= y
class XorAssignExp: dmd.expression.BinAssignExp;
x ^= y
class PowAssignExp: dmd.expression.BinAssignExp;
x ^^= y
class ShlAssignExp: dmd.expression.BinAssignExp;
x <<= y
class ShrAssignExp: dmd.expression.BinAssignExp;
x >>= y
class UshrAssignExp: dmd.expression.BinAssignExp;
x >>>= y
class CatAssignExp: dmd.expression.BinAssignExp;
The ~= operator.
It can have one of the following operators:
EXP.concatenateAssign - appending T[] to T[] EXP.concatenateElemAssign - appending T to T[] EXP.concatenateDcharAssign - appending dchar to T[]
The parser initially sets it to EXP.concatenateAssign, and semantic() later decides which of the three it will be set to.
class CatElemAssignExp: dmd.expression.CatAssignExp;
The ~= operator when appending a single element
class CatDcharAssignExp: dmd.expression.CatAssignExp;
The ~= operator when appending a single dchar
class AddExp: dmd.expression.BinExp;
The addition operator, x + y
class MinExp: dmd.expression.BinExp;
The minus operator, x - y
class CatExp: dmd.expression.BinExp;
The concatenation operator, x ~ y
class MulExp: dmd.expression.BinExp;
The multiplication operator, x * y
class DivExp: dmd.expression.BinExp;
The division operator, x / y
class ModExp: dmd.expression.BinExp;
The modulo operator, x % y
class PowExp: dmd.expression.BinExp;
The 'power' operator, x ^^ y
class ShlExp: dmd.expression.BinExp;
The 'shift left' operator, x << y
class ShrExp: dmd.expression.BinExp;
The 'shift right' operator, x >> y
class UshrExp: dmd.expression.BinExp;
The 'unsigned shift right' operator, x >>> y
class AndExp: dmd.expression.BinExp;
The bitwise 'and' operator, x & y
class OrExp: dmd.expression.BinExp;
The bitwise 'or' operator, x | y
class XorExp: dmd.expression.BinExp;
The bitwise 'xor' operator, x ^ y
class LogicalExp: dmd.expression.BinExp;
The logical 'and' / 'or' operator, X && Y / X || Y
class CmpExp: dmd.expression.BinExp;
A comparison operator, < <= > >=
op is one of: EXP.lessThan, EXP.lessOrEqual, EXP.greaterThan, EXP.greaterOrEqual
https://dlang.org/spec/expression.html#relation_expressions
class InExp: dmd.expression.BinExp;
The in operator, "a" in ["a": 1]

Note x !in y is rewritten to !(x in y) in the parser

https://dlang.org/spec/expression.html#in_expressions

class RemoveExp: dmd.expression.BinExp;
Associative array removal, aa.remove(arg)
This deletes the key e1 from the associative array e2
class EqualExp: dmd.expression.BinExp;
== and !=
class IdentityExp: dmd.expression.BinExp;
is and !is
class CondExp: dmd.expression.BinExp;
The ternary operator, econd ? e1 : e2
class DefaultInitExp: dmd.expression.Expression;
A special keyword when used as a function's default argument
When possible, special keywords are resolved in the parser, but when appearing as a default argument, they result in an expression deriving from this base class that is resolved for each function call.
const x = __LINE__; // resolved in the parser
void foo(string file = __FILE__, int line = __LINE__); // DefaultInitExp
https://dlang.org/spec/expression.html#specialkeywords
@safe this(const ref Loc loc, EXP op);
Parameters:
Loc loc location
EXP op EXP.prettyFunction, EXP.functionString, EXP.moduleString, EXP.line, EXP.file, EXP.fileFullPath
class FileInitExp: dmd.expression.DefaultInitExp;
The __FILE__ token as a default argument
class LineInitExp: dmd.expression.DefaultInitExp;
The __LINE__ token as a default argument
class ModuleInitExp: dmd.expression.DefaultInitExp;
The __MODULE__ token as a default argument
class FuncInitExp: dmd.expression.DefaultInitExp;
The __FUNCTION__ token as a default argument
class PrettyFuncInitExp: dmd.expression.DefaultInitExp;
The __PRETTY_FUNCTION__ token as a default argument
class ClassReferenceExp: dmd.expression.Expression;
A reference to a class, or an interface. We need this when we point to a base class (we must record what the type is).
class CTFEExp: dmd.expression.Expression;
This type is only used by the interpreter.
class ThrownExceptionExp: dmd.expression.Expression;
Fake class which holds the thrown exception. Used for implementing exception handling.
class ObjcClassReferenceExp: dmd.expression.Expression;
Objective-C class reference expression.
Used to get the metaclass of an Objective-C class, NSObject.Class.
class GenericExp: dmd.expression.Expression;
C11 6.5.1.1 Generic Selection For ImportC
Expression cntlExp;
controlling expression of a generic selection (not evaluated)
Types* types;
type-names for generic associations (null entry for default)
Expressions* exps;
1:1 mapping of typeNames to exps
bool isArrayConstruction(const Identifier id);
Verify if the given identifier is d_array{,set}ctor.
Parameters:
Identifier id the identifier to verify
Returns:
true if the identifier corresponds to a construction runtime hook, false otherwise.