// 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.

import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/standard_ast_factory.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/generated/resolver.dart' show AstRewriteVisitor;
import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
import 'package:analyzer/src/generated/testing/token_factory.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary/resynthesize.dart';

/**
 * Builder of [Expression]s from [UnlinkedExpr]s.
 */
class ExprBuilder {
  static const ARGUMENT_LIST = 'ARGUMENT_LIST';

  final UnitResynthesizer resynthesizer;
  final ElementImpl context;
  final UnlinkedExpr uc;
  final bool requireValidConst;

  int intPtr = 0;
  int doublePtr = 0;
  int stringPtr = 0;
  int refPtr = 0;
  int assignmentOperatorPtr = 0;
  final List<Expression> stack = <Expression>[];

  final List<UnlinkedExecutable> localFunctions;

  final Map<String, ParameterElement> parametersInScope;

  ExprBuilder(this.resynthesizer, this.context, this.uc,
      {this.requireValidConst: true,
      this.localFunctions,
      Map<String, ParameterElement> parametersInScope})
      : this.parametersInScope =
            parametersInScope ?? _parametersInScope(context);

  Expression build() {
    if (requireValidConst && !uc.isValidConst) {
      return null;
    }
    try {
      for (UnlinkedExprOperation operation in uc.operations) {
        switch (operation) {
          case UnlinkedExprOperation.pushNull:
            _push(AstTestFactory.nullLiteral());
            break;
          // bool
          case UnlinkedExprOperation.pushFalse:
            _push(AstTestFactory.booleanLiteral(false));
            break;
          case UnlinkedExprOperation.pushTrue:
            _push(AstTestFactory.booleanLiteral(true));
            break;
          // literals
          case UnlinkedExprOperation.pushInt:
            int value = uc.ints[intPtr++];
            _push(AstTestFactory.integer(value));
            break;
          case UnlinkedExprOperation.pushLongInt:
            int value = 0;
            int count = uc.ints[intPtr++];
            for (int i = 0; i < count; i++) {
              int next = uc.ints[intPtr++];
              value = value << 32 | next;
            }
            _push(AstTestFactory.integer(value));
            break;
          case UnlinkedExprOperation.pushDouble:
            double value = uc.doubles[doublePtr++];
            _push(AstTestFactory.doubleLiteral(value));
            break;
          case UnlinkedExprOperation.makeSymbol:
            String component = uc.strings[stringPtr++];
            _push(AstTestFactory.symbolLiteral([component]));
            break;
          // String
          case UnlinkedExprOperation.pushString:
            String value = uc.strings[stringPtr++];
            _push(AstTestFactory.string2(value));
            break;
          case UnlinkedExprOperation.concatenate:
            int count = uc.ints[intPtr++];
            List<InterpolationElement> elements = <InterpolationElement>[];
            for (int i = 0; i < count; i++) {
              Expression expr = _pop();
              InterpolationElement element = _newInterpolationElement(expr);
              elements.insert(0, element);
            }
            _push(AstTestFactory.string(elements));
            break;
          // binary
          case UnlinkedExprOperation.equal:
            _pushBinary(TokenType.EQ_EQ);
            break;
          case UnlinkedExprOperation.notEqual:
            _pushBinary(TokenType.BANG_EQ);
            break;
          case UnlinkedExprOperation.and:
            _pushBinary(TokenType.AMPERSAND_AMPERSAND);
            break;
          case UnlinkedExprOperation.or:
            _pushBinary(TokenType.BAR_BAR);
            break;
          case UnlinkedExprOperation.bitXor:
            _pushBinary(TokenType.CARET);
            break;
          case UnlinkedExprOperation.bitAnd:
            _pushBinary(TokenType.AMPERSAND);
            break;
          case UnlinkedExprOperation.bitOr:
            _pushBinary(TokenType.BAR);
            break;
          case UnlinkedExprOperation.bitShiftLeft:
            _pushBinary(TokenType.LT_LT);
            break;
          case UnlinkedExprOperation.bitShiftRight:
            _pushBinary(TokenType.GT_GT);
            break;
          case UnlinkedExprOperation.add:
            _pushBinary(TokenType.PLUS);
            break;
          case UnlinkedExprOperation.subtract:
            _pushBinary(TokenType.MINUS);
            break;
          case UnlinkedExprOperation.multiply:
            _pushBinary(TokenType.STAR);
            break;
          case UnlinkedExprOperation.divide:
            _pushBinary(TokenType.SLASH);
            break;
          case UnlinkedExprOperation.floorDivide:
            _pushBinary(TokenType.TILDE_SLASH);
            break;
          case UnlinkedExprOperation.modulo:
            _pushBinary(TokenType.PERCENT);
            break;
          case UnlinkedExprOperation.greater:
            _pushBinary(TokenType.GT);
            break;
          case UnlinkedExprOperation.greaterEqual:
            _pushBinary(TokenType.GT_EQ);
            break;
          case UnlinkedExprOperation.less:
            _pushBinary(TokenType.LT);
            break;
          case UnlinkedExprOperation.lessEqual:
            _pushBinary(TokenType.LT_EQ);
            break;
          // prefix
          case UnlinkedExprOperation.complement:
            _pushPrefix(TokenType.TILDE);
            break;
          case UnlinkedExprOperation.negate:
            _pushPrefix(TokenType.MINUS);
            break;
          case UnlinkedExprOperation.not:
            _pushPrefix(TokenType.BANG);
            break;
          // conditional
          case UnlinkedExprOperation.conditional:
            Expression elseExpr = _pop();
            Expression thenExpr = _pop();
            Expression condition = _pop();
            _push(AstTestFactory.conditionalExpression(
                condition, thenExpr, elseExpr));
            break;
          case UnlinkedExprOperation.invokeMethodRef:
            _pushInvokeMethodRef();
            break;
          case UnlinkedExprOperation.invokeMethod:
            List<Expression> arguments = _buildArguments();
            TypeArgumentList typeArguments = _buildTypeArguments();
            Expression target = _pop();
            String name = uc.strings[stringPtr++];
            _push(AstTestFactory.methodInvocation3(
                target, name, typeArguments, arguments));
            break;
          // containers
          case UnlinkedExprOperation.makeUntypedList:
            _pushList(null);
            break;
          case UnlinkedExprOperation.makeTypedList:
            TypeAnnotation itemType = _newTypeName();
            _pushList(
                AstTestFactory.typeArgumentList(<TypeAnnotation>[itemType]));
            break;
          case UnlinkedExprOperation.makeUntypedMap:
            _pushMap(null);
            break;
          case UnlinkedExprOperation.makeTypedMap:
            TypeAnnotation keyType = _newTypeName();
            TypeAnnotation valueType = _newTypeName();
            _pushMap(AstTestFactory.typeArgumentList(
                <TypeAnnotation>[keyType, valueType]));
            break;
          case UnlinkedExprOperation.pushReference:
            _pushReference();
            break;
          case UnlinkedExprOperation.extractProperty:
            _pushExtractProperty();
            break;
          case UnlinkedExprOperation.invokeConstructor:
            _pushInstanceCreation();
            break;
          case UnlinkedExprOperation.pushParameter:
            String name = uc.strings[stringPtr++];
            SimpleIdentifier identifier = AstTestFactory.identifier3(name);
            identifier.staticElement = parametersInScope[name];
            _push(identifier);
            break;
          case UnlinkedExprOperation.ifNull:
            _pushBinary(TokenType.QUESTION_QUESTION);
            break;
          case UnlinkedExprOperation.await:
            Expression expression = _pop();
            _push(AstTestFactory.awaitExpression(expression));
            break;
          case UnlinkedExprOperation.pushLocalFunctionReference:
            _pushLocalFunctionReference();
            break;
          case UnlinkedExprOperation.assignToRef:
            var ref = _createReference();
            _push(_createAssignment(ref));
            break;
          case UnlinkedExprOperation.typeCast:
            Expression expression = _pop();
            TypeAnnotation type = _newTypeName();
            _push(AstTestFactory.asExpression(expression, type));
            break;
          case UnlinkedExprOperation.typeCheck:
            Expression expression = _pop();
            TypeAnnotation type = _newTypeName();
            _push(AstTestFactory.isExpression(expression, false, type));
            break;
          case UnlinkedExprOperation.throwException:
            Expression expression = _pop();
            _push(AstTestFactory.throwExpression2(expression));
            break;
          case UnlinkedExprOperation.assignToProperty:
            Expression target = _pop();
            String name = uc.strings[stringPtr++];
            SimpleIdentifier propertyNode = AstTestFactory.identifier3(name);
            PropertyAccess propertyAccess =
                AstTestFactory.propertyAccess(target, propertyNode);
            _push(_createAssignment(propertyAccess));
            break;
          case UnlinkedExprOperation.assignToIndex:
            Expression index = _pop();
            Expression target = _pop();
            IndexExpression indexExpression =
                AstTestFactory.indexExpression(target, index);
            _push(_createAssignment(indexExpression));
            break;
          case UnlinkedExprOperation.extractIndex:
            Expression index = _pop();
            Expression target = _pop();
            _push(AstTestFactory.indexExpression(target, index));
            break;
          case UnlinkedExprOperation.pushSuper:
          case UnlinkedExprOperation.pushThis:
            throw const _InvalidConstantException(); // TODO(paulberry)
          case UnlinkedExprOperation.cascadeSectionBegin:
          case UnlinkedExprOperation.cascadeSectionEnd:
          case UnlinkedExprOperation.pushLocalFunctionReference:
          case UnlinkedExprOperation.pushError:
          case UnlinkedExprOperation.pushTypedAbstract:
          case UnlinkedExprOperation.pushUntypedAbstract:
            throw new UnimplementedError(
                'Unexpected $operation in a constant expression.');
        }
      }
    } on _InvalidConstantException {
      return AstTestFactory.identifier3(r'#invalidConst');
    }
    return stack.single;
  }

