// Copyright (c) 2016, 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/token.dart';
import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/idl.dart';

/// Serialize the given constructor initializer [node].
UnlinkedConstructorInitializerBuilder serializeConstructorInitializer(
    ConstructorInitializer node,
    UnlinkedExprBuilder serializeConstExpr(Expression expr)) {
  if (node is ConstructorFieldInitializer) {
    return new UnlinkedConstructorInitializerBuilder(
        kind: UnlinkedConstructorInitializerKind.field,
        name: node.fieldName.name,
        expression: serializeConstExpr(node.expression));
  }

  List<UnlinkedExprBuilder> arguments = <UnlinkedExprBuilder>[];
  List<String> argumentNames = <String>[];
  void serializeArguments(List<Expression> args) {
    for (Expression arg in args) {
      if (arg is NamedExpression) {
        NamedExpression namedExpression = arg;
        argumentNames.add(namedExpression.name.label.name);
        arg = namedExpression.expression;
      }
      arguments.add(serializeConstExpr(arg));
    }
  }

  if (node is AssertInitializer) {
    serializeArguments(node.message != null
        ? [node.condition, node.message]
        : [node.condition]);
    return new UnlinkedConstructorInitializerBuilder(
        kind: UnlinkedConstructorInitializerKind.assertInvocation,
        arguments: arguments);
  }
  if (node is RedirectingConstructorInvocation) {
    serializeArguments(node.argumentList.arguments);
    return new UnlinkedConstructorInitializerBuilder(
        kind: UnlinkedConstructorInitializerKind.thisInvocation,
        name: node?.constructorName?.name,
        arguments: arguments,
        argumentNames: argumentNames);
  }
  if (node is SuperConstructorInvocation) {
    serializeArguments(node.argumentList.arguments);
    return new UnlinkedConstructorInitializerBuilder(
        kind: UnlinkedConstructorInitializerKind.superInvocation,
        name: node?.constructorName?.name,
        arguments: arguments,
        argumentNames: argumentNames);
  }
  throw new StateError('Unexpected initializer type ${node.runtimeType}');
}

/// Converts all the tokens between [startToken] and [endToken] (inclusive) into
/// a string which, when scanned, will yield the same tokens back.
String tokensToString(Token startToken, Token endToken) {
  var buffer = StringBuffer();
  var token = startToken;
  var spaceNeeded = false;
  while (true) {
    if (token.type == TokenType.STRING_INTERPOLATION_EXPRESSION) {
      buffer.write(token.lexeme);
      buffer.write(tokensToString(token.next, token.endGroup));
      spaceNeeded = false;
      token = token.endGroup;
    } else if (token.type == TokenType.STRING_INTERPOLATION_IDENTIFIER) {
      buffer.write(token.lexeme);
      buffer.write(token.next.lexeme);
      spaceNeeded = false;
      token = token.next;
    } else {
      if (spaceNeeded) buffer.write(' ');
      buffer.write(token.lexeme);
      spaceNeeded = true;
    }
    if (identical(token, endToken)) break;
    token = token.next;
  }
  return buffer.toString();
}

/// Instances of this class keep track of intermediate state during
/// serialization of a single constant [Expression].
abstract class AbstractConstExprSerializer {
  /// Whether an expression that should be a constant is being serialized.
  ///
  /// For constants we need to store more than we need just for type inference,
  /// because we need to be able to restore these AST to evaluate actual values
  /// of constants. So, we need to store constructor arguments, elements for
  /// list and map literals even if these literals are typed.
  final bool forConst;

  /// See [UnlinkedExprBuilder.isValidConst].
  bool isValidConst = true;

  /// See [UnlinkedExprBuilder.name].
  String name = null;

  /// See [UnlinkedExprBuilder.operations].
  final List<UnlinkedExprOperation> operations = <UnlinkedExprOperation>[];

