// 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);

  /// 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 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) {
    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 MapLiteral) {
      _serializeMapLiteral(expr);
    } else if (expr is SetLiteral) {
      _serializeSetLiteral(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 _serializeListLiteral(ListLiteral expr) {
    if (forConst || expr.typeArguments == null) {
      List<Expression> elements = expr.elements;
      elements.forEach(_serialize);
      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 _serializeMapLiteral(MapLiteral expr) {
    if (forConst || expr.typeArguments == null) {
      for (MapLiteralEntry entry in expr.entries) {
        _serialize(entry.key);
        _serialize(entry.value);
      }
      ints.add(expr.entries.length);
    } else {
      ints.add(0);
    }
    if (expr.typeArguments != null &&
        expr.typeArguments.arguments.length == 2) {
      references.add(serializeType(expr.typeArguments.arguments[0]));
      references.add(serializeType(expr.typeArguments.arguments[1]));
      operations.add(UnlinkedExprOperation.makeTypedMap);
    } else {
      operations.add(UnlinkedExprOperation.makeUntypedMap);
    }
  }

  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 _serializeSetLiteral(SetLiteral expr) {
    if (forConst || expr.typeArguments == null) {
      List<Expression> elements = expr.elements;
      elements.forEach(_serialize);
      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.makeTypedSet);
    } else {
      operations.add(UnlinkedExprOperation.makeUntypedSet);
    }
  }

  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));
      }
    }
  }
}
