Menu

- Learn
- Documentation
  - Language Reference
  - Library Reference
  - Command-line Reference
  - Feature Overview
  - Articles
- Downloads
- Packages
- Community
  - Blog
  - Orgs using D
  - Twitter
  - Forums
  - IRC
  - Wiki
  - GitHub
  - Issues
  - Get involved
  - Contributors
  - Foundation
  - Donate
  - Sponsors
- Resources
  - Tour
  - Books
  - Tutorials
  - Tools
  - Editors
  - IDEs
  - Visual D
  - Acknowledgments
  - D Style
  - Glossary
  - Sitemap

Search
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

Compiler implementation of the D programming language.
Authors:
Walter Bright
License:
Boost License 1.0

Source expression.d

Documentation https://dlang.org/phobos/dmd_expression.html

Coverage https://codecov.io/gh/dlang/dmd/src/master/src/dmd/expression.d

Expression `getRightThis`(ref const Loc `loc`, Scope* `sc`, AggregateDeclaration `ad`, Expression `e1`, Declaration `var`, int `flag` = 0);
  Given `var`, get the right this pointer if `var` is in an outer class, but our existing this pointer is in an inner class.
  Parameters:

  Loc `loc` | location to use for error messages
  Scope* `sc` | context
  AggregateDeclaration `ad` | struct or class we need the correct this for
  Expression `e1` | existing this
  Declaration `var` | the specific member of `ad` we're accessing
  int `flag` | if `true`, return null instead of throwing an error

  Returns:
  Expression representing the this for the `var`
Expression `resolve`(ref const Loc `loc`, Scope* `sc`, Dsymbol `s`, bool `hasOverloads`);
  Resolve a symbol `s` and wraps it in an expression object.
  Parameters:

  Loc `loc` | location of use of `s`
  Scope* `sc` | context
  Dsymbol `s` | symbol to `resolve`
  bool `hasOverloads` | applies if `s` represents a function. `true` means it'`s` overloaded and will be resolved later, `false` means it'`s` the exact function symbol.

  Returns:
  `s` turned into an expression, ErrorExp if an error occurred
FuncDeclaration `hasThis`(Scope* `sc`);
  Determine if this is available by walking up the enclosing scopes until a function is found.
  Parameters:

  Scope* `sc` | where to start looking for the enclosing function

  Returns:
  Found function if it satisfies isThis(), otherwise null
bool `isNeedThisScope`(Scope* `sc`, Declaration `d`);
  Determine if a this is needed to access `d`.
  Parameters:

  Scope* `sc` | context
  Declaration `d` | declaration to check

  Returns:
  `true` means a this is needed
Expression `resolvePropertiesOnly`(Scope* `sc`, Expression `e1`);
  If `e1` is a property function (template), resolve it.
bool `isDotOpDispatch`(Expression `e`);
  check `e` is exp.opDispatch!(tiargs) or not It's used to switch to UFCS the semantic analysis path
Expression `resolveUFCS`(Scope* `sc`, CallExp `ce`);
  Pull out callable entity with UFCS.
Expression `resolveUFCSProperties`(Scope* `sc`, Expression `e1`, Expression `e2` = null);
  Pull out property with UFCS.
bool `arrayExpressionSemantic`(Expressions* `exps`, Scope* `sc`, bool `preserveErrors` = false);
  Perform semantic() on an array of Expressions.
void `expandTuples`(Expressions* `exps`);
  Expand tuples.

  Input `exps` aray of Expressions

  Output `exps` rewritten in place

TupleDeclaration `isAliasThisTuple`(Expression `e`);
  Expand alias this tuples.
TemplateDeclaration `getFuncTemplateDecl`(Dsymbol `s`);
  Get TemplateDeclaration enclosing FuncDeclaration.
Expression `valueNoDtor`(Expression `e`);
  If we want the value of this expression, but do not want to call the destructor on it.
Expression `doCopyOrMove`(Scope* `sc`, Expression `e`);
  Handle the postblit call on lvalue, or the move of rvalue.
struct `UnionExp`;
int `RealEquals`(real_t `x1`, real_t `x2`);
  Test to see if two reals are the same. Regard NaN's as equivalent. Regard +0 and -0 as different.
DotIdExp `typeDotIdExp`(ref const Loc `loc`, Type `type`, Identifier `ident`);
  TypeDotIdExp