  /// See [UnlinkedExprBuilder.assignmentOperators].
  final List<UnlinkedExprAssignOperator> assignmentOperators =
      <UnlinkedExprAssignOperator>[];

  /// See [UnlinkedExprBuilder.ints].
  final List<int> ints = <int>[];

  /// See [UnlinkedExprBuilder.doubles].
  final List<double> doubles = <double>[];

  /// See [UnlinkedExprBuilder.strings].
  final List<String> strings = <String>[];

  /// See [UnlinkedExprBuilder.references].
  final List<EntityRefBuilder> references = <EntityRefBuilder>[];

  AbstractConstExprSerializer(this.forConst);

  /// Return `true` if the given [name] is a parameter reference.
  bool isParameterName(String name);

  /// Removes the [count] variables that were most recently added to the scope
  /// by [pushVariableName].
  void popVariableNames(int count);

  /// Pushes a variable with the given [name] onto the current scope.
  void pushVariableName(String name);

  /// Serialize the given [expr] expression into this serializer state.
  void serialize(Expression expr) {
    try {
      if (expr is NamedExpression) {
        NamedExpression namedExpression = expr;
        name = namedExpression.name.label.name;
        expr = namedExpression.expression;
      }
      _serialize(expr);
    } on StateError {
      isValidConst = false;
      operations.clear();
      assignmentOperators.clear();
      ints.clear();
      doubles.clear();
      strings.clear();
      references.clear();
    }
  }

  /// Serialize the given [annotation] into this serializer state.
  void serializeAnnotation(Annotation annotation);

  /// Return [EntityRefBuilder] that corresponds to the constructor having name
  /// [name] in the class identified by [typeName].
  EntityRefBuilder serializeConstructorRef(Identifier typeName,
      TypeArgumentList typeArguments, SimpleIdentifier name);

  /// Return a pair of ints showing how the given [functionExpression] is nested
  /// within the constant currently being serialized.  The first int indicates
  /// how many levels of function nesting must be popped in order to reach the
  /// parent of the [functionExpression].  The second int is the index of the
  /// [functionExpression] within its parent element.
  ///
  /// If the constant being summarized is in a context where local function
  /// references are not allowed, return `null`.
  List<int> serializeFunctionExpression(FunctionExpression functionExpression);

  /// Return [EntityRefBuilder] that corresponds to the [type], which is defined
  /// using generic function type syntax. These may appear as the type arguments
  /// of a const list, etc.
  EntityRefBuilder serializeGenericFunctionType(GenericFunctionType type);

  /// Return [EntityRefBuilder] that corresponds to the given [identifier].
  EntityRefBuilder serializeIdentifier(Identifier identifier);

  /// Return [EntityRefBuilder] that corresponds to the given [expr], which
  /// must be a sequence of identifiers.
  EntityRefBuilder serializeIdentifierSequence(Expression expr);

  void serializeInstanceCreation(EntityRefBuilder constructor,
      ArgumentList argumentList, bool typeArgumentsProvided) {
    _serializeArguments(argumentList, typeArgumentsProvided);
    references.add(constructor);
    operations.add(UnlinkedExprOperation.invokeConstructor);
  }

  /// Return [EntityRefBuilder] that corresponds to the given [type].
  EntityRefBuilder serializeType(TypeAnnotation type) {
    if (type is TypeName) {
      return serializeTypeName(type?.name, type?.typeArguments);
    }
    if (type is GenericFunctionType) {
      return serializeGenericFunctionType(type);
    }
    throw new ArgumentError(
        'Cannot serialize an instance of ${type.runtimeType}');
  }

  /// Return [EntityRefBuilder] that corresponds to the type with the given
  /// [name] and [arguments].
  EntityRefBuilder serializeTypeName(
      Identifier name, TypeArgumentList arguments);