  List<Expression> _buildArguments() {
    List<Expression> arguments;
    {
      int numNamedArgs = uc.ints[intPtr++];
      int numPositionalArgs = uc.ints[intPtr++];
      int numArgs = numNamedArgs + numPositionalArgs;
      arguments = _removeTopItems(numArgs);
      // add names to the named arguments
      for (int i = 0; i < numNamedArgs; i++) {
        String name = uc.strings[stringPtr++];
        int index = numPositionalArgs + i;
        arguments[index] =
            AstTestFactory.namedExpression2(name, arguments[index]);
      }
    }
    return arguments;
  }

  /// Given the sequence of identifiers in [node], and the [classElement] or
  /// [constructorElement] to which this sequence resolves, build the
  /// [InstanceCreationExpression].
  InstanceCreationExpression _buildCreation(
    Expression node,
    TypeArgumentList typeArguments,
    ArgumentList argumentList, {
    ClassElement classElement,
    ConstructorElement constructorElement,
  }) {
    InstanceCreationExpression composeCreation(
        DartType type,
        ConstructorName constructorName,
        ConstructorElement constructorElement,
        ArgumentList argumentList) {
      TypeName typeName = constructorName.type;
      typeName.type = type;

      constructorName.name?.staticElement = constructorElement;

      var creation = astFactory.instanceCreationExpression(
          uc.isValidConst
              ? TokenFactory.tokenFromKeyword(Keyword.CONST)
              : TokenFactory.tokenFromKeyword(Keyword.NEW),
          constructorName,
          argumentList);

      creation.staticElement = constructorElement;
      creation.staticType = type;
      return creation;
    }

    classElement ??= constructorElement?.enclosingElement;
    var type = AstRewriteVisitor.getType(
        resynthesizer.typeSystem, classElement, typeArguments);

    // C()
    if (node is SimpleIdentifier && classElement != null) {
      constructorElement = type.lookUpConstructor('', resynthesizer.library);
      node.staticType = type;
      return composeCreation(
        type,
        astFactory.constructorName(
          astFactory.typeName(node, typeArguments),
          null,
          null,
        ),
        constructorElement,
        argumentList,
      );
    }
    if (node is PrefixedIdentifier) {
      // C.n()
      if (constructorElement != null) {
        constructorElement =
            type.lookUpConstructor(node.identifier.name, resynthesizer.library);
        node.prefix.staticType = type;
        return composeCreation(
          type,
          astFactory.constructorName(
            astFactory.typeName(node.prefix, typeArguments),
            TokenFactory.tokenFromType(TokenType.PERIOD),
            node.identifier,
          ),
          constructorElement,
          argumentList,
        );
      }
      // p.C()
      if (classElement != null) {
        constructorElement = type.lookUpConstructor('', resynthesizer.library);
        node.identifier.staticType = type;
        return composeCreation(
          type,
          astFactory.constructorName(
            astFactory.typeName(node.identifier, typeArguments),
            null,
            null,
          ),
          constructorElement,
          argumentList,
        );
      }
    }
    // p.C.n()
    if (node is PropertyAccess && constructorElement != null) {
      constructorElement =
          type.lookUpConstructor(node.propertyName.name, resynthesizer.library);
      var typeIdentifier = (node.target as PrefixedIdentifier).identifier;
      typeIdentifier.staticType = type;
      return composeCreation(
        type,
        astFactory.constructorName(
          astFactory.typeName(typeIdentifier, typeArguments),
          TokenFactory.tokenFromType(TokenType.PERIOD),
          node.propertyName,
        ),
        constructorElement,
        argumentList,
      );
    }

    throw new UnimplementedError('For ${node?.runtimeType}: $node; '
        'class: $classElement;  constructor: $constructorElement');
  }

