// Copyright (c) 2018, 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.

library fasta.fangorn;

import 'dart:core' hide MapEntry;

import 'package:kernel/ast.dart';

import '../names.dart';

import '../problems.dart' show unsupported;

import 'collections.dart'
    show
        ForElement,
        ForInElement,
        ForInMapEntry,
        ForMapEntry,
        IfElement,
        IfMapEntry,
        SpreadElement;

import 'internal_ast.dart';

/// A shadow tree factory.
class Forest {
  const Forest();

  Arguments createArguments(int fileOffset, List<Expression> positional,
      {List<DartType> types, List<NamedExpression> named}) {
    return new ArgumentsImpl(positional, types: types, named: named)
      ..fileOffset = fileOffset ?? TreeNode.noOffset;
  }

  Arguments createArgumentsForExtensionMethod(
      int fileOffset,
      int extensionTypeParameterCount,
      int typeParameterCount,
      Expression receiver,
      {List<DartType> extensionTypeArguments = const <DartType>[],
      int extensionTypeArgumentOffset,
      List<DartType> typeArguments = const <DartType>[],
      List<Expression> positionalArguments = const <Expression>[],
      List<NamedExpression> namedArguments = const <NamedExpression>[]}) {
    assert(fileOffset != null);
    return new ArgumentsImpl.forExtensionMethod(
        extensionTypeParameterCount, typeParameterCount, receiver,
        extensionTypeArguments: extensionTypeArguments,
        extensionTypeArgumentOffset: extensionTypeArgumentOffset,
        typeArguments: typeArguments,
        positionalArguments: positionalArguments,
        namedArguments: namedArguments)
      ..fileOffset = fileOffset ?? TreeNode.noOffset;
  }

  Arguments createArgumentsEmpty(int fileOffset) {
    assert(fileOffset != null);
    return createArguments(fileOffset, <Expression>[]);
  }

  List<NamedExpression> argumentsNamed(Arguments arguments) {
    return arguments.named;
  }

  List<Expression> argumentsPositional(Arguments arguments) {
    return arguments.positional;
  }

  List<DartType> argumentsTypeArguments(Arguments arguments) {
    return arguments.types;
  }

  void argumentsSetTypeArguments(Arguments arguments, List<DartType> types) {
    ArgumentsImpl.setNonInferrableArgumentTypes(arguments, types);
  }

  /// Return a representation of a boolean literal at the given [fileOffset].
  /// The literal has the given [value].
  BoolLiteral createBoolLiteral(int fileOffset, bool value) {
    assert(fileOffset != null);
    return new BoolLiteral(value)..fileOffset = fileOffset;
  }

  /// Return a representation of a double literal at the given [fileOffset]. The
  /// literal has the given [value].
  DoubleLiteral createDoubleLiteral(int fileOffset, double value) {
    assert(fileOffset != null);
    return new DoubleLiteral(value)..fileOffset = fileOffset;
  }

  /// Return a representation of an integer literal at the given [fileOffset].
  /// The literal has the given [value].
  IntLiteral createIntLiteral(int fileOffset, int value, [String literal]) {
    assert(fileOffset != null);
    return new IntJudgment(value, literal)..fileOffset = fileOffset;
  }

  IntLiteral createIntLiteralLarge(int fileOffset, String literal) {
    assert(fileOffset != null);
    return new ShadowLargeIntLiteral(literal, fileOffset);
  }

  /// Return a representation of a list literal at the given [fileOffset]. The
  /// [isConst] is `true` if the literal is either explicitly or implicitly a
  /// constant. The [typeArgument] is the representation of the single valid
  /// type argument preceding the list literal, or `null` if there is no type
  /// argument, there is more than one type argument, or if the type argument
  /// cannot be resolved. The list of [expressions] is a list of the
  /// representations of the list elements.
  ListLiteral createListLiteral(
      int fileOffset, DartType typeArgument, List<Expression> expressions,
      {bool isConst}) {
    assert(fileOffset != null);
    assert(isConst != null);
    return new ListLiteral(expressions,
        typeArgument: typeArgument, isConst: isConst)
      ..fileOffset = fileOffset;
  }