  /// Return the [UnlinkedExprBuilder] that corresponds to the state of this
  /// serializer.
  UnlinkedExprBuilder toBuilder(Token startToken, Token endToken) {
    return new UnlinkedExprBuilder(
        isValidConst: isValidConst,
        operations: operations,
        assignmentOperators: assignmentOperators,
        ints: ints,
        doubles: doubles,
        strings: strings,
        references: references,
        sourceRepresentation: tokensToString(startToken, endToken));
  }

  /// Return `true` if the given [expr] is a sequence of identifiers.
  bool _isIdentifierSequence(Expression expr) {
    while (expr != null) {
      if (expr is SimpleIdentifier) {
        AstNode parent = expr.parent;
        if (parent is MethodInvocation && parent.methodName == expr) {
          if (parent.isCascaded) {
            return false;
          }
          return parent.target == null || _isIdentifierSequence(parent.target);
        }
        if (isParameterName(expr.name)) {
          return false;
        }
        return true;
      } else if (expr is PrefixedIdentifier) {
        expr = (expr as PrefixedIdentifier).prefix;
      } else if (expr is PropertyAccess) {
        expr = (expr as PropertyAccess).target;
      } else {
        return false;
      }
    }
    return false;
  }

  /// Push the operation for the given assignable [expr].
  void _pushAssignable(Expression expr) {
    if (_isIdentifierSequence(expr)) {
      EntityRefBuilder ref = serializeIdentifierSequence(expr);
      references.add(ref);
      operations.add(UnlinkedExprOperation.assignToRef);
    } else if (expr is SimpleIdentifier && isParameterName(expr.name)) {
      strings.add(expr.name);
      operations.add(UnlinkedExprOperation.assignToParameter);
    } else if (expr is PropertyAccess) {
      if (!expr.isCascaded) {
        _serialize(expr.target);
      }
      strings.add(expr.propertyName.name);
      operations.add(UnlinkedExprOperation.assignToProperty);
    } else if (expr is IndexExpression) {
      if (!expr.isCascaded) {
        _serialize(expr.target);
      }
      _serialize(expr.index);
      operations.add(UnlinkedExprOperation.assignToIndex);
    } else if (expr is PrefixedIdentifier) {
      strings.add(expr.prefix.name);
      operations.add(UnlinkedExprOperation.pushParameter);
      strings.add(expr.identifier.name);
      operations.add(UnlinkedExprOperation.assignToProperty);
    } else {
      throw new StateError('Unsupported assignable: $expr');
    }
  }

  void _pushInt(int value) {
    value ??= 0;
    assert(value >= 0);
    if (value >= 0x100000000) {
      int numOfComponents = 0;
      ints.add(numOfComponents);
      void pushComponents(int value) {
        if (value >= 0x100000000) {
          pushComponents(value ~/ 0x100000000);
        }
        numOfComponents++;
        ints.add(value & 0xFFFFFFFF);
      }

      pushComponents(value);
      ints[ints.length - 1 - numOfComponents] = numOfComponents;
      operations.add(UnlinkedExprOperation.pushLongInt);
    } else {
      operations.add(UnlinkedExprOperation.pushInt);
      ints.add(value);
    }
  }