Expression `resolveOpDollar`(Scope* `sc`, ArrayExp `ae`, Expression* `pe0`);
  Runs semantic on `ae`.arguments. Declares temporary variables if '$' was used.
Expression `resolveOpDollar`(Scope* `sc`, ArrayExp `ae`, IntervalExp `ie`, Expression* `pe0`);
  Runs semantic on se.lwr and se.upr. Declares a temporary variable if '$' was used.
StringExp `semanticString`(Scope* `sc`, Expression `exp`, const char* `s`);
  Resolve `exp` as a compile-time known string.
  Parameters:

  Scope* `sc` | scope
  Expression `exp` | Expression which expected as a string
  char* `s` | What the string is expected for, will be used in error diagnostic.

  Returns:
  String literal, or null if error happens.
abstract class `Expression`: dmd.root.rootobject.RootObject;
  http://dlang.org/spec/expression.html#expression
  final Expression `copy`();
    Does *not* do a deep `copy`.
  static Expression `combine`(Expression `e1`, Expression `e2`);
    Combine `e1` and `e2` by CommaExp if both are not NULL.
  static Expression `extractLast`(Expression `e`, Expression* `pe0`);
    If '`e`' is a tree of commas, returns the leftmost expression by stripping off it from the tree. The remained part of the tree is returned via *`pe0`. Otherwise '`e`' is directly returned and *`pe0` is set to NULL.
  bool `isLvalue`();
    Return !=0 if expression is an lvalue.
  Expression `toLvalue`(Scope* `sc`, Expression `e`);
    Give error if we're not an lvalue. If we can, convert expression to be an lvalue.
  Expression `resolveLoc`(ref const Loc `loc`, Scope* `sc`);
    Resolve __FILE__, __LINE__, __MODULE__, __FUNCTION__, __PRETTY_FUNCTION__, _FILE_FULL_PATH__ to `loc`.
  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 `checkPurity`(Scope* `sc`, FuncDeclaration `f`);
    Calling function `f`. Check the purity, i.e. if we're in a pure function we can only call other pure functions. Returns `true` if error occurs.
  final bool `checkPurity`(Scope* `sc`, VarDeclaration `v`);
    Accessing variable `v`. Check for purity and safety violations. Returns `true` if error occurs.
  final bool `checkSafety`(Scope* `sc`, FuncDeclaration `f`);
    Calling function `f`. Check the safety, i.e. if we're in a @safe function we can only call @safe or @trusted functions. Returns `true` if error occurs.
  final bool `checkNogc`(Scope* `sc`, FuncDeclaration `f`);
    Calling function `f`. Check the @nogc-ness, i.e. if we're in a @nogc function we can only call other @nogc functions. Returns `true` if error occurs.
  final bool `checkPostblit`(Scope* `sc`, Type `t`);
    Check that the postblit is callable if `t` is an array of structs. Returns `true` if error happens.
  final bool `checkReadModifyWrite`(TOK `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.
  int `checkModifiable`(Scope* `sc`, int `flag` = 0);

    Parameters `sc`: scope `flag`: 1: do not issue error message for invalid modification

    Returns:
    0: is not modifiable 1: is modifiable in default == being related to type.isMutable() 2: is modifiable, because this is a part of initializing.
  Expression `toBoolean`(Scope* `sc`);
    If expression can be tested for `true` or `false`, returns the modified expression. Otherwise returns ErrorExp.
  Expression `addDtorHook`(Scope* `sc`);
    Destructors are attached to VarDeclarations. Hence, if expression returns a temp that needs a destructor, make sure and create a VarDeclaration for that temp.
  final Expression `addressOf`();
    Take address of expression.
  final Expression `deref`();
    If this is a reference, dereference it.
  bool `isBool`(bool `result`);
    Does this expression statically evaluate to a boolean '`result`' (`true` or `false`)?
class `IntegerExp`: dmd.expression.Expression;
class `ErrorExp`: dmd.expression.Expression;
  Use this expression for error recovery. It should behave as a 'sink' to prevent further cascaded error messages.
class `RealExp`: dmd.expression.Expression;
class `ComplexExp`: dmd.expression.Expression;
class `IdentifierExp`: dmd.expression.Expression;
class `DollarExp`: dmd.expression.IdentifierExp;
class `DsymbolExp`: dmd.expression.Expression;
  Won't be generated by parser.
class `ThisExp`: dmd.expression.Expression;
  http://dlang.org/spec/expression.html#this
class `SuperExp`: dmd.expression.ThisExp;
  http://dlang.org/spec/expression.html#super
class `NullExp`: dmd.expression.Expression;
  http://dlang.org/spec/expression.html#null
class `StringExp`: dmd.expression.Expression;
  http://dlang.org/spec/expression.html#string_literals
  final 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

  final 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`
  final 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

  char* `toPtr`();
    If the string data is UTF-8 and can be accessed directly, return a pointer to it. Do not assume a terminating 0.
    Returns:
    pointer to string data if possible, `null` if not
  StringExp `toUTF8`(Scope* `sc`);
    Convert string to char[].
  final const const(char)[] `toStringz`();
    Convert string contents to a 0 terminated string, allocated by mem.xmalloc().
class `TupleExp`: dmd.expression.Expression;
class `ArrayLiteralExp`: dmd.expression.Expression;
  [ e1, e2, e3, ... ]
  http://dlang.org/spec/expression.html#array_literals
  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.
  static Expressions* `copyElements`(Expression `e1`, Expression `e2` = null);
    Copy element Expressions in the parameters when they're ArrayLiteralExps.
    Parameters:

    Expression `e1` | If it's ArrayLiteralExp, its elements will be copied. Otherwise, `e1` itself will be pushed into the new Expressions.
    Expression `e2` | If it's not null, it will be pushed/appended to the new Expressions by the same way with `e1`.

    Returns:
    Newly allocated Expressions. Note that it points to the original Expression values in `e1` and `e2`.
class `AssocArrayLiteralExp`: dmd.expression.Expression;
  [ key0 : value0, key1 : value1, ... ]
  http://dlang.org/spec/expression.html#associative_array_literals
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)
  bool `useStaticInit`;
    if this is `true`, use the StructDeclaration's init symbol
  Symbol* `sym`;
    back end symbol to initialize with literal
  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.
  StructLiteralExp `inlinecopy`;
    those fields need to prevent a infinite recursion when one field of struct initialized with 'this' pointer.
  int `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.
  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 `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;
  thisexp.new(newargs) newtype(arguments)
