// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

part of js;

abstract class NodeVisitor<T> {
  T visitProgram(Program node);

  T visitBlock(Block node);
  T visitExpressionStatement(ExpressionStatement node);
  T visitEmptyStatement(EmptyStatement node);
  T visitIf(If node);
  T visitFor(For node);
  T visitForIn(ForIn node);
  T visitWhile(While node);
  T visitDo(Do node);
  T visitContinue(Continue node);
  T visitBreak(Break node);
  T visitReturn(Return node);
  T visitThrow(Throw node);
  T visitTry(Try node);
  T visitCatch(Catch node);
  T visitSwitch(Switch node);
  T visitCase(Case node);
  T visitDefault(Default node);
  T visitFunctionDeclaration(FunctionDeclaration node);
  T visitLabeledStatement(LabeledStatement node);
  T visitLiteralStatement(LiteralStatement node);

  T visitLiteralExpression(LiteralExpression node);
  T visitVariableDeclarationList(VariableDeclarationList node);
  T visitSequence(Sequence node);
  T visitAssignment(Assignment node);
  T visitVariableInitialization(VariableInitialization node);
  T visitConditional(Conditional cond);
  T visitNew(New node);
  T visitCall(Call node);
  T visitBinary(Binary node);
  T visitPrefix(Prefix node);
  T visitPostfix(Postfix node);

  T visitVariableUse(VariableUse node);
  T visitThis(This node);
  T visitVariableDeclaration(VariableDeclaration node);
  T visitParameter(Parameter node);
  T visitAccess(PropertyAccess node);

  T visitNamedFunction(NamedFunction node);
  T visitFun(Fun node);

  T visitLiteralBool(LiteralBool node);
  T visitLiteralString(LiteralString node);
  T visitLiteralNumber(LiteralNumber node);
  T visitLiteralNull(LiteralNull node);

  T visitArrayInitializer(ArrayInitializer node);
  T visitArrayElement(ArrayElement node);
  T visitObjectInitializer(ObjectInitializer node);
  T visitProperty(Property node);
  T visitRegExpLiteral(RegExpLiteral node);

  T visitComment(Comment node);

  T visitInterpolatedExpression(InterpolatedExpression node);
  T visitJSExpression(JSExpression node);
}

class BaseVisitor<T> implements NodeVisitor<T> {
  T visitNode(Node node) {
    node.visitChildren(this);
    return null;
  }

  T visitProgram(Program node) => visitNode(node);

  T visitStatement(Statement node) => visitNode(node);
  T visitLoop(Loop node) => visitStatement(node);
  T visitJump(Statement node) => visitStatement(node);

  T visitBlock(Block node) => visitStatement(node);
  T visitExpressionStatement(ExpressionStatement node)
      => visitStatement(node);
  T visitEmptyStatement(EmptyStatement node) => visitStatement(node);
  T visitIf(If node) => visitStatement(node);
  T visitFor(For node) => visitLoop(node);
  T visitForIn(ForIn node) => visitLoop(node);
  T visitWhile(While node) => visitLoop(node);
  T visitDo(Do node) => visitLoop(node);
  T visitContinue(Continue node) => visitJump(node);
  T visitBreak(Break node) => visitJump(node);
  T visitReturn(Return node) => visitJump(node);
  T visitThrow(Throw node) => visitJump(node);
  T visitTry(Try node) => visitStatement(node);
  T visitSwitch(Switch node) => visitStatement(node);
  T visitFunctionDeclaration(FunctionDeclaration node)
      => visitStatement(node);
  T visitLabeledStatement(LabeledStatement node) => visitStatement(node);
  T visitLiteralStatement(LiteralStatement node) => visitStatement(node);

  T visitCatch(Catch node) => visitNode(node);
  T visitCase(Case node) => visitNode(node);
  T visitDefault(Default node) => visitNode(node);

  T visitExpression(Expression node) => visitNode(node);
  T visitVariableReference(VariableReference node) => visitExpression(node);