  /**
   * Build the identifier sequence (a single or prefixed identifier, or a
   * property access) corresponding to the given reference [info].
   */
  Expression _buildIdentifierSequence(ReferenceInfo info) {
    Expression enclosing;
    if (info.enclosing != null) {
      enclosing = _buildIdentifierSequence(info.enclosing);
    }
    Element element = info.element;
    if (element == null && info.name == 'length') {
      element = _getStringLengthElement();
    }
    if (enclosing == null) {
      return AstTestFactory.identifier3(info.name)..staticElement = element;
    }
    if (enclosing is SimpleIdentifier) {
      SimpleIdentifier identifier = AstTestFactory.identifier3(info.name)
        ..staticElement = element;
      return AstTestFactory.identifier(enclosing, identifier);
    }
    if (requireValidConst && element == null) {
      throw const _InvalidConstantException();
    }
    SimpleIdentifier property = AstTestFactory.identifier3(info.name)
      ..staticElement = element;
    return AstTestFactory.propertyAccess(enclosing, property);
  }

  TypeArgumentList _buildTypeArguments() {
    int numTypeArguments = uc.ints[intPtr++];
    if (numTypeArguments == 0) {
      return null;
    }

    var typeNames = new List<TypeAnnotation>(numTypeArguments);
    for (int i = 0; i < numTypeArguments; i++) {
      typeNames[i] = _newTypeName();
    }
    return AstTestFactory.typeArgumentList(typeNames);
  }