  /// Return a representation of a set literal at the given [fileOffset]. The
  /// [isConst] is `true` if the literal is either explicitly or implicitly a
  /// constant. The [typeArgument] is the representation of the single valid
  /// type argument preceding the set literal, or `null` if there is no type
  /// argument, there is more than one type argument, or if the type argument
  /// cannot be resolved. The list of [expressions] is a list of the
  /// representations of the set elements.
  SetLiteral createSetLiteral(
      int fileOffset, DartType typeArgument, List<Expression> expressions,
      {bool isConst}) {
    assert(fileOffset != null);
    assert(isConst != null);
    return new SetLiteral(expressions,
        typeArgument: typeArgument, isConst: isConst)
      ..fileOffset = fileOffset;
  }

  /// Return a representation of a map literal at the given [fileOffset]. The
  /// [isConst] is `true` if the literal is either explicitly or implicitly a
  /// constant. The [keyType] is the representation of the first type argument
  /// preceding the map literal, or `null` if there are not exactly two type
  /// arguments or if the first type argument cannot be resolved. The
  /// [valueType] is the representation of the second type argument preceding
  /// the map literal, or `null` if there are not exactly two type arguments or
  /// if the second type argument cannot be resolved. The list of [entries] is a
  /// list of the representations of the map entries.
  MapLiteral createMapLiteral(int fileOffset, DartType keyType,
      DartType valueType, List<MapEntry> entries,
      {bool isConst}) {
    assert(fileOffset != null);
    assert(isConst != null);
    return new MapLiteral(entries,
        keyType: keyType, valueType: valueType, isConst: isConst)
      ..fileOffset = fileOffset;
  }

  /// Return a representation of a null literal at the given [fileOffset].
  NullLiteral createNullLiteral(int fileOffset) {
    assert(fileOffset != null);
    return new NullLiteral()..fileOffset = fileOffset;
  }

  /// Return a representation of a simple string literal at the given
  /// [fileOffset]. The literal has the given [value]. This does not include
  /// either adjacent strings or interpolated strings.
  StringLiteral createStringLiteral(int fileOffset, String value) {
    assert(fileOffset != null);
    return new StringLiteral(value)..fileOffset = fileOffset;
  }

  /// Return a representation of a symbol literal defined by [value] at the
  /// given [fileOffset].
  SymbolLiteral createSymbolLiteral(int fileOffset, String value) {
    assert(fileOffset != null);
    return new SymbolLiteral(value)..fileOffset = fileOffset;
  }

  TypeLiteral createTypeLiteral(int fileOffset, DartType type) {
    assert(fileOffset != null);
    return new TypeLiteral(type)..fileOffset = fileOffset;
  }

  /// Return a representation of a key/value pair in a literal map at the given
  /// [fileOffset]. The [key] is the representation of the expression used to
  /// compute the key. The [value] is the representation of the expression used
  /// to compute the value.
  MapEntry createMapEntry(int fileOffset, Expression key, Expression value) {
    assert(fileOffset != null);
    return new MapEntry(key, value)..fileOffset = fileOffset;
  }

  Expression createLoadLibrary(
      int fileOffset, LibraryDependency dependency, Arguments arguments) {
    assert(fileOffset != null);
    return new LoadLibraryImpl(dependency, arguments)..fileOffset = fileOffset;
  }

  Expression checkLibraryIsLoaded(
      int fileOffset, LibraryDependency dependency) {
    assert(fileOffset != null);
    return new CheckLibraryIsLoaded(dependency)..fileOffset = fileOffset;
  }

  Expression createAsExpression(
      int fileOffset, Expression expression, DartType type) {
    assert(fileOffset != null);
    return new AsExpression(expression, type)..fileOffset = fileOffset;
  }

  Expression createSpreadElement(int fileOffset, Expression expression,
      {bool isNullAware}) {
    assert(fileOffset != null);
    assert(isNullAware != null);
    return new SpreadElement(expression, isNullAware)..fileOffset = fileOffset;
  }

  Expression createIfElement(
      int fileOffset, Expression condition, Expression then,
      [Expression otherwise]) {
    assert(fileOffset != null);
    return new IfElement(condition, then, otherwise)..fileOffset = fileOffset;
  }

  MapEntry createIfMapEntry(int fileOffset, Expression condition, MapEntry then,
      [MapEntry otherwise]) {
    assert(fileOffset != null);
    return new IfMapEntry(condition, then, otherwise)..fileOffset = fileOffset;
  }

  Expression createForElement(
      int fileOffset,
      List<VariableDeclaration> variables,
      Expression condition,
      List<Expression> updates,
      Expression body) {
    assert(fileOffset != null);
    return new ForElement(variables, condition, updates, body)
      ..fileOffset = fileOffset;
  }