  T visitLiteralExpression(LiteralExpression node) => visitExpression(node);
  T visitVariableDeclarationList(VariableDeclarationList node)
      => visitExpression(node);
  T visitSequence(Sequence node) => visitExpression(node);
  T visitAssignment(Assignment node) => visitExpression(node);
  T visitVariableInitialization(VariableInitialization node) {
    if (node.value != null) {
      visitAssignment(node);
    } else {
      visitExpression(node);
    }
  }
  T visitConditional(Conditional node) => visitExpression(node);
  T visitNew(New node) => visitExpression(node);
  T visitCall(Call node) => visitExpression(node);
  T visitBinary(Binary node) => visitCall(node);
  T visitPrefix(Prefix node) => visitCall(node);
  T visitPostfix(Postfix node) => visitCall(node);
  T visitAccess(PropertyAccess node) => visitExpression(node);

  T visitVariableUse(VariableUse node) => visitVariableReference(node);
  T visitVariableDeclaration(VariableDeclaration node)
      => visitVariableReference(node);
  T visitParameter(Parameter node) => visitVariableDeclaration(node);
  T visitThis(This node) => visitParameter(node);

  T visitNamedFunction(NamedFunction node) => visitExpression(node);
  T visitFun(Fun node) => visitExpression(node);

  T visitLiteral(Literal node) => visitExpression(node);

  T visitLiteralBool(LiteralBool node) => visitLiteral(node);
  T visitLiteralString(LiteralString node) => visitLiteral(node);
  T visitLiteralNumber(LiteralNumber node) => visitLiteral(node);
  T visitLiteralNull(LiteralNull node) => visitLiteral(node);

  T visitArrayInitializer(ArrayInitializer node) => visitExpression(node);
  T visitArrayElement(ArrayElement node) => visitNode(node);
  T visitObjectInitializer(ObjectInitializer node) => visitExpression(node);
  T visitProperty(Property node) => visitNode(node);
  T visitRegExpLiteral(RegExpLiteral node) => visitExpression(node);

  T visitInterpolatedExpression(InterpolatedExpression node)
      => visitExpression(node);
  T visitJSExpression(JSExpression node) => visitExpression(node);

  // Ignore comments by default.
  T visitComment(Comment node) {}
}

abstract class Node {
  var sourcePosition;
  var endSourcePosition;

  accept(NodeVisitor visitor);
  void visitChildren(NodeVisitor visitor);

  VariableUse asVariableUse() => null;

  Statement toStatement() {
    throw new UnsupportedError('toStatement');
  }
}

class Program extends Node {
  final List<Statement> body;
  Program(this.body);

  accept(NodeVisitor visitor) => visitor.visitProgram(this);
  void visitChildren(NodeVisitor visitor) {
    for (Statement statement in body) statement.accept(visitor);
  }
}

abstract class Statement extends Node {
  Statement toStatement() => this;
}

class Block extends Statement {
  final List<Statement> statements;
  Block(this.statements);
  Block.empty() : this.statements = <Statement>[];

  accept(NodeVisitor visitor) => visitor.visitBlock(this);
  void visitChildren(NodeVisitor visitor) {
    for (Statement statement in statements) statement.accept(visitor);
  }
}

class ExpressionStatement extends Statement {
  final Expression expression;
  ExpressionStatement(this.expression);

  accept(NodeVisitor visitor) => visitor.visitExpressionStatement(this);
  void visitChildren(NodeVisitor visitor) { expression.accept(visitor); }
}

class EmptyStatement extends Statement {
  EmptyStatement();

  accept(NodeVisitor visitor) => visitor.visitEmptyStatement(this);
  void visitChildren(NodeVisitor visitor) {}
}

class If extends Statement {
  final Expression condition;
  final Node then;
  final Node otherwise;

  If(this.condition, this.then, this.otherwise);
  If.noElse(this.condition, this.then) : this.otherwise = new EmptyStatement();

  bool get hasElse => otherwise is !EmptyStatement;