  TypeAnnotation _buildTypeAst(DartType type) {
    List<TypeAnnotation> argumentNodes;
    if (type is ParameterizedType) {
      if (!resynthesizer.doesTypeHaveImplicitArguments(type)) {
        List<DartType> typeArguments = type.typeArguments;
        argumentNodes = typeArguments.every((a) => a.isDynamic)
            ? null
            : typeArguments.map(_buildTypeAst).toList();
      }
    }
    TypeName node = AstTestFactory.typeName4(type.name, argumentNodes);
    node.type = type;
    (node.name as SimpleIdentifier).staticElement = type.element;
    return node;
  }

  Expression _createAssignment(Expression lhs) {
    Expression binary(TokenType tokenType) {
      return AstTestFactory.assignmentExpression(lhs, tokenType, _pop());
    }

    Expression prefix(TokenType tokenType) {
      return AstTestFactory.prefixExpression(tokenType, lhs);
    }

    Expression postfix(TokenType tokenType) {
      return AstTestFactory.postfixExpression(lhs, tokenType);
    }

    switch (uc.assignmentOperators[assignmentOperatorPtr++]) {
      case UnlinkedExprAssignOperator.assign:
        return binary(TokenType.EQ);
      case UnlinkedExprAssignOperator.ifNull:
        return binary(TokenType.QUESTION_QUESTION_EQ);
      case UnlinkedExprAssignOperator.multiply:
        return binary(TokenType.STAR_EQ);
      case UnlinkedExprAssignOperator.divide:
        return binary(TokenType.SLASH_EQ);
      case UnlinkedExprAssignOperator.floorDivide:
        return binary(TokenType.TILDE_SLASH_EQ);
      case UnlinkedExprAssignOperator.modulo:
        return binary(TokenType.PERCENT_EQ);
      case UnlinkedExprAssignOperator.plus:
        return binary(TokenType.PLUS_EQ);
      case UnlinkedExprAssignOperator.minus:
        return binary(TokenType.MINUS_EQ);
      case UnlinkedExprAssignOperator.shiftLeft:
        return binary(TokenType.LT_LT_EQ);
      case UnlinkedExprAssignOperator.shiftRight:
        return binary(TokenType.GT_GT_EQ);
      case UnlinkedExprAssignOperator.bitAnd:
        return binary(TokenType.AMPERSAND_EQ);
      case UnlinkedExprAssignOperator.bitXor:
        return binary(TokenType.CARET_EQ);
      case UnlinkedExprAssignOperator.bitOr:
        return binary(TokenType.BAR_EQ);
      case UnlinkedExprAssignOperator.prefixIncrement:
        return prefix(TokenType.PLUS_PLUS);
      case UnlinkedExprAssignOperator.prefixDecrement:
        return prefix(TokenType.MINUS_MINUS);
      case UnlinkedExprAssignOperator.postfixIncrement:
        return postfix(TokenType.PLUS_PLUS);
      case UnlinkedExprAssignOperator.postfixDecrement:
        return postfix(TokenType.MINUS_MINUS);
      default:
        throw new UnimplementedError('Unexpected UnlinkedExprAssignOperator');
    }
  }