  MapEntry createForMapEntry(
      int fileOffset,
      List<VariableDeclaration> variables,
      Expression condition,
      List<Expression> updates,
      MapEntry body) {
    assert(fileOffset != null);
    return new ForMapEntry(variables, condition, updates, body)
      ..fileOffset = fileOffset;
  }

  Expression createForInElement(
      int fileOffset,
      VariableDeclaration variable,
      Expression iterable,
      Statement prologue,
      Expression body,
      Expression problem,
      {bool isAsync: false}) {
    assert(fileOffset != null);
    return new ForInElement(variable, iterable, prologue, body, problem,
        isAsync: isAsync)
      ..fileOffset = fileOffset;
  }

  MapEntry createForInMapEntry(
      int fileOffset,
      VariableDeclaration variable,
      Expression iterable,
      Statement prologue,
      MapEntry body,
      Expression problem,
      {bool isAsync: false}) {
    assert(fileOffset != null);
    return new ForInMapEntry(variable, iterable, prologue, body, problem,
        isAsync: isAsync)
      ..fileOffset = fileOffset;
  }

  /// Return a representation of an assert that appears in a constructor's
  /// initializer list.
  AssertInitializer createAssertInitializer(
      int fileOffset, AssertStatement assertStatement) {
    assert(fileOffset != null);
    return new AssertInitializer(assertStatement)..fileOffset = fileOffset;
  }

  /// Return a representation of an assert that appears as a statement.
  Statement createAssertStatement(int fileOffset, Expression condition,
      Expression message, int conditionStartOffset, int conditionEndOffset) {
    assert(fileOffset != null);
    return new AssertStatement(condition,
        conditionStartOffset: conditionStartOffset,
        conditionEndOffset: conditionEndOffset,
        message: message)
      ..fileOffset = fileOffset;
  }

  Expression createAwaitExpression(int fileOffset, Expression operand) {
    assert(fileOffset != null);
    return new AwaitExpression(operand)..fileOffset = fileOffset;
  }

  /// Return a representation of a block of [statements] at the given
  /// [fileOffset].
  Statement createBlock(int fileOffset, List<Statement> statements) {
    assert(fileOffset != null);
    List<Statement> copy;
    for (int i = 0; i < statements.length; i++) {
      Statement statement = statements[i];
      if (statement is _VariablesDeclaration) {
        copy ??= new List<Statement>.from(statements.getRange(0, i));
        copy.addAll(statement.declarations);
      } else if (copy != null) {
        copy.add(statement);
      }
    }
    return new Block(copy ?? statements)..fileOffset = fileOffset;
  }

  /// Return a representation of a break statement.
  Statement createBreakStatement(int fileOffset, Object label) {
    assert(fileOffset != null);
    // TODO(johnniwinther): Use [label]?
    return new BreakStatementImpl(isContinue: false)..fileOffset = fileOffset;
  }

  /// Return a representation of a catch clause.
  Catch createCatch(
      int fileOffset,
      DartType exceptionType,
      VariableDeclaration exceptionParameter,
      VariableDeclaration stackTraceParameter,
      DartType stackTraceType,
      Statement body) {
    assert(fileOffset != null);
    return new Catch(exceptionParameter, body,
        guard: exceptionType, stackTrace: stackTraceParameter)
      ..fileOffset = fileOffset;
  }

  /// Return a representation of a conditional expression at the given
  /// [fileOffset]. The [condition] is the expression preceding the question
  /// mark. The [thenExpression] is the expression following the question mark.
  /// The [elseExpression] is the expression following the colon.
  Expression createConditionalExpression(int fileOffset, Expression condition,
      Expression thenExpression, Expression elseExpression) {
    return new ConditionalExpression(
        condition, thenExpression, elseExpression, null)
      ..fileOffset = fileOffset;
  }

  /// Return a representation of a continue statement.
  Statement createContinueStatement(int fileOffset, Object label) {
    assert(fileOffset != null);
    // TODO(johnniwinther): Use [label]?
    return new BreakStatementImpl(isContinue: true)..fileOffset = fileOffset;
  }

  /// Return a representation of a do statement.
  Statement createDoStatement(
      int fileOffset, Statement body, Expression condition) {
    assert(fileOffset != null);
    return new DoStatement(body, condition)..fileOffset = fileOffset;
  }

  /// Return a representation of an expression statement at the given
  /// [fileOffset] containing the [expression].
  Statement createExpressionStatement(int fileOffset, Expression expression) {
    assert(fileOffset != null);
    return new ExpressionStatement(expression)..fileOffset = fileOffset;
  }