  /// Serialize the given [expr] expression into this serializer state.
  void _serialize(Expression expr, {bool emptyExpressionPermitted: false}) {
    if (emptyExpressionPermitted && expr == null) {
      operations.add(UnlinkedExprOperation.pushEmptyExpression);
    } else if (expr is IntegerLiteral) {
      int value = expr.value ?? 0;
      if (value >= 0) {
        _pushInt(value);
      } else {
        _pushInt(-value);
        operations.add(UnlinkedExprOperation.negate);
      }
    } else if (expr is DoubleLiteral) {
      operations.add(UnlinkedExprOperation.pushDouble);
      doubles.add(expr.value);
    } else if (expr is BooleanLiteral) {
      if (expr.value) {
        operations.add(UnlinkedExprOperation.pushTrue);
      } else {
        operations.add(UnlinkedExprOperation.pushFalse);
      }
    } else if (expr is StringLiteral) {
      _serializeString(expr);
    } else if (expr is SymbolLiteral) {
      strings.add(expr.components.map((token) => token.lexeme).join('.'));
      operations.add(UnlinkedExprOperation.makeSymbol);
    } else if (expr is NullLiteral) {
      operations.add(UnlinkedExprOperation.pushNull);
    } else if (expr is Identifier) {
      if (expr is SimpleIdentifier && isParameterName(expr.name)) {
        strings.add(expr.name);
        operations.add(UnlinkedExprOperation.pushParameter);
      } else if (expr is PrefixedIdentifier &&
          isParameterName(expr.prefix.name)) {
        strings.add(expr.prefix.name);
        operations.add(UnlinkedExprOperation.pushParameter);
        strings.add(expr.identifier.name);
        operations.add(UnlinkedExprOperation.extractProperty);
      } else {
        references.add(serializeIdentifier(expr));
        operations.add(UnlinkedExprOperation.pushReference);
      }
    } else if (expr is InstanceCreationExpression) {
      if (!expr.isConst) {
        isValidConst = false;
      }
      TypeName typeName = expr.constructorName.type;
      serializeInstanceCreation(
          serializeConstructorRef(
              typeName.name, typeName.typeArguments, expr.constructorName.name),
          expr.argumentList,
          typeName.typeArguments != null);
    } else if (expr is ListLiteral) {
      _serializeListLiteral(expr);
    } else if (expr is SetOrMapLiteral) {
      _serializeSetOrMapLiteral(expr);
    } else if (expr is MethodInvocation) {
      _serializeMethodInvocation(expr);
    } else if (expr is BinaryExpression) {
      _serializeBinaryExpression(expr);
    } else if (expr is ConditionalExpression) {
      _serialize(expr.condition);
      _serialize(expr.thenExpression);
      _serialize(expr.elseExpression);
      operations.add(UnlinkedExprOperation.conditional);
    } else if (expr is PrefixExpression) {
      _serializePrefixExpression(expr);
    } else if (expr is PostfixExpression) {
      _serializePostfixExpression(expr);
    } else if (expr is PropertyAccess) {
      _serializePropertyAccess(expr);
    } else if (expr is ParenthesizedExpression) {
      _serialize(expr.expression);
    } else if (expr is IndexExpression) {
      isValidConst = false;
      _serialize(expr.target);
      _serialize(expr.index);
      operations.add(UnlinkedExprOperation.extractIndex);
    } else if (expr is AssignmentExpression) {
      _serializeAssignment(expr);
    } else if (expr is CascadeExpression) {
      isValidConst = false;
      _serialize(expr.target);
    } else if (expr is FunctionExpression) {
      isValidConst = false;
      List<int> indices = serializeFunctionExpression(expr);
      if (indices != null) {
        ints.addAll(serializeFunctionExpression(expr));
        operations.add(UnlinkedExprOperation.pushLocalFunctionReference);
      } else {
        // Invalid expression; just push null.
        operations.add(UnlinkedExprOperation.pushNull);
      }
    } else if (expr is FunctionExpressionInvocation) {
      isValidConst = false;
      _serialize(expr.function);
      _serializeArguments(expr.argumentList, expr.typeArguments != null);
      strings.add('call');
      _serializeTypeArguments(expr.typeArguments);
      operations.add(UnlinkedExprOperation.invokeMethod);
    } else if (expr is AsExpression) {
      isValidConst = false;
      _serialize(expr.expression);
      references.add(serializeType(expr.type));
      operations.add(UnlinkedExprOperation.typeCast);
    } else if (expr is IsExpression) {
      isValidConst = false;
      _serialize(expr.expression);
      references.add(serializeType(expr.type));
      operations.add(UnlinkedExprOperation.typeCheck);
      if (expr.notOperator != null) {
        operations.add(UnlinkedExprOperation.not);
      }
    } else if (expr is SuperExpression) {
      operations.add(UnlinkedExprOperation.pushSuper);
    } else if (expr is ThisExpression) {
      operations.add(UnlinkedExprOperation.pushThis);
    } else if (expr is ThrowExpression) {
      isValidConst = false;
      _serialize(expr.expression);
      operations.add(UnlinkedExprOperation.throwException);
    } else if (expr is AwaitExpression) {
      isValidConst = false;
      _serialize(expr.expression);
      operations.add(UnlinkedExprOperation.await);
    } else {
      throw new StateError('Unknown expression type: $expr');
    }
  }