  Expression _createReference() {
    EntityRef ref = uc.references[refPtr++];
    ReferenceInfo info = resynthesizer.getReferenceInfo(ref.reference);
    Expression node = _buildIdentifierSequence(info);
    if (requireValidConst && node is Identifier && node.staticElement == null) {
      throw const _InvalidConstantException();
    }
    return node;
  }

  PropertyAccessorElement _getStringLengthElement() =>
      resynthesizer.typeProvider.stringType.getGetter('length');

  FormalParameter _makeParameter(ParameterElement param) {
    SimpleFormalParameterImpl simpleParam =
        AstTestFactory.simpleFormalParameter(null, param.name);
    simpleParam.identifier.staticElement = param;
    simpleParam.declaredElement = param;
    var unlinkedParam = (param as ParameterElementImpl).unlinkedParam;
    if (unlinkedParam.kind == UnlinkedParamKind.positional) {
      return AstTestFactory.positionalFormalParameter(simpleParam, null);
    } else if (unlinkedParam.kind == UnlinkedParamKind.named) {
      return AstTestFactory.namedFormalParameter(simpleParam, null);
    } else {
      return simpleParam;
    }
  }

  InterpolationElement _newInterpolationElement(Expression expr) {
    if (expr is SimpleStringLiteral) {
      return astFactory.interpolationString(expr.literal, expr.value);
    } else {
      return astFactory.interpolationExpression(
          TokenFactory.tokenFromType(TokenType.STRING_INTERPOLATION_EXPRESSION),
          expr,
          TokenFactory.tokenFromType(TokenType.CLOSE_CURLY_BRACKET));
    }
  }

  /**
   * Convert the next reference to the [DartType] and return the AST
   * corresponding to this type.
   */
  TypeAnnotation _newTypeName() {
    EntityRef typeRef = uc.references[refPtr++];
    DartType type = resynthesizer.buildType(context, typeRef);
    return _buildTypeAst(type);
  }

  Expression _pop() => stack.removeLast();

  void _push(Expression expr) {
    stack.add(expr);
  }

  void _pushBinary(TokenType operator) {
    Expression right = _pop();
    Expression left = _pop();
    _push(AstTestFactory.binaryExpression(left, operator, right));
  }

  void _pushExtractProperty() {
    Expression target = _pop();
    String name = uc.strings[stringPtr++];
    SimpleIdentifier propertyNode = AstTestFactory.identifier3(name);
    // Only String.length property access can be potentially resolved.
    if (name == 'length') {
      propertyNode.staticElement = _getStringLengthElement();
    }
    _push(AstTestFactory.propertyAccess(target, propertyNode));
  }