  /// Return a representation of an empty statement  at the given [fileOffset].
  Statement createEmptyStatement(int fileOffset) {
    assert(fileOffset != null);
    return new EmptyStatement()..fileOffset = fileOffset;
  }

  /// Return a representation of a for statement.
  Statement createForStatement(
      int fileOffset,
      List<VariableDeclaration> variables,
      Expression condition,
      List<Expression> updaters,
      Statement body) {
    assert(fileOffset != null);
    return new ForStatement(variables ?? [], condition, updaters, body)
      ..fileOffset = fileOffset;
  }

  /// Return a representation of an `if` statement.
  Statement createIfStatement(int fileOffset, Expression condition,
      Statement thenStatement, Statement elseStatement) {
    assert(fileOffset != null);
    return new IfStatement(condition, thenStatement, elseStatement)
      ..fileOffset = fileOffset;
  }

  /// Return a representation of an `is` expression at the given [fileOffset].
  /// The [operand] is the representation of the left operand. The [type] is a
  /// representation of the type that is the right operand. If [notFileOffset]
  /// is non-null the test is negated the that file offset.
  Expression createIsExpression(
      int fileOffset, Expression operand, DartType type,
      {int notFileOffset}) {
    assert(fileOffset != null);
    Expression result = new IsExpression(operand, type)
      ..fileOffset = fileOffset;
    if (notFileOffset != null) {
      result = createNot(notFileOffset, result);
    }
    return result;
  }

  /// Return a representation of a logical expression at the given [fileOffset]
  /// having the [leftOperand], [rightOperand] and the [operator]
  /// (either `&&` or `||`).
  Expression createLogicalExpression(int fileOffset, Expression leftOperand,
      String operator, Expression rightOperand) {
    assert(fileOffset != null);
    assert(operator == '&&' || operator == '||');
    return new LogicalExpression(leftOperand, operator, rightOperand)
      ..fileOffset = fileOffset;
  }

  Expression createNot(int fileOffset, Expression operand) {
    assert(fileOffset != null);
    return new Not(operand)..fileOffset = fileOffset;
  }

  /// Return a representation of a rethrow statement consisting of the
  /// rethrow at [rethrowFileOffset] and the statement at [statementFileOffset].
  Statement createRethrowStatement(
      int rethrowFileOffset, int statementFileOffset) {
    assert(rethrowFileOffset != null);
    assert(statementFileOffset != null);
    return new ExpressionStatement(
        new Rethrow()..fileOffset = rethrowFileOffset)
      ..fileOffset = statementFileOffset;
  }

  /// Return a representation of a return statement.
  Statement createReturnStatement(int fileOffset, Expression expression,
      {bool isArrow: true}) {
    assert(fileOffset != null);
    return new ReturnStatementImpl(isArrow, expression)
      ..fileOffset = fileOffset ?? TreeNode.noOffset;
  }

  Expression createStringConcatenation(
      int fileOffset, List<Expression> expressions) {
    assert(fileOffset != null);
    return new StringConcatenation(expressions)..fileOffset = fileOffset;
  }

  /// The given [statement] is being used as the target of either a break or
  /// continue statement. Return the statement that should be used as the actual
  /// target.
  Statement createLabeledStatement(Statement statement) {
    return new LabeledStatement(statement)..fileOffset = statement.fileOffset;
  }

  Expression createThisExpression(int fileOffset) {
    assert(fileOffset != null);
    return new ThisExpression()..fileOffset = fileOffset;
  }

  /// Return a representation of a throw expression at the given [fileOffset].
  Expression createThrow(int fileOffset, Expression expression) {
    assert(fileOffset != null);
    return new Throw(expression)..fileOffset = fileOffset;
  }

  bool isThrow(Object o) => o is Throw;

  TryCatch createTryCatch(
      int fileOffset, Statement tryBlock, List<Catch> catchBlocks) {
    assert(fileOffset != null);
    return new TryCatch(tryBlock, catchBlocks)..fileOffset = fileOffset;
  }

  TryFinally createTryFinally(
      int fileOffset, Statement tryBlock, Statement finallyBlock) {
    assert(fileOffset != null);
    return new TryFinally(tryBlock, finallyBlock)..fileOffset = fileOffset;
  }

  _VariablesDeclaration variablesDeclaration(
      List<VariableDeclaration> declarations, Uri uri) {
    return new _VariablesDeclaration(declarations, uri);
  }