  accept(NodeVisitor visitor) => visitor.visitIf(this);

  void visitChildren(NodeVisitor visitor) {
    condition.accept(visitor);
    then.accept(visitor);
    otherwise.accept(visitor);
  }
}

abstract class Loop extends Statement {
  final Statement body;
  Loop(this.body);
}

class For extends Loop {
  final Expression init;
  final Expression condition;
  final Expression update;

  For(this.init, this.condition, this.update, Statement body) : super(body);

  accept(NodeVisitor visitor) => visitor.visitFor(this);

  void visitChildren(NodeVisitor visitor) {
    if (init != null) init.accept(visitor);
    if (condition != null) condition.accept(visitor);
    if (update != null) update.accept(visitor);
    body.accept(visitor);
  }
}

class ForIn extends Loop {
  // Note that [VariableDeclarationList] is a subclass of [Expression].
  // Therefore we can type the leftHandSide as [Expression].
  final Expression leftHandSide;
  final Expression object;

  ForIn(this.leftHandSide, this.object, Statement body) : super(body);

  accept(NodeVisitor visitor) => visitor.visitForIn(this);

  void visitChildren(NodeVisitor visitor) {
    leftHandSide.accept(visitor);
    object.accept(visitor);
    body.accept(visitor);
  }
}

class While extends Loop {
  final Node condition;

  While(this.condition, Statement body) : super(body);

  accept(NodeVisitor visitor) => visitor.visitWhile(this);

  void visitChildren(NodeVisitor visitor) {
    condition.accept(visitor);
    body.accept(visitor);
  }
}

class Do extends Loop {
  final Expression condition;

  Do(Statement body, this.condition) : super(body);

  accept(NodeVisitor visitor) => visitor.visitDo(this);

  void visitChildren(NodeVisitor visitor) {
    body.accept(visitor);
    condition.accept(visitor);
  }
}

class Continue extends Statement {
  final String targetLabel;  // Can be null.

  Continue(this.targetLabel);

  accept(NodeVisitor visitor) => visitor.visitContinue(this);
  void visitChildren(NodeVisitor visitor) {}
}

class Break extends Statement {
  final String targetLabel;  // Can be null.

  Break(this.targetLabel);

  accept(NodeVisitor visitor) => visitor.visitBreak(this);
  void visitChildren(NodeVisitor visitor) {}
}

class Return extends Statement {
  final Expression value;  // Can be null.

  Return([this.value = null]);

  accept(NodeVisitor visitor) => visitor.visitReturn(this);

  void visitChildren(NodeVisitor visitor) {
    if (value != null) value.accept(visitor);
  }
}

class Throw extends Statement {
  final Expression expression;

  Throw(this.expression);

  accept(NodeVisitor visitor) => visitor.visitThrow(this);

  void visitChildren(NodeVisitor visitor) {
    expression.accept(visitor);
  }
}

class Try extends Statement {
  final Block body;
  final Catch catchPart;  // Can be null if [finallyPart] is non-null.
  final Block finallyPart;  // Can be null if [catchPart] is non-null.

  Try(this.body, this.catchPart, this.finallyPart) {
    assert(catchPart != null || finallyPart != null);
  }

  accept(NodeVisitor visitor) => visitor.visitTry(this);

  void visitChildren(NodeVisitor visitor) {
    body.accept(visitor);
    if (catchPart != null) catchPart.accept(visitor);
    if (finallyPart != null) finallyPart.accept(visitor);
  }
}

class Catch extends Node {
  final VariableDeclaration declaration;
  final Block body;

  Catch(this.declaration, this.body);

  accept(NodeVisitor visitor) => visitor.visitCatch(this);

  void visitChildren(NodeVisitor visitor) {
    declaration.accept(visitor);
    body.accept(visitor);
  }
}

class Switch extends Statement {
  final Expression key;
  final List<SwitchClause> cases;

  Switch(this.key, this.cases);

  accept(NodeVisitor visitor) => visitor.visitSwitch(this);