  void _pushInstanceCreation() {
    EntityRef ref = uc.references[refPtr++];
    ReferenceInfo info = resynthesizer.getReferenceInfo(ref.reference);
    // prepare ConstructorElement
    TypeName typeNode;
    String constructorName;
    ConstructorElement constructorElement;
    if (info.element != null) {
      if (info.element is ConstructorElement) {
        constructorName = info.name;
      } else if (info.element is ClassElement) {
        constructorName = null;
      } else {
        List<Expression> arguments = _buildArguments();
        SimpleIdentifier name = AstTestFactory.identifier3(info.name);
        name.staticElement = info.element;
        name.setProperty(ARGUMENT_LIST, AstTestFactory.argumentList(arguments));
        _push(name);
        return;
      }
      InterfaceType definingType = resynthesizer.createConstructorDefiningType(
          context, info, ref.typeArguments);
      constructorElement =
          resynthesizer.getConstructorForInfo(definingType, info);
      typeNode = _buildTypeAst(definingType);
    } else {
      if (info.enclosing != null) {
        if (info.enclosing.enclosing != null) {
          PrefixedIdentifier typeName = AstTestFactory.identifier5(
              info.enclosing.enclosing.name, info.enclosing.name);
          typeName.prefix.staticElement = info.enclosing.enclosing.element;
          typeName.identifier.staticElement = info.enclosing.element;
          typeName.identifier.staticType = info.enclosing.type;
          typeNode = AstTestFactory.typeName3(typeName);
          typeNode.type = info.enclosing.type;
          constructorName = info.name;
        } else if (info.enclosing.element != null) {
          SimpleIdentifier typeName =
              AstTestFactory.identifier3(info.enclosing.name);
          typeName.staticElement = info.enclosing.element;
          typeName.staticType = info.enclosing.type;
          typeNode = AstTestFactory.typeName3(typeName);
          typeNode.type = info.enclosing.type;
          constructorName = info.name;
        } else {
          typeNode = AstTestFactory.typeName3(
              AstTestFactory.identifier5(info.enclosing.name, info.name));
          constructorName = null;
        }
      } else {
        typeNode = AstTestFactory.typeName4(info.name);
      }
    }
    // prepare arguments
    List<Expression> arguments = _buildArguments();
    // create ConstructorName
    ConstructorName constructorNode;
    if (constructorName != null) {
      constructorNode =
          AstTestFactory.constructorName(typeNode, constructorName);
      constructorNode.name.staticElement = constructorElement;
    } else {
      constructorNode = AstTestFactory.constructorName(typeNode, null);
    }
    constructorNode.staticElement = constructorElement;
    if (constructorElement == null) {
      throw const _InvalidConstantException();
    }
    // create InstanceCreationExpression
    InstanceCreationExpression instanceCreation =
        AstTestFactory.instanceCreationExpression(
            requireValidConst ? Keyword.CONST : Keyword.NEW,
            constructorNode,
            arguments);
    instanceCreation.staticElement = constructorElement;
    _push(instanceCreation);
  }

  void _pushInvokeMethodRef() {
    List<Expression> arguments = _buildArguments();
    EntityRef ref = uc.references[refPtr++];
    ReferenceInfo info = resynthesizer.getReferenceInfo(ref.reference);
    Expression node = _buildIdentifierSequence(info);
    TypeArgumentList typeArguments = _buildTypeArguments();
    var period = TokenFactory.tokenFromType(TokenType.PERIOD);
    var argumentList = AstTestFactory.argumentList(arguments);

    // Check for optional new/const.
    if (info.element is ClassElement) {
      _push(_buildCreation(node, typeArguments, argumentList,
          classElement: info.element));
      return;
    }
    if (info.element is ConstructorElement) {
      _push(_buildCreation(node, typeArguments, argumentList,
          constructorElement: info.element));
      return;
    }

    if (node is SimpleIdentifier) {
      _push(astFactory.methodInvocation(
          null, period, node, typeArguments, argumentList));
    } else if (node is PropertyAccess) {
      _push(astFactory.methodInvocation(
          node.target, period, node.propertyName, typeArguments, argumentList));
    } else if (node is PrefixedIdentifier) {
      _push(astFactory.methodInvocation(
          node.prefix, period, node.identifier, typeArguments, argumentList));
    } else {
      throw new UnimplementedError('For ${node?.runtimeType}: $node');
    }
  }

  void _pushList(TypeArgumentList typeArguments) {
    int count = uc.ints[intPtr++];
    List<Expression> elements = <Expression>[];
    for (int i = 0; i < count; i++) {
      elements.insert(0, _pop());
    }
    var typeArg = typeArguments == null
        ? resynthesizer.typeProvider.dynamicType
        : typeArguments.arguments[0].type;
    var staticType = resynthesizer.typeProvider.listType.instantiate([typeArg]);
    _push(AstTestFactory.listLiteral2(Keyword.CONST, typeArguments, elements)
      ..staticType = staticType);
  }