  void _serializeArguments(
      ArgumentList argumentList, bool typeArgumentsProvided) {
    if (forConst || !typeArgumentsProvided) {
      List<Expression> arguments = argumentList.arguments;
      // Serialize the arguments.
      List<String> argumentNames = <String>[];
      arguments.forEach((arg) {
        if (arg is NamedExpression) {
          argumentNames.add(arg.name.label.name);
          _serialize(arg.expression);
        } else {
          _serialize(arg);
        }
      });
      // Add numbers of named and positional arguments, and the op-code.
      ints.add(argumentNames.length);
      strings.addAll(argumentNames);
      ints.add(arguments.length - argumentNames.length);
    } else {
      ints.add(0);
      ints.add(0);
    }
  }

  void _serializeAssignment(AssignmentExpression expr) {
    isValidConst = false;
    // Push the value.
    _serialize(expr.rightHandSide);
    // Push the assignment operator.
    TokenType operator = expr.operator.type;
    UnlinkedExprAssignOperator assignmentOperator;
    if (operator == TokenType.EQ) {
      assignmentOperator = UnlinkedExprAssignOperator.assign;
    } else if (operator == TokenType.QUESTION_QUESTION_EQ) {
      assignmentOperator = UnlinkedExprAssignOperator.ifNull;
    } else if (operator == TokenType.STAR_EQ) {
      assignmentOperator = UnlinkedExprAssignOperator.multiply;
    } else if (operator == TokenType.SLASH_EQ) {
      assignmentOperator = UnlinkedExprAssignOperator.divide;
    } else if (operator == TokenType.TILDE_SLASH_EQ) {
      assignmentOperator = UnlinkedExprAssignOperator.floorDivide;
    } else if (operator == TokenType.PERCENT_EQ) {
      assignmentOperator = UnlinkedExprAssignOperator.modulo;
    } else if (operator == TokenType.PLUS_EQ) {
      assignmentOperator = UnlinkedExprAssignOperator.plus;
    } else if (operator == TokenType.MINUS_EQ) {
      assignmentOperator = UnlinkedExprAssignOperator.minus;
    } else if (operator == TokenType.LT_LT_EQ) {
      assignmentOperator = UnlinkedExprAssignOperator.shiftLeft;
    } else if (operator == TokenType.GT_GT_EQ) {
      assignmentOperator = UnlinkedExprAssignOperator.shiftRight;
    } else if (operator == TokenType.AMPERSAND_EQ) {
      assignmentOperator = UnlinkedExprAssignOperator.bitAnd;
    } else if (operator == TokenType.CARET_EQ) {
      assignmentOperator = UnlinkedExprAssignOperator.bitXor;
    } else if (operator == TokenType.BAR_EQ) {
      assignmentOperator = UnlinkedExprAssignOperator.bitOr;
    } else {
      throw new StateError('Unknown assignment operator: $operator');
    }
    assignmentOperators.add(assignmentOperator);
    // Push the assignment to the LHS.
    _pushAssignable(expr.leftHandSide);
  }