  void visitChildren(NodeVisitor visitor) {
    key.accept(visitor);
    for (SwitchClause clause in cases) clause.accept(visitor);
  }
}

abstract class SwitchClause extends Node {
  final Block body;

  SwitchClause(this.body);
}

class Case extends SwitchClause {
  final Expression expression;

  Case(this.expression, Block body) : super(body);

  accept(NodeVisitor visitor) => visitor.visitCase(this);

  void visitChildren(NodeVisitor visitor) {
    expression.accept(visitor);
    body.accept(visitor);
  }
}

class Default extends SwitchClause {
  Default(Block body) : super(body);

  accept(NodeVisitor visitor) => visitor.visitDefault(this);

  void visitChildren(NodeVisitor visitor) {
    body.accept(visitor);
  }
}

class FunctionDeclaration extends Statement {
  final VariableDeclaration name;
  final Fun function;

  FunctionDeclaration(this.name, this.function);

  accept(NodeVisitor visitor) => visitor.visitFunctionDeclaration(this);

  void visitChildren(NodeVisitor visitor) {
    name.accept(visitor);
    function.accept(visitor);
  }
}

class LabeledStatement extends Statement {
  final String label;
  final Statement body;

  LabeledStatement(this.label, this.body);

  accept(NodeVisitor visitor) => visitor.visitLabeledStatement(this);

  void visitChildren(NodeVisitor visitor) {
    body.accept(visitor);
  }
}

class LiteralStatement extends Statement {
  final String code;

  LiteralStatement(this.code);

  accept(NodeVisitor visitor) => visitor.visitLiteralStatement(this);
  void visitChildren(NodeVisitor visitor) { }
}

abstract class Expression extends Node {
  int get precedenceLevel;

  Call callWith(List<Expression> arguments) => new Call(this, arguments);

  New newWith(List<Expression> arguments) => new New(this, arguments);

  PropertyAccess operator [](expression) {
    if (expression is Expression) {
      return new PropertyAccess(this, expression);
    } else if (expression is int) {
      return new PropertyAccess.indexed(this, expression);
    } else if (expression is String) {
      return new PropertyAccess.field(this, expression);
    } else {
      throw new ArgumentError('Expected an int, String, or Expression');
    }
  }

  Statement toStatement() => new ExpressionStatement(this);

  Call call([expression]) {
    List<Expression> arguments;
    if (expression == null) {
      arguments = <Expression>[];
    } else if (expression is List) {
      arguments = expression.map(js.toExpression).toList();
    } else {
      arguments = <Expression>[js.toExpression(expression)];
    }
    return callWith(arguments);
  }

  Expression equals(expression) => binary('==', expression);

  Expression strictEquals(expression) => binary('===', expression);

  Expression notEquals(expression) => binary('!=', expression);

  Expression operator +(expression) => binary('+', expression);

  Expression operator -(expression) => binary('-', expression);

  Expression operator &(expression) => binary('&', expression);

  Expression operator <(expression) => binary('<', expression);

  Expression operator >(expression) => binary('>', expression);

  Expression operator >=(expression) => binary('>=', expression);

  Expression binary(String operator, expression) {
    return new Binary(operator, this, js.toExpression(expression));
  }

  Expression assign(expression) {
    return new Assignment(this, js.toExpression(expression));
  }

  Expression update(String operator, expression) {
    return new Assignment.compound(this, operator, js.toExpression(expression));
  }

  Expression get plusPlus => new Postfix('++', this);

  Prefix get typeof => new Prefix('typeof', this);

  Prefix get not => new Prefix('!', this);
}

class LiteralExpression extends Expression {
  final String template;
  final List<Expression> inputs;

  LiteralExpression(this.template) : inputs = const [];
  LiteralExpression.withData(this.template, this.inputs);

  accept(NodeVisitor visitor) => visitor.visitLiteralExpression(this);

  void visitChildren(NodeVisitor visitor) {
    if (inputs != null) {
      for (Expression expr in inputs) expr.accept(visitor);
    }
  }