  List<VariableDeclaration> variablesDeclarationExtractDeclarations(
      _VariablesDeclaration variablesDeclaration) {
    return variablesDeclaration.declarations;
  }

  Statement wrapVariables(Statement statement) {
    if (statement is _VariablesDeclaration) {
      return new Block(
          new List<Statement>.from(statement.declarations, growable: true))
        ..fileOffset = statement.fileOffset;
    } else if (statement is VariableDeclaration) {
      return new Block(<Statement>[statement])
        ..fileOffset = statement.fileOffset;
    } else {
      return statement;
    }
  }

  /// Return a representation of a while statement at the given [fileOffset]
  /// consisting of the given [condition] and [body].
  Statement createWhileStatement(
      int fileOffset, Expression condition, Statement body) {
    assert(fileOffset != null);
    return new WhileStatement(condition, body)..fileOffset = fileOffset;
  }

  /// Return a representation of a yield statement at the given [fileOffset]
  /// of the given [expression]. If [isYieldStar] is `true` the created
  /// statement is a yield* statement.
  Statement createYieldStatement(int fileOffset, Expression expression,
      {bool isYieldStar}) {
    assert(fileOffset != null);
    assert(isYieldStar != null);
    return new YieldStatement(expression, isYieldStar: isYieldStar)
      ..fileOffset = fileOffset;
  }

  bool isBlock(Object node) => node is Block;

  bool isErroneousNode(Object node) {
    if (node is ExpressionStatement) {
      ExpressionStatement statement = node;
      node = statement.expression;
    }
    if (node is VariableDeclaration) {
      VariableDeclaration variable = node;
      node = variable.initializer;
    }
    if (node is Let) {
      Let let = node;
      node = let.variable.initializer;
    }
    return node is InvalidExpression;
  }

  bool isThisExpression(Object node) => node is ThisExpression;

  bool isVariablesDeclaration(Object node) => node is _VariablesDeclaration;

  /// Creates [VariableDeclaration] for a variable named [name] at the given
  /// [functionNestingLevel].
  VariableDeclaration createVariableDeclaration(
      int fileOffset, String name, int functionNestingLevel,
      {Expression initializer,
      DartType type,
      bool isFinal: false,
      bool isConst: false,
      bool isFieldFormal: false,
      bool isCovariant: false,
      bool isLocalFunction: false}) {
    assert(fileOffset != null);
    return new VariableDeclarationImpl(name, functionNestingLevel,
        type: type,
        initializer: initializer,
        isFinal: isFinal,
        isConst: isConst,
        isFieldFormal: isFieldFormal,
        isCovariant: isCovariant,
        isLocalFunction: isLocalFunction);
  }

  VariableDeclaration createVariableDeclarationForValue(Expression initializer,
      {DartType type = const DynamicType()}) {
    return new VariableDeclarationImpl.forValue(initializer)
      ..type = type
      ..fileOffset = initializer.fileOffset;
  }

  Let createLet(VariableDeclaration variable, Expression body) {
    return new Let(variable, body);
  }

  FunctionNode createFunctionNode(int fileOffset, Statement body,
      {List<TypeParameter> typeParameters,
      List<VariableDeclaration> positionalParameters,
      List<VariableDeclaration> namedParameters,
      int requiredParameterCount,
      DartType returnType: const DynamicType(),
      AsyncMarker asyncMarker: AsyncMarker.Sync,
      AsyncMarker dartAsyncMarker}) {
    assert(fileOffset != null);
    return new FunctionNode(body,
        typeParameters: typeParameters,
        positionalParameters: positionalParameters,
        namedParameters: namedParameters,
        requiredParameterCount: requiredParameterCount,
        returnType: returnType,
        asyncMarker: asyncMarker,
        dartAsyncMarker: dartAsyncMarker);
  }

  TypeParameter createTypeParameter(String name) {
    return new TypeParameter(name);
  }

  TypeParameterType createTypeParameterType(
      TypeParameter typeParameter, Nullability nullability) {
    return new TypeParameterType(typeParameter, nullability);
  }

  TypeParameterType createTypeParameterTypeWithDefaultNullabilityForLibrary(
      TypeParameter typeParameter, Library library) {
    return new TypeParameterType.withDefaultNullabilityForLibrary(
        typeParameter, library);
  }

  FunctionExpression createFunctionExpression(
      int fileOffset, FunctionNode function) {
    assert(fileOffset != null);
    return new FunctionExpression(function)..fileOffset = fileOffset;
  }