  void _serializeBinaryExpression(BinaryExpression expr) {
    _serialize(expr.leftOperand);
    _serialize(expr.rightOperand);
    TokenType operator = expr.operator.type;
    if (operator == TokenType.EQ_EQ) {
      operations.add(UnlinkedExprOperation.equal);
    } else if (operator == TokenType.BANG_EQ) {
      operations.add(UnlinkedExprOperation.notEqual);
    } else if (operator == TokenType.AMPERSAND_AMPERSAND) {
      operations.add(UnlinkedExprOperation.and);
    } else if (operator == TokenType.BAR_BAR) {
      operations.add(UnlinkedExprOperation.or);
    } else if (operator == TokenType.CARET) {
      operations.add(UnlinkedExprOperation.bitXor);
    } else if (operator == TokenType.AMPERSAND) {
      operations.add(UnlinkedExprOperation.bitAnd);
    } else if (operator == TokenType.BAR) {
      operations.add(UnlinkedExprOperation.bitOr);
    } else if (operator == TokenType.GT_GT) {
      operations.add(UnlinkedExprOperation.bitShiftRight);
    } else if (operator == TokenType.LT_LT) {
      operations.add(UnlinkedExprOperation.bitShiftLeft);
    } else if (operator == TokenType.PLUS) {
      operations.add(UnlinkedExprOperation.add);
    } else if (operator == TokenType.MINUS) {
      operations.add(UnlinkedExprOperation.subtract);
    } else if (operator == TokenType.STAR) {
      operations.add(UnlinkedExprOperation.multiply);
    } else if (operator == TokenType.SLASH) {
      operations.add(UnlinkedExprOperation.divide);
    } else if (operator == TokenType.TILDE_SLASH) {
      operations.add(UnlinkedExprOperation.floorDivide);
    } else if (operator == TokenType.GT) {
      operations.add(UnlinkedExprOperation.greater);
    } else if (operator == TokenType.LT) {
      operations.add(UnlinkedExprOperation.less);
    } else if (operator == TokenType.GT_EQ) {
      operations.add(UnlinkedExprOperation.greaterEqual);
    } else if (operator == TokenType.LT_EQ) {
      operations.add(UnlinkedExprOperation.lessEqual);
    } else if (operator == TokenType.PERCENT) {
      operations.add(UnlinkedExprOperation.modulo);
    } else if (operator == TokenType.QUESTION_QUESTION) {
      operations.add(UnlinkedExprOperation.ifNull);
    } else {
      throw new StateError('Unknown operator: $operator');
    }
  }

