diff trunk/src/dil/ast/Expressions.d @ 586:e25345656d10

Moved dil.Expressions to dil.ast.Expressions.
author Aziz K?ksal <aziz.koeksal@gmail.com>
date Sat, 05 Jan 2008 23:06:03 +0100
parents trunk/src/dil/Expressions.d@05c375fb2d5c
children 7d0ba0c93e95
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/dil/ast/Expressions.d	Sat Jan 05 23:06:03 2008 +0100
@@ -0,0 +1,1243 @@
+/++
+  Author: Aziz Köksal
+  License: GPL3
++/
+module dil.ast.Expressions;
+
+import dil.ast.Node;
+import dil.Token;
+import dil.Types;
+import dil.ast.Declarations;
+import dil.Statements;
+import dil.Identifier;
+import dil.Scope;
+import dil.semantic.Types;
+import common;
+
+abstract class Expression : Node
+{
+  Type type; /// The type of this expression.
+  this()
+  {
+    super(NodeCategory.Expression);
+  }
+
+  // Semantic analysis:
+
+  Expression semantic(Scope scop)
+  {
+    debug Stdout("SA for "~this.classinfo.name).newline;
+    if (!type)
+      type = Types.Undefined;
+    return this;
+  }
+
+  Expression evaluate()
+  {
+    return null;
+  }
+
+  import dil.Messages;
+  void error(Scope scop, MID mid)
+  {
+    scop.error(this.begin, mid);
+  }
+
+  void error(Scope scop, char[] msg)
+  {
+
+  }
+}
+
+class EmptyExpression : Expression
+{
+  this()
+  {
+    mixin(set_kind);
+  }
+}
+
+abstract class BinaryExpression : Expression
+{
+  Expression left, right;
+  Token* tok;
+  this(Expression left, Expression right, Token* tok)
+  {
+    addChildren([left, right]);
+    this.left = left;
+    this.right = right;
+    this.tok = tok;
+  }
+
+  override Expression semantic(Scope scop)
+  {
+    left = left.semantic(scop);
+    right = right.semantic(scop);
+    return this;
+  }
+}
+
+class CondExpression : BinaryExpression
+{
+  Expression condition;
+  this(Expression condition, Expression left, Expression right, Token* tok)
+  {
+    addChild(condition);
+    super(left, right, tok);
+    mixin(set_kind);
+    this.condition = condition;
+  }
+}
+
+class CommaExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class OrOrExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class AndAndExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class OrExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class XorExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class AndExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+abstract class CmpExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+  }
+}
+
+class EqualExpression : CmpExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class IdentityExpression : CmpExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class RelExpression : CmpExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class InExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class LShiftExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class RShiftExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class URShiftExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class PlusExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class MinusExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class CatExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class MulExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class DivExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class ModExpression : BinaryExpression
+{
+  this(Expression left, Expression right, Token* tok)
+  {
+    super(left, right, tok);
+    mixin(set_kind);
+  }
+}
+
+class AssignExpression : BinaryExpression
+{
+  this(Expression left, Expression right)
+  {
+    super(left, right, null);
+    mixin(set_kind);
+  }
+}
+class LShiftAssignExpression : BinaryExpression
+{
+  this(Expression left, Expression right)
+  {
+    super(left, right, null);
+    mixin(set_kind);
+  }
+}
+class RShiftAssignExpression : BinaryExpression
+{
+  this(Expression left, Expression right)
+  {
+    super(left, right, null);
+    mixin(set_kind);
+  }
+}
+class URShiftAssignExpression : BinaryExpression
+{
+  this(Expression left, Expression right)
+  {
+    super(left, right, null);
+    mixin(set_kind);
+  }
+}
+class OrAssignExpression : BinaryExpression
+{
+  this(Expression left, Expression right)
+  {
+    super(left, right, null);
+    mixin(set_kind);
+  }
+}
+class AndAssignExpression : BinaryExpression
+{
+  this(Expression left, Expression right)
+  {
+    super(left, right, null);
+    mixin(set_kind);
+  }
+}
+class PlusAssignExpression : BinaryExpression
+{
+  this(Expression left, Expression right)
+  {
+    super(left, right, null);
+    mixin(set_kind);
+  }
+}
+class MinusAssignExpression : BinaryExpression
+{
+  this(Expression left, Expression right)
+  {
+    super(left, right, null);
+    mixin(set_kind);
+  }
+}
+class DivAssignExpression : BinaryExpression
+{
+  this(Expression left, Expression right)
+  {
+    super(left, right, null);
+    mixin(set_kind);
+  }
+}
+class MulAssignExpression : BinaryExpression
+{
+  this(Expression left, Expression right)
+  {
+    super(left, right, null);
+    mixin(set_kind);
+  }
+}
+class ModAssignExpression : BinaryExpression
+{
+  this(Expression left, Expression right)
+  {
+    super(left, right, null);
+    mixin(set_kind);
+  }
+}
+class XorAssignExpression : BinaryExpression
+{
+  this(Expression left, Expression right)
+  {
+    super(left, right, null);
+    mixin(set_kind);
+  }
+}
+class CatAssignExpression : BinaryExpression
+{
+  this(Expression left, Expression right)
+  {
+    super(left, right, null);
+    mixin(set_kind);
+  }
+}
+
+abstract class UnaryExpression : Expression
+{
+  Expression e;
+  this(Expression e)
+  {
+    addChild(e);
+    this.e = e;
+  }
+}
+
+class AddressExpression : UnaryExpression
+{
+  this(Expression e)
+  {
+    super(e);
+    mixin(set_kind);
+  }
+}
+
+class PreIncrExpression : UnaryExpression
+{
+  this(Expression e)
+  {
+    super(e);
+    mixin(set_kind);
+  }
+}
+
+class PreDecrExpression : UnaryExpression
+{
+  this(Expression e)
+  {
+    super(e);
+    mixin(set_kind);
+  }
+}
+
+class PostIncrExpression : UnaryExpression
+{
+  this(Expression e)
+  {
+    super(e);
+    mixin(set_kind);
+  }
+}
+
+class PostDecrExpression : UnaryExpression
+{
+  this(Expression e)
+  {
+    super(e);
+    mixin(set_kind);
+  }
+}
+
+class DerefExpression : UnaryExpression
+{
+  this(Expression e)
+  {
+    super(e);
+    mixin(set_kind);
+  }
+}
+
+class SignExpression : UnaryExpression
+{
+  this(Expression e)
+  {
+    super(e);
+    mixin(set_kind);
+  }
+}
+
+class NotExpression : UnaryExpression
+{
+  this(Expression e)
+  {
+    super(e);
+    mixin(set_kind);
+  }
+}
+
+class CompExpression : UnaryExpression
+{
+  this(Expression e)
+  {
+    super(e);
+    mixin(set_kind);
+  }
+}
+/+
+class DotIdExpression : UnaryExpression
+{
+  string ident;
+  this(Expression e, string ident)
+  {
+    super(e);
+    this.ident = ident;
+  }
+}
++/
+/+
+class DotTemplateInstanceExpression : UnaryExpression
+{
+  string ident;
+  TemplateArguments targs;
+  this(Expression e, string ident, TemplateArguments targs)
+  {
+    super(e);
+    this.ident = ident;
+    this.targs = targs;
+  }
+}
++/
+class PostDotListExpression : UnaryExpression
+{
+  DotListExpression dotList;
+  this(Expression e, DotListExpression dotList)
+  {
+    super(e);
+    mixin(set_kind);
+    addChild(dotList);
+    this.dotList = dotList;
+  }
+}
+
+class CallExpression : UnaryExpression
+{
+  Expression[] args;
+  this(Expression e, Expression[] args)
+  {
+    super(e);
+    mixin(set_kind);
+    addOptChildren(args);
+    this.args = args;
+  }
+}
+
+class NewExpression : /*Unary*/Expression
+{
+  Expression[] newArgs;
+  TypeNode type;
+  Expression[] ctorArgs;
+  this(/*Expression e, */Expression[] newArgs, TypeNode type, Expression[] ctorArgs)
+  {
+    /*super(e);*/
+    mixin(set_kind);
+    addOptChildren(newArgs);
+    addChild(type);
+    addOptChildren(ctorArgs);
+    this.newArgs = newArgs;
+    this.type = type;
+    this.ctorArgs = ctorArgs;
+  }
+}
+
+class NewAnonClassExpression : /*Unary*/Expression
+{
+  Expression[] newArgs;
+  BaseClass[] bases;
+  Expression[] ctorArgs;
+  Declarations decls;
+  this(/*Expression e, */Expression[] newArgs, BaseClass[] bases, Expression[] ctorArgs, Declarations decls)
+  {
+    /*super(e);*/
+    mixin(set_kind);
+    addOptChildren(newArgs);
+    addOptChildren(bases);
+    addOptChildren(ctorArgs);
+    addChild(decls);
+
+    this.newArgs = newArgs;
+    this.bases = bases;
+    this.ctorArgs = ctorArgs;
+    this.decls = decls;
+  }
+}
+
+class DeleteExpression : UnaryExpression
+{
+  this(Expression e)
+  {
+    super(e);
+    mixin(set_kind);
+  }
+}
+
+class CastExpression : UnaryExpression
+{
+  TypeNode type;
+  this(Expression e, TypeNode type)
+  {
+    addChild(type); // Add type before super().
+    super(e);
+    mixin(set_kind);
+    this.type = type;
+  }
+}
+
+class IndexExpression : UnaryExpression
+{
+  Expression[] args;
+  this(Expression e, Expression[] args)
+  {
+    super(e);
+    mixin(set_kind);
+    addChildren(args);
+    this.args = args;
+  }
+}
+
+class SliceExpression : UnaryExpression
+{
+  Expression left, right;
+  this(Expression e, Expression left, Expression right)
+  {
+    super(e);
+    mixin(set_kind);
+    assert(left ? (right !is null) : right is null);
+    if (left)
+      addChildren([left, right]);
+
+    this.left = left;
+    this.right = right;
+  }
+}
+
+/*
+class PrimaryExpression
+{
+
+}
+*/
+
+class IdentifierExpression : Expression
+{
+  Identifier* identifier;
+  this(Identifier* identifier)
+  {
+    mixin(set_kind);
+    this.identifier = identifier;
+  }
+}
+
+class SpecialTokenExpression : Expression
+{
+  Token* specialToken;
+  this(Token* specialToken)
+  {
+    mixin(set_kind);
+    this.specialToken = specialToken;
+  }
+
+  Expression e; /// The expression created in the semantic phase.
+
+  override Expression semantic(Scope)
+  {
+    if (type)
+      return e;
+    switch (specialToken.type)
+    {
+    case TOK.LINE, TOK.VERSION:
+      e = new IntExpression(specialToken.uint_, Types.Uint);
+      break;
+    case TOK.FILE, TOK.DATE, TOK.TIME, TOK.TIMESTAMP, TOK.VENDOR:
+      e = new StringExpression(specialToken.str);
+      break;
+    default:
+      assert(0);
+    }
+    type = e.type;
+    return e;
+  }
+}
+
+/*
+class IdentifierListExpression : Expression
+{
+  Expression[] identList;
+  this(Expression[] identList)
+  {
+    this.identList = identList;
+  }
+}
+*/
+
+class DotExpression : Expression
+{
+  this()
+  {
+    mixin(set_kind);
+  }
+}
+
+class DotListExpression : Expression
+{
+  Expression[] items;
+  this(Expression[] items)
+  {
+    mixin(set_kind);
+    addChildren(items);
+    this.items = items;
+  }
+}
+
+class TemplateInstanceExpression : Expression
+{
+  Identifier* ident;
+  TemplateArguments targs;
+  this(Identifier* ident, TemplateArguments targs)
+  {
+    mixin(set_kind);
+    addOptChild(targs);
+    this.ident = ident;
+    this.targs = targs;
+  }
+}
+
+class ThisExpression : Expression
+{
+  this()
+  {
+    mixin(set_kind);
+  }
+}
+
+class SuperExpression : Expression
+{
+  this()
+  {
+    mixin(set_kind);
+  }
+}
+
+class NullExpression : Expression
+{
+  this()
+  {
+    mixin(set_kind);
+  }
+
+  this(Type type)
+  {
+    this();
+    this.type = type;
+  }
+
+  override Expression semantic(Scope)
+  {
+    if (!type)
+      type = Types.Void_ptr;
+    return this;
+  }
+}
+
+class DollarExpression : Expression
+{
+  this()
+  {
+    mixin(set_kind);
+  }
+
+  override Expression semantic(Scope scop)
+  {
+    if (type)
+      return this;
+    type = Types.Size_t;
+    // if (!scop.inArraySubscript)
+    //   error(scop, "$ can only be in an array subscript.");
+    return this;
+  }
+}
+
+class BoolExpression : Expression
+{
+  this()
+  {
+    mixin(set_kind);
+  }
+
+  Expression e;
+  override Expression semantic(Scope scop)
+  {
+    if (type)
+      return this;
+    assert(this.begin !is null);
+    auto b = (this.begin.type == TOK.True) ? true : false;
+    e = new IntExpression(b, Types.Bool);
+    type = Types.Bool;
+    return this;
+  }
+}
+
+class IntExpression : Expression
+{
+  ulong number;
+
+  this(ulong number, Type type)
+  {
+    mixin(set_kind);
+    this.number = number;
+    this.type = type;
+  }
+
+  this(Token* token)
+  {
+    auto type = Types.Int; // Should be most common case.
+    switch (token.type)
+    {
+    // case TOK.Int32:
+    //   type = Types.Int; break;
+    case TOK.Uint32:
+      type = Types.Uint; break;
+    case TOK.Int64:
+      type = Types.Long; break;
+    case TOK.Uint64:
+      type = Types.Ulong; break;
+    default:
+      assert(token.type == TOK.Int32);
+    }
+    this(token.ulong_, type);
+  }
+
+  override Expression semantic(Scope)
+  {
+    if (type)
+      return this;
+
+    if (number & 0x8000_0000_0000_0000)
+      type = Types.Ulong; // 0xFFFF_FFFF_FFFF_FFFF
+    else if (number & 0xFFFF_FFFF_0000_0000)
+      type = Types.Long; // 0x7FFF_FFFF_FFFF_FFFF
+    else if (number & 0x8000_0000)
+      type = Types.Uint; // 0xFFFF_FFFF
+    else
+      type = Types.Int; // 0x7FFF_FFFF
+    return this;
+  }
+}
+
+class RealExpression : Expression
+{
+  real number;
+
+  this(real number, Type type)
+  {
+    mixin(set_kind);
+    this.number = number;
+    this.type = type;
+  }
+
+  this(Token* token)
+  {
+    auto type = Types.Double; // Most common case?
+    switch (token.type)
+    {
+    case TOK.Float32:
+      type = Types.Float; break;
+    // case TOK.Float64:
+    //   type = Types.Double; break;
+    case TOK.Float80:
+      type = Types.Real; break;
+    case TOK.Imaginary32:
+      type = Types.Ifloat; break;
+    case TOK.Imaginary64:
+      type = Types.Idouble; break;
+    case TOK.Imaginary80:
+      type = Types.Ireal; break;
+    default:
+      assert(token.type == TOK.Float64);
+    }
+    this(token.real_, type);
+  }
+
+  override Expression semantic(Scope)
+  {
+    if (type)
+      return this;
+    type = Types.Double;
+    return this;
+  }
+}
+
+/++
+  This expression holds a complex number.
+  It is only created in the semantic phase.
++/
+class ComplexExpression : Expression
+{
+  creal number;
+
+  this(creal number, Type type)
+  {
+    mixin(set_kind);
+    this.number = number;
+    this.type = type;
+  }
+
+  override Expression semantic(Scope)
+  {
+    if (type)
+      return this;
+    type = Types.Cdouble;
+    return this;
+  }
+}
+
+class CharExpression : Expression
+{
+  dchar character;
+  this(dchar character)
+  {
+    mixin(set_kind);
+    this.character = character;
+  }
+
+  override Expression semantic(Scope scop)
+  {
+    if (type)
+      return this;
+    if (character <= 0xFF)
+      type = Types.Char;
+    else if (character <= 0xFFFF)
+      type = Types.Wchar;
+    else
+      type = Types.Dchar;
+    return this;
+  }
+}
+
+class StringExpression : Expression
+{
+  Token*[] stringTokens;
+  this()
+  { mixin(set_kind); }
+
+  /// Constructor used in parsing phase.
+  this(Token*[] stringTokens)
+  {
+    this();
+    this.stringTokens = stringTokens;
+  }
+
+  ubyte[] str;   /// The string data.
+  Type charType; /// The character type of the string.
+  // Constructors used in semantic phase.
+  this(ubyte[] str, Type charType)
+  {
+    this();
+    this.str = str;
+    this.charType = charType;
+    type = new TypeSArray(charType, str.length);
+  }
+
+  this(char[] str)
+  {
+    this(cast(ubyte[])str, Types.Char);
+  }
+  this(wchar[] str)
+  {
+    this(cast(ubyte[])str, Types.Wchar);
+  }
+  this(dchar[] str)
+  {
+    this(cast(ubyte[])str, Types.Dchar);
+  }
+
+  override Expression semantic(Scope scop)
+  {
+    if (type)
+      return this;
+    return this;
+  }
+
+  char[] getString()
+  {
+    char[] buffer;
+    foreach (token; stringTokens)
+      buffer ~= token.str[0..$-1];
+    return buffer;
+  }
+}
+
+class ArrayLiteralExpression : Expression
+{
+  Expression[] values;
+  this(Expression[] values)
+  {
+    mixin(set_kind);
+    addOptChildren(values);
+    this.values = values;
+  }
+}
+
+class AArrayLiteralExpression : Expression
+{
+  Expression[] keys, values;
+  this(Expression[] keys, Expression[] values)
+  {
+    assert(keys.length == values.length);
+    mixin(set_kind);
+    foreach (i, key; keys)
+      addChildren([key, values[i]]);
+    this.keys = keys;
+    this.values = values;
+  }
+}
+
+class AssertExpression : Expression
+{
+  Expression expr, msg;
+  this(Expression expr, Expression msg)
+  {
+    mixin(set_kind);
+    addChild(expr);
+    addOptChild(msg);
+    this.expr = expr;
+    this.msg = msg;
+  }
+}
+
+class MixinExpression : Expression
+{
+  Expression expr;
+  this(Expression expr)
+  {
+    mixin(set_kind);
+    addChild(expr);
+    this.expr = expr;
+  }
+
+  // import dil.Parser;
+  override Expression semantic(Scope scop)
+  {
+    // TODO:
+    /+
+    auto expr = this.expr.semantic(scop);
+    auto strExpr = Cast!(StringExpression)(expr);
+    // if (strExpr is null)
+    //  error(scop, MID.MixinExpressionMustBeString);
+    auto parser = new Parser(strExpr.getString(), "", scop.infoMan);
+    expr = parser.start2();
+    return expr;
+    +/
+    return null;
+  }
+}
+
+class ImportExpression : Expression
+{
+  Expression expr;
+  this(Expression expr)
+  {
+    mixin(set_kind);
+    addChild(expr);
+    this.expr = expr;
+  }
+}
+
+class TypeofExpression : Expression
+{
+  TypeNode type;
+  this(TypeNode type)
+  {
+    mixin(set_kind);
+    addChild(type);
+    this.type = type;
+  }
+}
+
+class TypeDotIdExpression : Expression
+{
+  TypeNode type;
+  Identifier* ident;
+  this(TypeNode type, Identifier* ident)
+  {
+    mixin(set_kind);
+    addChild(type);
+    this.type = type;
+    this.ident = ident;
+  }
+}
+
+class TypeidExpression : Expression
+{
+  TypeNode type;
+  this(TypeNode type)
+  {
+    mixin(set_kind);
+    addChild(type);
+    this.type = type;
+  }
+}
+
+class IsExpression : Expression
+{
+  TypeNode type;
+  Identifier* ident;
+  Token* opTok, specTok;
+  TypeNode specType;
+  TemplateParameters tparams; // D 2.0
+  this(TypeNode type, Identifier* ident, Token* opTok, Token* specTok,
+       TypeNode specType, typeof(tparams) tparams)
+  {
+    mixin(set_kind);
+    addChild(type);
+    addOptChild(specType);
+  version(D2)
+    addOptChild(tparams);
+    this.type = type;
+    this.ident = ident;
+    this.opTok = opTok;
+    this.specTok = specTok;
+    this.specType = specType;
+    this.tparams = tparams;
+  }
+}
+
+class FunctionLiteralExpression : Expression
+{
+  TypeNode returnType;
+  Parameters parameters;
+  FunctionBody funcBody;
+
+  this()
+  {
+    mixin(set_kind);
+    addOptChild(returnType);
+    addOptChild(parameters);
+    addChild(funcBody);
+  }
+
+  this(TypeNode returnType, Parameters parameters, FunctionBody funcBody)
+  {
+    this.returnType = returnType;
+    this.parameters = parameters;
+    this.funcBody = funcBody;
+    this();
+  }
+
+  this(FunctionBody funcBody)
+  {
+    this.funcBody = funcBody;
+    this();
+  }
+}
+
+version(D2)
+{
+class TraitsExpression : Expression
+{
+  Identifier* ident;
+  TemplateArguments targs;
+  this(typeof(ident) ident, typeof(targs) targs)
+  {
+    mixin(set_kind);
+    addOptChild(targs);
+    this.ident = ident;
+    this.targs = targs;
+  }
+}
+}
+
+class VoidInitializer : Expression
+{
+  this()
+  {
+    mixin(set_kind);
+  }
+}
+
+class ArrayInitializer : Expression
+{
+  Expression[] keys;
+  Expression[] values;
+  this(Expression[] keys, Expression[] values)
+  {
+    assert(keys.length == values.length);
+    mixin(set_kind);
+    foreach (i, key; keys)
+    {
+      addOptChild(key); // The key is optional in ArrayInitializers.
+      addChild(values[i]);
+    }
+    this.keys = keys;
+    this.values = values;
+  }
+}
+
+class StructInitializer : Expression
+{
+  Identifier*[] idents;
+  Expression[] values;
+  this(Identifier*[] idents, Expression[] values)
+  {
+    mixin(set_kind);
+    addOptChildren(values);
+    this.idents = idents;
+    this.values = values;
+  }
+}
+
+class AsmTypeExpression : UnaryExpression
+{
+  this(Expression e)
+  {
+    super(e);
+    mixin(set_kind);
+  }
+}
+
+class AsmOffsetExpression : UnaryExpression
+{
+  this(Expression e)
+  {
+    super(e);
+    mixin(set_kind);
+  }
+}
+
+class AsmSegExpression : UnaryExpression
+{
+  this(Expression e)
+  {
+    super(e);
+    mixin(set_kind);
+  }
+}
+
+class AsmPostBracketExpression : UnaryExpression
+{
+  this(Expression e)
+  {
+    super(e);
+    mixin(set_kind);
+  }
+}
+
+class AsmBracketExpression : Expression
+{
+  Expression e;
+  this(Expression e)
+  {
+    mixin(set_kind);
+    addChild(e);
+    this.e = e;
+  }
+}
+
+class AsmLocalSizeExpression : Expression
+{
+  this()
+  {
+    mixin(set_kind);
+  }
+}
+
+class AsmRegisterExpression : Expression
+{
+  Identifier* register;
+  int number; // ST(0) - ST(7) or FS:0, FS:4, FS:8
+  this(Identifier* register, int number = -1)
+  {
+    mixin(set_kind);
+    this.register = register;
+    this.number = number;
+  }
+}