  void _pushLocalFunctionReference() {
    _throwIfConst();
    int popCount = uc.ints[intPtr++];
    // Note: nonzero popCount is no longer used.
    assert(popCount == 0);
    int functionIndex = uc.ints[intPtr++];
    var localFunction = localFunctions[functionIndex];
    var parametersInScope =
        new Map<String, ParameterElement>.from(this.parametersInScope);
    var functionElement =
        new FunctionElementImpl.forSerialized(localFunction, context);
    for (ParameterElementImpl parameter in functionElement.parameters) {
      parametersInScope[parameter.name] = parameter;
      if (parameter.unlinkedParam.type == null) {
        // Store a type of `dynamic` for the parameter; this prevents
        // resynthesis from trying to read a type out of the summary (which
        // wouldn't work anyway, since nested functions don't have their
        // parameter types stored in the summary anyhow).
        parameter.type = resynthesizer.typeProvider.dynamicType;
      }
    }
    var parameters = functionElement.parameters.map(_makeParameter).toList();
    var asyncKeyword = localFunction.isAsynchronous
        ? TokenFactory.tokenFromKeyword(Keyword.ASYNC)
        : null;
    FunctionBody functionBody;
    if (localFunction.bodyExpr == null) {
      // Most likely the original source code contained a block function body
      // here.  Block function bodies aren't supported by the summary mechanism.
      // But they are tolerated when their presence doesn't affect inferred
      // types.
      functionBody = AstTestFactory.blockFunctionBody(AstTestFactory.block());
    } else {
      var bodyExpr = new ExprBuilder(
              resynthesizer, functionElement, localFunction.bodyExpr,
              requireValidConst: requireValidConst,
              parametersInScope: parametersInScope,
              localFunctions: localFunction.localFunctions)
          .build();
      functionBody = astFactory.expressionFunctionBody(asyncKeyword,
          TokenFactory.tokenFromType(TokenType.FUNCTION), bodyExpr, null);
    }
    var functionExpression = astFactory.functionExpression(
        null, AstTestFactory.formalParameterList(parameters), functionBody);
    functionExpression.element = functionElement;
    _push(functionExpression);
  }

  void _pushMap(TypeArgumentList typeArguments) {
    int count = uc.ints[intPtr++];
    List<MapLiteralEntry> entries = <MapLiteralEntry>[];
    for (int i = 0; i < count; i++) {
      Expression value = _pop();
      Expression key = _pop();
      entries.insert(0, AstTestFactory.mapLiteralEntry2(key, value));
    }
    var keyType = typeArguments == null
        ? resynthesizer.typeProvider.dynamicType
        : typeArguments.arguments[0].type;
    var valueType = typeArguments == null
        ? resynthesizer.typeProvider.dynamicType
        : typeArguments.arguments[1].type;
    var staticType =
        resynthesizer.typeProvider.mapType.instantiate([keyType, valueType]);
    _push(AstTestFactory.mapLiteral(Keyword.CONST, typeArguments, entries)
      ..staticType = staticType);
  }

  void _pushPrefix(TokenType operator) {
    Expression operand = _pop();
    _push(AstTestFactory.prefixExpression(operator, operand));
  }

  void _pushReference() {
    _push(_createReference());
  }

  List<Expression> _removeTopItems(int count) {
    int start = stack.length - count;
    int end = stack.length;
    List<Expression> items = stack.getRange(start, end).toList();
    stack.removeRange(start, end);
    return items;
  }

  void _throwIfConst() {
    if (requireValidConst) {
      throw const _InvalidConstantException();
    }
  }

  /// Figures out the default value of [parametersInScope] based on [context].
  ///
  /// If [context] is (or contains) a constructor, then its parameters are used.
  /// Otherwise, no parameters are considered to be in scope.
  static Map<String, ParameterElement> _parametersInScope(Element context) {
    var result = <String, ParameterElement>{};
    for (Element e = context; e != null; e = e.enclosingElement) {
      if (e is ConstructorElement) {
        for (var parameter in e.parameters) {
          result[parameter.name] = parameter;
        }
        return result;
      }
    }
    return result;
  }
}

/**
 * This exception is thrown when we detect that the constant expression
 * being resynthesized is not a valid constant expression.
 */
class _InvalidConstantException {
  const _InvalidConstantException();
}