  // Code that uses JS must take care of operator precedences, and
  // put parenthesis if needed.
  int get precedenceLevel => PRIMARY;
}

/**
 * [VariableDeclarationList] is a subclass of [Expression] to simplify the
 * AST.
 */
class VariableDeclarationList extends Expression {
  final List<VariableInitialization> declarations;

  VariableDeclarationList(this.declarations);

  accept(NodeVisitor visitor) => visitor.visitVariableDeclarationList(this);

  void visitChildren(NodeVisitor visitor) {
    for (VariableInitialization declaration in declarations) {
      declaration.accept(visitor);
    }
  }

  int get precedenceLevel => EXPRESSION;
}

class Sequence extends Expression {
  final List<Expression> expressions;

  Sequence(this.expressions);

  accept(NodeVisitor visitor) => visitor.visitSequence(this);

  void visitChildren(NodeVisitor visitor) {
    for (Expression expr in expressions) expr.accept(visitor);
  }

  int get precedenceLevel => EXPRESSION;
}

class Assignment extends Expression {
  final Expression leftHandSide;
  // Null, if the assignment is not compound.
  final VariableReference compoundTarget;
  final Expression value;  // May be null, for [VariableInitialization]s.

  Assignment(leftHandSide, value)
      : this._internal(leftHandSide, null, value);
  Assignment.compound(leftHandSide, String op, value)
      : this._internal(leftHandSide, new VariableUse(op), value);
  Assignment._internal(this.leftHandSide, this.compoundTarget, this.value);

  int get precedenceLevel => ASSIGNMENT;

  bool get isCompound => compoundTarget != null;
  String get op => compoundTarget == null ? null : compoundTarget.name;

  accept(NodeVisitor visitor) => visitor.visitAssignment(this);

  void visitChildren(NodeVisitor visitor) {
    leftHandSide.accept(visitor);
    if (compoundTarget != null) compoundTarget.accept(visitor);
    if (value != null) value.accept(visitor);
  }
}

class VariableInitialization extends Assignment {
  /** [value] may be null. */
  VariableInitialization(VariableDeclaration declaration, Expression value)
      : super(declaration, value);

  VariableDeclaration get declaration => leftHandSide;

  accept(NodeVisitor visitor) => visitor.visitVariableInitialization(this);
}

class Conditional extends Expression {
  final Expression condition;
  final Expression then;
  final Expression otherwise;

  Conditional(this.condition, this.then, this.otherwise);

  accept(NodeVisitor visitor) => visitor.visitConditional(this);

  void visitChildren(NodeVisitor visitor) {
    condition.accept(visitor);
    then.accept(visitor);
    otherwise.accept(visitor);
  }

  int get precedenceLevel => ASSIGNMENT;
}

class Call extends Expression {
  Expression target;
  List<Expression> arguments;

  Call(this.target, this.arguments);

  accept(NodeVisitor visitor) => visitor.visitCall(this);

  void visitChildren(NodeVisitor visitor) {
    target.accept(visitor);
    for (Expression arg in arguments) arg.accept(visitor);
  }

  int get precedenceLevel => CALL;
}

class New extends Call {
  New(Expression cls, List<Expression> arguments) : super(cls, arguments);

  accept(NodeVisitor visitor) => visitor.visitNew(this);
}

class Binary extends Call {
  Binary(String op, Expression left, Expression right)
      : super(new VariableUse(op), <Expression>[left, right]);

  String get op {
    VariableUse use = target;
    return use.name;
  }

  Expression get left => arguments[0];
  Expression get right => arguments[1];

  accept(NodeVisitor visitor) => visitor.visitBinary(this);