class `NewAnonClassExp`: dmd.expression.Expression;
  thisexp.new(newargs) 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;
class `IsExp`: dmd.expression.Expression;
  is(targ id tok tspec) is(targ id == tok2)
class `UnaExp`: dmd.expression.Expression;
  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;
  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;
class `CompileExp`: dmd.expression.UnaExp;
class `ImportExp`: dmd.expression.UnaExp;
class `AssertExp`: dmd.expression.UnaExp;
  https://dlang.org/spec/expression.html#assert_expressions
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;
class `CallExp`: dmd.expression.UnaExp;
class `AddrExp`: dmd.expression.UnaExp;
class `PtrExp`: dmd.expression.UnaExp;
class `NegExp`: dmd.expression.UnaExp;
class `UAddExp`: dmd.expression.UnaExp;
class `ComExp`: dmd.expression.UnaExp;
class `NotExp`: dmd.expression.UnaExp;
class `DeleteExp`: dmd.expression.UnaExp;
class `CastExp`: dmd.expression.UnaExp;
  Possible to cast to one type while painting to another type
class `VectorExp`: dmd.expression.UnaExp;
class `SliceExp`: dmd.expression.UnaExp;
  e1 [lwr .. upr]
  http://dlang.org/spec/expression.html#slice_expressions
  this(ref const Loc `loc`, Expression `e1`, IntervalExp `ie`);
class `ArrayLengthExp`: dmd.expression.UnaExp;
  static Expression `rewriteOpAssign`(BinExp `exp`);

    Rewrite array.length op= e2 as: array.length = array.length op e2 or: auto tmp = &array; (*tmp).length = (*tmp).length op e2

class `ArrayExp`: dmd.expression.UnaExp;
  e1 [ a0, a1, a2, a3 ,... ]
  http://dlang.org/spec/expression.html#index_expressions
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 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 `DelegateFuncptrExp`: dmd.expression.UnaExp;
class `IndexExp`: dmd.expression.BinExp;
  e1 [ e2 ]
class `PostExp`: dmd.expression.BinExp;
  For both i++ and i--