  void _serializeCollectionElement(CollectionElement element) {
    if (element is Expression) {
      _serialize(element);
    } else if (element is MapLiteralEntry) {
      _serialize(element.key);
      _serialize(element.value);
      operations.add(UnlinkedExprOperation.makeMapLiteralEntry);
    } else if (element is SpreadElement) {
      _serialize(element.expression);
      bool isNullAware = element.spreadOperator.type ==
          TokenType.PERIOD_PERIOD_PERIOD_QUESTION;
      operations.add(isNullAware
          ? UnlinkedExprOperation.nullAwareSpreadElement
          : UnlinkedExprOperation.spreadElement);
    } else if (element is IfElement) {
      _serialize(element.condition);
      _serializeCollectionElement(element.thenElement);
      var elseElement = element.elseElement;
      if (elseElement == null) {
        operations.add(UnlinkedExprOperation.ifElement);
      } else {
        _serializeCollectionElement(elseElement);
        operations.add(UnlinkedExprOperation.ifElseElement);
      }
    } else if (element is ForElement) {
      isValidConst = false;
      var parts = element.forLoopParts;
      int numVariablesToPop = 0;
      if (parts is ForParts) {
        if (parts is ForPartsWithExpression) {
          _serialize(parts.initialization, emptyExpressionPermitted: true);
        } else if (parts is ForPartsWithDeclarations) {
          for (var variable in parts.variables.variables) {
            operations.add(UnlinkedExprOperation.variableDeclarationStart);
            var name = variable.name.name;
            strings.add(name);
            pushVariableName(name);
            ++numVariablesToPop;
            _serialize(variable.initializer, emptyExpressionPermitted: true);
            operations.add(UnlinkedExprOperation.variableDeclaration);
            ints.add(0);
          }
          var type = parts.variables.type;
          if (type == null) {
            operations
                .add(UnlinkedExprOperation.forInitializerDeclarationsUntyped);
          } else {
            references.add(serializeType(type));
            operations
                .add(UnlinkedExprOperation.forInitializerDeclarationsTyped);
          }
          ints.add(parts.variables.variables.length);
        } else {
          throw StateError('Unrecognized for parts');
        }
        _serialize(parts.condition, emptyExpressionPermitted: true);
        for (var updater in parts.updaters) {
          _serialize(updater);
        }
        operations.add(UnlinkedExprOperation.forParts);
        ints.add(parts.updaters.length);
      } else if (parts is ForEachParts) {
        if (parts is ForEachPartsWithIdentifier) {
          _serialize(parts.identifier);
          _serialize(parts.iterable);
          operations.add(UnlinkedExprOperation.forEachPartsWithIdentifier);
        } else if (parts is ForEachPartsWithDeclaration) {
          _serialize(parts.iterable);
          var type = parts.loopVariable.type;
          if (type == null) {
            operations
                .add(UnlinkedExprOperation.forEachPartsWithUntypedDeclaration);
          } else {
            references.add(serializeType(type));
            operations
                .add(UnlinkedExprOperation.forEachPartsWithTypedDeclaration);
          }
          var name = parts.loopVariable.identifier.name;
          strings.add(name);
          pushVariableName(name);
          ++numVariablesToPop;
        } else {
          throw StateError('Unrecognized for parts');
        }
      } else {
        throw StateError('Unrecognized for parts');
      }
      _serializeCollectionElement(element.body);
      popVariableNames(numVariablesToPop);
      operations.add(element.awaitKeyword == null
          ? UnlinkedExprOperation.forElement
          : UnlinkedExprOperation.forElementWithAwait);
    } else {
      throw new StateError('Unsupported CollectionElement: $element');
    }
  }

  void _serializeListLiteral(ListLiteral expr) {
    if (forConst || expr.typeArguments == null) {
      List<CollectionElement> elements = expr.elements;
      elements.forEach(_serializeCollectionElement);
      ints.add(elements.length);
    } else {
      ints.add(0);
    }
    if (expr.typeArguments != null &&
        expr.typeArguments.arguments.length == 1) {
      references.add(serializeType(expr.typeArguments.arguments[0]));
      operations.add(UnlinkedExprOperation.makeTypedList);
    } else {
      operations.add(UnlinkedExprOperation.makeUntypedList);
    }
  }

  void _serializeMethodInvocation(MethodInvocation invocation) {
    Expression target = invocation.target;
    SimpleIdentifier methodName = invocation.methodName;
    ArgumentList argumentList = invocation.argumentList;
    if (_isIdentifierSequence(methodName)) {
      EntityRefBuilder ref = serializeIdentifierSequence(methodName);
      _serializeArguments(argumentList, invocation.typeArguments != null);
      references.add(ref);
      _serializeTypeArguments(invocation.typeArguments);
      operations.add(UnlinkedExprOperation.invokeMethodRef);
    } else {
      if (!invocation.isCascaded) {
        _serialize(target);
      }
      _serializeArguments(argumentList, invocation.typeArguments != null);
      strings.add(methodName.name);
      _serializeTypeArguments(invocation.typeArguments);
      operations.add(UnlinkedExprOperation.invokeMethod);
    }
  }

  void _serializePostfixExpression(PostfixExpression expr) {
    TokenType operator = expr.operator.type;
    Expression operand = expr.operand;
    if (operator == TokenType.PLUS_PLUS) {
      _serializePrefixPostfixIncDec(
          operand, UnlinkedExprAssignOperator.postfixIncrement);
    } else if (operator == TokenType.MINUS_MINUS) {
      _serializePrefixPostfixIncDec(
          operand, UnlinkedExprAssignOperator.postfixDecrement);
    } else {
      throw new StateError('Unknown operator: $operator');
    }
  }