  int get precedenceLevel {
    // TODO(floitsch): switch to constant map.
    switch (op) {
      case "*":
      case "/":
      case "%":
        return MULTIPLICATIVE;
      case "+":
      case "-":
        return ADDITIVE;
      case "<<":
      case ">>":
      case ">>>":
        return SHIFT;
      case "<":
      case ">":
      case "<=":
      case ">=":
      case "instanceof":
      case "in":
        return RELATIONAL;
      case "==":
      case "===":
      case "!=":
      case "!==":
        return EQUALITY;
      case "&":
        return BIT_AND;
      case "^":
        return BIT_XOR;
      case "|":
        return BIT_OR;
      case "&&":
        return LOGICAL_AND;
      case "||":
        return LOGICAL_OR;
      default:
        throw new leg.CompilerCancelledException(
            "Internal Error: Unhandled binary operator: $op");
    }
  }
}

class Prefix extends Call {
  Prefix(String op, Expression arg)
      : super(new VariableUse(op), <Expression>[arg]);

  String get op => (target as VariableUse).name;
  Expression get argument => arguments[0];

  accept(NodeVisitor visitor) => visitor.visitPrefix(this);

  int get precedenceLevel => UNARY;
}

class Postfix extends Call {
  Postfix(String op, Expression arg)
      : super(new VariableUse(op), <Expression>[arg]);

  String get op => (target as VariableUse).name;
  Expression get argument => arguments[0];

  accept(NodeVisitor visitor) => visitor.visitPostfix(this);

  int get precedenceLevel => UNARY;
}

abstract class VariableReference extends Expression {
  final String name;

  // We treat operators as if they were special functions. They can thus be
  // referenced like other variables.
  VariableReference(this.name);

  accept(NodeVisitor visitor);
  int get precedenceLevel => PRIMARY;
  void visitChildren(NodeVisitor visitor) {}
}

class VariableUse extends VariableReference {
  VariableUse(String name) : super(name);

  accept(NodeVisitor visitor) => visitor.visitVariableUse(this);

  VariableUse asVariableUse() => this;
}

class VariableDeclaration extends VariableReference {
  VariableDeclaration(String name) : super(name);

  accept(NodeVisitor visitor) => visitor.visitVariableDeclaration(this);
}

class Parameter extends VariableDeclaration {
  Parameter(String id) : super(id);

  accept(NodeVisitor visitor) => visitor.visitParameter(this);
}

class This extends Parameter {
  This() : super("this");

  accept(NodeVisitor visitor) => visitor.visitThis(this);
}

class NamedFunction extends Expression {
  final VariableDeclaration name;
  final Fun function;

  NamedFunction(this.name, this.function);

  accept(NodeVisitor visitor) => visitor.visitNamedFunction(this);

  void visitChildren(NodeVisitor visitor) {
    name.accept(visitor);
    function.accept(visitor);
  }

  int get precedenceLevel => CALL;
}

class Fun extends Expression {
  final List<Parameter> params;
  final Block body;

  Fun(this.params, this.body);

  accept(NodeVisitor visitor) => visitor.visitFun(this);

  void visitChildren(NodeVisitor visitor) {
    for (Parameter param in params) param.accept(visitor);
    body.accept(visitor);
  }

  int get precedenceLevel => CALL;
}

class PropertyAccess extends Expression {
  final Expression receiver;
  final Expression selector;

  PropertyAccess(this.receiver, this.selector);
  PropertyAccess.field(this.receiver, String fieldName)
      : selector = new LiteralString("'$fieldName'");
  PropertyAccess.indexed(this.receiver, int index)
      : selector = new LiteralNumber('$index');

  accept(NodeVisitor visitor) => visitor.visitAccess(this);

  void visitChildren(NodeVisitor visitor) {
    receiver.accept(visitor);
    selector.accept(visitor);
  }

  int get precedenceLevel => CALL;
}

abstract class Literal extends Expression {
  void visitChildren(NodeVisitor visitor) {}

  int get precedenceLevel => PRIMARY;
}

class LiteralBool extends Literal {
  final bool value;

  LiteralBool(this.value);

  accept(NodeVisitor visitor) => visitor.visitLiteralBool(this);
  // [visitChildren] inherited from [Literal].
}

class LiteralNull extends Literal {
  LiteralNull();

  accept(NodeVisitor visitor) => visitor.visitLiteralNull(this);
}