class `PreExp`: dmd.expression.UnaExp;
  For both ++i and --i
class `AssignExp`: dmd.expression.BinExp;
  this(ref const Loc `loc`, Expression `e1`, Expression `e2`);
class `ConstructExp`: dmd.expression.AssignExp;
class `BlitExp`: dmd.expression.AssignExp;
class `AddAssignExp`: dmd.expression.BinAssignExp;
class `MinAssignExp`: dmd.expression.BinAssignExp;
class `MulAssignExp`: dmd.expression.BinAssignExp;
class `DivAssignExp`: dmd.expression.BinAssignExp;
class `ModAssignExp`: dmd.expression.BinAssignExp;
class `AndAssignExp`: dmd.expression.BinAssignExp;
class `OrAssignExp`: dmd.expression.BinAssignExp;
class `XorAssignExp`: dmd.expression.BinAssignExp;
class `PowAssignExp`: dmd.expression.BinAssignExp;
class `ShlAssignExp`: dmd.expression.BinAssignExp;
class `ShrAssignExp`: dmd.expression.BinAssignExp;
class `UshrAssignExp`: dmd.expression.BinAssignExp;
class `CatAssignExp`: dmd.expression.BinAssignExp;
  The ~= operator. It can have one of the following operators:
  TOK.concatenateAssign - appending T[] to T[] TOK.concatenateElemAssign - appending T to T[] TOK.concatenateDcharAssign - appending dchar to T[]
  The parser initially sets it to TOK.concatenateAssign, and semantic() later decides which of the three it will be set to.
class `AddExp`: dmd.expression.BinExp;
  http://dlang.org/spec/expression.html#add_expressions
class `MinExp`: dmd.expression.BinExp;
class `CatExp`: dmd.expression.BinExp;
  http://dlang.org/spec/expression.html#cat_expressions
class `MulExp`: dmd.expression.BinExp;
  http://dlang.org/spec/expression.html#mul_expressions
class `DivExp`: dmd.expression.BinExp;
  http://dlang.org/spec/expression.html#mul_expressions
class `ModExp`: dmd.expression.BinExp;
  http://dlang.org/spec/expression.html#mul_expressions
class `PowExp`: dmd.expression.BinExp;
  http://dlang.org/spec/expression.html#pow_expressions
class `ShlExp`: dmd.expression.BinExp;
class `ShrExp`: dmd.expression.BinExp;
class `UshrExp`: dmd.expression.BinExp;
class `AndExp`: dmd.expression.BinExp;
class `OrExp`: dmd.expression.BinExp;
class `XorExp`: dmd.expression.BinExp;
class `LogicalExp`: dmd.expression.BinExp;
  http://dlang.org/spec/expression.html#andand_expressions http://dlang.org/spec/expression.html#oror_expressions
class `CmpExp`: dmd.expression.BinExp;
  op is one of: TOK.lessThan, TOK.lessOrEqual, TOK.greaterThan, TOK.greaterOrEqual, TOK.unord, TOK.lg, TOK.leg, TOK.ule, TOK.ul, TOK.uge, TOK.ug, TOK.ue
  http://dlang.org/spec/expression.html#relation_expressions
class `InExp`: dmd.expression.BinExp;
class `RemoveExp`: dmd.expression.BinExp;
  This deletes the key e1 from the associative array e2
class `EqualExp`: dmd.expression.BinExp;
  == and !=
  TOK.equal and TOK.notEqual
  http://dlang.org/spec/expression.html#equality_expressions
class `IdentityExp`: dmd.expression.BinExp;
  is and !is
  TOK.identity and TOK.notIdentity
  http://dlang.org/spec/expression.html#identity_expressions
class `CondExp`: dmd.expression.BinExp;
  econd ? e1 : e2
  http://dlang.org/spec/expression.html#conditional_expressions
class `DefaultInitExp`: dmd.expression.Expression;
class `FileInitExp`: dmd.expression.DefaultInitExp;
class `LineInitExp`: dmd.expression.DefaultInitExp;
class `ModuleInitExp`: dmd.expression.DefaultInitExp;
class `FuncInitExp`: dmd.expression.DefaultInitExp;
class `PrettyFuncInitExp`: dmd.expression.DefaultInitExp;

Copyright © 1999-2018 by the D Language Foundation | Page generated by Ddoc on Sat Apr 14 16:39:18 2018