  void _serializePrefixExpression(PrefixExpression expr) {
    TokenType operator = expr.operator.type;
    Expression operand = expr.operand;
    if (operator == TokenType.BANG) {
      _serialize(operand);
      operations.add(UnlinkedExprOperation.not);
    } else if (operator == TokenType.MINUS) {
      _serialize(operand);
      operations.add(UnlinkedExprOperation.negate);
    } else if (operator == TokenType.TILDE) {
      _serialize(operand);
      operations.add(UnlinkedExprOperation.complement);
    } else if (operator == TokenType.PLUS_PLUS) {
      _serializePrefixPostfixIncDec(
          operand, UnlinkedExprAssignOperator.prefixIncrement);
    } else if (operator == TokenType.MINUS_MINUS) {
      _serializePrefixPostfixIncDec(
          operand, UnlinkedExprAssignOperator.prefixDecrement);
    } else {
      throw new StateError('Unknown operator: $operator');
    }
  }

  void _serializePrefixPostfixIncDec(
      Expression operand, UnlinkedExprAssignOperator operator) {
    isValidConst = false;
    assignmentOperators.add(operator);
    _pushAssignable(operand);
  }

  void _serializePropertyAccess(PropertyAccess expr) {
    if (_isIdentifierSequence(expr)) {
      EntityRefBuilder ref = serializeIdentifierSequence(expr);
      references.add(ref);
      operations.add(UnlinkedExprOperation.pushReference);
    } else {
      if (!expr.isCascaded) {
        _serialize(expr.target);
      }
      strings.add(expr.propertyName.name);
      operations.add(UnlinkedExprOperation.extractProperty);
    }
  }

  void _serializeSetOrMapLiteral(SetOrMapLiteral expr) {
    if (forConst || expr.typeArguments == null) {
      for (CollectionElement element in expr.elements) {
        _serializeCollectionElement(element);
      }
      ints.add(expr.elements.length);
    } else {
      ints.add(0);
    }

    List<TypeAnnotation> typeArguments = expr.typeArguments?.arguments;
    if (typeArguments != null && typeArguments.length == 2) {
      references.add(serializeType(typeArguments[0]));
      references.add(serializeType(typeArguments[1]));
      operations.add(UnlinkedExprOperation.makeTypedMap2);
    } else if (typeArguments != null && typeArguments.length == 1) {
      references.add(serializeType(typeArguments[0]));
      operations.add(UnlinkedExprOperation.makeTypedSet);
    } else {
      operations.add(UnlinkedExprOperation.makeUntypedSetOrMap);
    }
  }

  void _serializeString(StringLiteral expr) {
    if (expr is AdjacentStrings) {
      if (expr.strings.every((string) => string is SimpleStringLiteral)) {
        operations.add(UnlinkedExprOperation.pushString);
        strings.add(expr.stringValue);
      } else {
        expr.strings.forEach(_serializeString);
        operations.add(UnlinkedExprOperation.concatenate);
        ints.add(expr.strings.length);
      }
    } else if (expr is SimpleStringLiteral) {
      operations.add(UnlinkedExprOperation.pushString);
      strings.add(expr.value);
    } else {
      StringInterpolation interpolation = expr as StringInterpolation;
      for (InterpolationElement element in interpolation.elements) {
        if (element is InterpolationString) {
          operations.add(UnlinkedExprOperation.pushString);
          strings.add(element.value);
        } else {
          _serialize((element as InterpolationExpression).expression);
        }
      }
      operations.add(UnlinkedExprOperation.concatenate);
      ints.add(interpolation.elements.length);
    }
  }

  void _serializeTypeArguments(TypeArgumentList typeArguments) {
    if (typeArguments == null) {
      ints.add(0);
    } else {
      ints.add(typeArguments.arguments.length);
      for (TypeAnnotation type in typeArguments.arguments) {
        references.add(serializeType(type));
      }
    }
  }
}