class LiteralString extends Literal {
  final String value;

  LiteralString(this.value);

  accept(NodeVisitor visitor) => visitor.visitLiteralString(this);
}

class LiteralNumber extends Literal {
  final String value;

  LiteralNumber(this.value);

  accept(NodeVisitor visitor) => visitor.visitLiteralNumber(this);
}

class ArrayInitializer extends Expression {
  final int length;
  // We represent the array as sparse list of elements. Each element knows its
  // position in the array.
  final List<ArrayElement> elements;

  ArrayInitializer(this.length, this.elements);

  factory ArrayInitializer.from(Iterable<Expression> expressions) =>
      new ArrayInitializer(expressions.length, _convert(expressions));

  accept(NodeVisitor visitor) => visitor.visitArrayInitializer(this);

  void visitChildren(NodeVisitor visitor) {
    for (ArrayElement element in elements) element.accept(visitor);
  }

  int get precedenceLevel => PRIMARY;

  static List<ArrayElement> _convert(Iterable<Expression> expressions) {
    int index = 0;
    return expressions.map(
        (expression) => new ArrayElement(index++, expression))
        .toList();
  }
}

/**
 * An expression inside an [ArrayInitializer]. An [ArrayElement] knows
 * its position in the containing [ArrayInitializer].
 */
class ArrayElement extends Node {
  int index;
  Expression value;

  ArrayElement(this.index, this.value);

  accept(NodeVisitor visitor) => visitor.visitArrayElement(this);

  void visitChildren(NodeVisitor visitor) {
    value.accept(visitor);
  }
}

class ObjectInitializer extends Expression {
  List<Property> properties;

  ObjectInitializer(this.properties);

  accept(NodeVisitor visitor) => visitor.visitObjectInitializer(this);

  void visitChildren(NodeVisitor visitor) {
    for (Property init in properties) init.accept(visitor);
  }

  int get precedenceLevel => PRIMARY;
}

class Property extends Node {
  Literal name;
  Expression value;

  Property(this.name, this.value);

  accept(NodeVisitor visitor) => visitor.visitProperty(this);

  void visitChildren(NodeVisitor visitor) {
    name.accept(visitor);
    value.accept(visitor);
  }
}

class InterpolatedExpression extends Expression {
  Expression value;

  InterpolatedExpression(this.value);

  accept(NodeVisitor visitor) => visitor.visitInterpolatedExpression(this);

  void visitChildren(NodeVisitor visitor) {
    if (value != null) value.accept(visitor);
  }

  int get precedenceLevel => value.precedenceLevel;
}

class JSExpression extends Expression {
  Expression value;
  List<InterpolatedExpression> interpolatedExpressions;

  JSExpression(this.value, this.interpolatedExpressions);

  accept(NodeVisitor visitor) => visitor.visitJSExpression(this);

  void visitChildren(NodeVisitor visitor) {
    value.accept(visitor);
    for (InterpolatedExpression expression in interpolatedExpressions) {
      expression.accept(visitor);
    }
  }

  int get precedenceLevel => value.precedenceLevel;
}

/**
 * [RegExpLiteral]s, despite being called "Literal", do not inherit from
 * [Literal]. Indeed, regular expressions in JavaScript have a side-effect and
 * are thus not in the same category as numbers or strings.
 */
class RegExpLiteral extends Expression {
  /** Contains the pattern and the flags.*/
  String pattern;

  RegExpLiteral(this.pattern);

  accept(NodeVisitor visitor) => visitor.visitRegExpLiteral(this);
  void visitChildren(NodeVisitor visitor) {}

  int get precedenceLevel => PRIMARY;
}

/**
 * A comment.
 *
 * Extends [Statement] so we can add comments before statements in
 * [Block] and [Program].
 */
class Comment extends Statement {
  final String comment;

  Comment(this.comment);

  accept(NodeVisitor visitor) => visitor.visitComment(this);

  void visitChildren(NodeVisitor visitor) {}
}