  MethodInvocation createFunctionInvocation(
      int fileOffset, Expression expression, Arguments arguments) {
    assert(fileOffset != null);
    return new MethodInvocationImpl(expression, callName, arguments)
      ..fileOffset = fileOffset;
  }

  MethodInvocation createMethodInvocation(
      int fileOffset, Expression expression, Name name, Arguments arguments,
      {bool isImplicitCall: false, Member interfaceTarget}) {
    assert(fileOffset != null);
    return new MethodInvocationImpl(expression, name, arguments,
        isImplicitCall: isImplicitCall)
      ..fileOffset = fileOffset
      ..interfaceTarget = interfaceTarget;
  }

  NamedExpression createNamedExpression(
      int fileOffset, String name, Expression expression) {
    assert(fileOffset != null);
    return new NamedExpression(name, expression)..fileOffset = fileOffset;
  }

  StaticInvocation createStaticInvocation(
      int fileOffset, Procedure procedure, Arguments arguments) {
    assert(fileOffset != null);
    return new StaticInvocation(procedure, arguments)..fileOffset = fileOffset;
  }

  SuperMethodInvocation createSuperMethodInvocation(
      int fileOffset, Name name, Procedure procedure, Arguments arguments) {
    assert(fileOffset != null);
    return new SuperMethodInvocation(name, arguments, procedure)
      ..fileOffset = fileOffset;
  }

  NullCheck createNullCheck(int fileOffset, Expression expression) {
    assert(fileOffset != null);
    return new NullCheck(expression)..fileOffset = fileOffset;
  }

  PropertyGet createPropertyGet(int fileOffset, Expression receiver, Name name,
      {Member interfaceTarget}) {
    assert(fileOffset != null);
    return new PropertyGet(receiver, name, interfaceTarget)
      ..fileOffset = fileOffset;
  }

  PropertySet createPropertySet(
      int fileOffset, Expression receiver, Name name, Expression value,
      {Member interfaceTarget, bool forEffect, bool readOnlyReceiver: false}) {
    assert(fileOffset != null);
    return new PropertySetImpl(receiver, name, value,
        interfaceTarget: interfaceTarget,
        forEffect: forEffect,
        readOnlyReceiver: readOnlyReceiver)
      ..fileOffset = fileOffset;
  }

  IndexGet createIndexGet(
      int fileOffset, Expression receiver, Expression index) {
    assert(fileOffset != null);
    return new IndexGet(receiver, index)..fileOffset = fileOffset;
  }

  IndexSet createIndexSet(
      int fileOffset, Expression receiver, Expression index, Expression value,
      {bool forEffect, bool readOnlyReceiver}) {
    assert(fileOffset != null);
    assert(forEffect != null);
    assert(readOnlyReceiver != null);
    return new IndexSet(receiver, index, value,
        forEffect: forEffect, readOnlyReceiver: readOnlyReceiver)
      ..fileOffset = fileOffset;
  }

  EqualsExpression createEquals(
      int fileOffset, Expression left, Expression right,
      {bool isNot}) {
    assert(fileOffset != null);
    assert(isNot != null);
    return new EqualsExpression(left, right, isNot: isNot)
      ..fileOffset = fileOffset;
  }

  BinaryExpression createBinary(
      int fileOffset, Expression left, Name binaryName, Expression right) {
    assert(fileOffset != null);
    return new BinaryExpression(left, binaryName, right)
      ..fileOffset = fileOffset;
  }

  UnaryExpression createUnary(
      int fileOffset, Name unaryName, Expression expression) {
    assert(fileOffset != null);
    return new UnaryExpression(unaryName, expression)..fileOffset = fileOffset;
  }

  ParenthesizedExpression createParenthesized(
      int fileOffset, Expression expression) {
    assert(fileOffset != null);
    return new ParenthesizedExpression(expression)..fileOffset = fileOffset;
  }
}

class _VariablesDeclaration extends Statement {
  final List<VariableDeclaration> declarations;
  final Uri uri;

  _VariablesDeclaration(this.declarations, this.uri) {
    setParents(declarations, this);
  }

  R accept<R>(v) {
    throw unsupported("accept", fileOffset, uri);
  }

  R accept1<R, A>(v, arg) {
    throw unsupported("accept1", fileOffset, uri);
  }

  visitChildren(v) {
    throw unsupported("visitChildren", fileOffset, uri);
  }

  transformChildren(v) {
    throw unsupported("transformChildren", fileOffset, uri);
  }
}
