| Index: pkg/analyzer/lib/src/summary/fasta/expression_serializer.dart
|
| diff --git a/pkg/analyzer/lib/src/summary/fasta/expression_serializer.dart b/pkg/analyzer/lib/src/summary/fasta/expression_serializer.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..3d60dd483afe434bccf203ca6fe1775afd8161d6
|
| --- /dev/null
|
| +++ b/pkg/analyzer/lib/src/summary/fasta/expression_serializer.dart
|
| @@ -0,0 +1,237 @@
|
| +// Copyright (c) 2017, 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.
|
| +
|
| +/// Algorithm to serialize expressions into the format used by summaries.
|
| +library summary.src.expression_serializer;
|
| +
|
| +import 'model.dart';
|
| +import 'package:front_end/src/fasta/scanner/token_constants.dart';
|
| +
|
| +/// Visitor over the minimal expression AST to convert them into stack-like
|
| +/// expressions used in the summary format.
|
| +class Serializer extends RecursiveVisitor {
|
| + UnlinkedExprBuilder expression;
|
| + final Scope scope;
|
| + final bool forConst;
|
| +
|
| + Serializer(this.scope, this.forConst);
|
| +
|
| + run(Expression root) {
|
| + expression = new UnlinkedExprBuilder(
|
| + isValidConst: forConst,
|
| + operations: [],
|
| + assignmentOperators: [],
|
| + ints: [],
|
| + doubles: [],
|
| + strings: [],
|
| + references: []);
|
| + root.accept(this);
|
| + expression.references.forEach((r) => (r as LazyEntityRef).expand());
|
| + return expression;
|
| + }
|
| +
|
| + handleRef(Ref n, {push: true}) {
|
| + var ref = n.prefix == null
|
| + ? new LazyEntityRef(n.name, scope)
|
| + : new NestedLazyEntityRef(
|
| + handleRef(n.prefix, push: false), n.name, scope);
|
| + if (push) {
|
| + expression.references.add(ref);
|
| + expression.operations.add(UnlinkedExprOperation.pushReference);
|
| + }
|
| + return ref;
|
| + }
|
| +
|
| + handleNull(NullLiteral n) {
|
| + expression.operations.add(UnlinkedExprOperation.pushNull);
|
| + }
|
| +
|
| + handleBool(BoolLiteral n) {
|
| + expression.operations.add(n.value
|
| + ? UnlinkedExprOperation.pushTrue
|
| + : UnlinkedExprOperation.pushFalse);
|
| + }
|
| +
|
| + handleInt(IntLiteral n) {
|
| + var ints = expression.ints;
|
| + var operations = expression.operations;
|
| + int value = n.value;
|
| + assert(value >= 0);
|
| + if (value >= (1 << 32)) {
|
| + int numOfComponents = 0;
|
| + expression.ints.add(numOfComponents);
|
| + void pushComponents(int value) {
|
| + if (value >= (1 << 32)) {
|
| + pushComponents(value >> 32);
|
| + }
|
| + 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);
|
| + }
|
| + }
|
| +
|
| + handleDouble(DoubleLiteral n) {
|
| + expression.operations.add(UnlinkedExprOperation.pushDouble);
|
| + expression.doubles.add(n.value);
|
| + }
|
| +
|
| + handleType(TypeRef n) {
|
| + var t = handleRef(n.name, push: false);
|
| + var args = n.typeArguments ?? [];
|
| + t.typeArguments = args.map((a) => handleType(a)).toList();
|
| + return t;
|
| + }
|
| +
|
| + handleList(ListLiteral n) {
|
| + expression.ints.add(n.values.length);
|
| + if (n.elementType == null) {
|
| + expression.operations.add(UnlinkedExprOperation.makeUntypedList);
|
| + } else {
|
| + handleType(n.elementType);
|
| + expression.operations.add(UnlinkedExprOperation.makeTypedList);
|
| + }
|
| + }
|
| +
|
| + handleMap(MapLiteral n) {
|
| + expression.ints.add(n.values.length);
|
| + if (n.types.isEmpty) {
|
| + expression.operations.add(UnlinkedExprOperation.makeUntypedMap);
|
| + } else {
|
| + n.types.forEach(handleType);
|
| + expression.operations.add(UnlinkedExprOperation.makeTypedMap);
|
| + }
|
| + }
|
| +
|
| + handleString(StringLiteral n) {
|
| + expression.strings.add(n.value);
|
| + expression.operations.add(UnlinkedExprOperation.pushString);
|
| + }
|
| +
|
| + handleSymbol(SymbolLiteral n) {
|
| + expression.strings.add(n.value);
|
| + expression.operations.add(UnlinkedExprOperation.makeSymbol);
|
| + }
|
| +
|
| + handleAs(As n) {
|
| + throw new UnimplementedError(); // TODO(paulberry): fix the code below.
|
| + // handleType(a.type);
|
| + // expression.operations.add(UnlinkedExprOperation.typeCast);
|
| + }
|
| +
|
| + handleIs(Is n) {
|
| + throw new UnimplementedError(); // TODO(paulberry): fix the code below.
|
| + // handleType(i.type);
|
| + // expression.operations.add(UnlinkedExprOperation.typeCheck);
|
| + }
|
| +
|
| + handleUnary(Unary n) {
|
| + expression.operations.add(_unaryOpFor(n.operator));
|
| + }
|
| +
|
| + handleBinary(Binary n){
|
| + expression.operations.add(_binaryOpFor(n.operator));
|
| + }
|
| +
|
| + handleLoad(Load n){
|
| + expression.strings.add(n.name);
|
| + expression.operations.add(UnlinkedExprOperation.extractProperty);
|
| + }
|
| +
|
| + handleIdentical(Identical n){
|
| + expression.references.add(handleRef(new Ref('identical'), push: false));
|
| + expression.ints.add(0);
|
| + expression.ints.add(2);
|
| + expression.ints.add(0);
|
| + expression.operations.add(UnlinkedExprOperation.invokeMethodRef);
|
| + }
|
| +
|
| + handleConditional(Conditional n) {
|
| + expression.operations.add(UnlinkedExprOperation.conditional);
|
| + }
|
| +
|
| + handleConstCreation(ConstCreation n) {
|
| + var ctor = n.constructor;
|
| + var type = handleType(ctor.type);
|
| + if (ctor.name != null) {
|
| + throw new UnimplementedError(); // TODO(paulberry): fix the code below.
|
| + //var classRef = handleRef(ctor.type.name, push: false);
|
| + //var top = scope.top;
|
| + //var ref = new LazyEntityRef(ctor.name, top)
|
| + // ..reference = (scope.serializeReference(classRef.reference, ctor.name))
|
| + // ..typeArguments = type.typeArguments
|
| + // ..wasExpanded = true;
|
| + //expression.references.add(ref);
|
| + } else {
|
| + expression.references.add(type);
|
| + }
|
| + expression.ints.add(n.namedArgs.length);
|
| + expression.ints.add(n.positionalArgs.length);
|
| + expression.strings.addAll(n.namedArgs.map((a) => a.name));
|
| + expression.operations.add(UnlinkedExprOperation.invokeConstructor);
|
| + }
|
| +
|
| + handleInvalid(Invalid n) {
|
| + expression.isValidConst = false;
|
| + throw new UnimplementedError(); // TODO(paulberry): fix the code below.
|
| + // expression.operations.add(UnlinkedExprOperation.pushInvalidor);
|
| + }
|
| +
|
| + handleOpaque(Opaque n) {
|
| + if (n.type != null) {
|
| + handleType(n.type);
|
| + expression.operations.add(UnlinkedExprOperation.pushTypedAbstract);
|
| + } else {
|
| + expression.operations.add(UnlinkedExprOperation.pushUntypedAbstract);
|
| + }
|
| + }
|
| +
|
| + handleOpaqueOp(OpaqueOp n) {
|
| + // nothing to do, recursive visitor serialized subexpression.
|
| + }
|
| +}
|
| +
|
| +/// Translate a parser unary operation into an operation in the summary format.
|
| +UnlinkedExprOperation _unaryOpFor(int operatorKind) {
|
| + switch (operatorKind) {
|
| + case BANG_TOKEN: return UnlinkedExprOperation.not;
|
| + case MINUS_TOKEN: return UnlinkedExprOperation.negate;
|
| + default:
|
| + throw "Unhandled operator kind $operatorKind";
|
| + }
|
| +}
|
| +
|
| +/// Translate a parser binary operation into an operation in the summary format.
|
| +UnlinkedExprOperation _binaryOpFor(int operatorKind) {
|
| + switch (operatorKind) {
|
| + case AMPERSAND_TOKEN: return UnlinkedExprOperation.bitAnd;
|
| + case AMPERSAND_AMPERSAND_TOKEN: return UnlinkedExprOperation.and;
|
| + case BANG_EQ_TOKEN: return UnlinkedExprOperation.notEqual;
|
| + case BAR_TOKEN: return UnlinkedExprOperation.bitOr;
|
| + case BAR_BAR_TOKEN: return UnlinkedExprOperation.or;
|
| + case CARET_TOKEN: return UnlinkedExprOperation.bitXor;
|
| + case EQ_EQ_TOKEN: return UnlinkedExprOperation.equal;
|
| + case GT_TOKEN: return UnlinkedExprOperation.greater;
|
| + case GT_EQ_TOKEN: return UnlinkedExprOperation.greaterEqual;
|
| + case GT_GT_TOKEN: return UnlinkedExprOperation.bitShiftRight;
|
| + case LT_TOKEN: return UnlinkedExprOperation.less;
|
| + case LT_EQ_TOKEN: return UnlinkedExprOperation.lessEqual;
|
| + case LT_LT_TOKEN: return UnlinkedExprOperation.bitShiftLeft;
|
| + case MINUS_TOKEN: return UnlinkedExprOperation.subtract;
|
| + case PERCENT_TOKEN: return UnlinkedExprOperation.modulo;
|
| + case PERIOD_TOKEN: return UnlinkedExprOperation.extractProperty;
|
| + case PLUS_TOKEN: return UnlinkedExprOperation.add;
|
| + case QUESTION_QUESTION_TOKEN: return UnlinkedExprOperation.ifNull;
|
| + case SLASH_TOKEN: return UnlinkedExprOperation.divide;
|
| + case STAR_TOKEN: return UnlinkedExprOperation.multiply;
|
| + case TILDE_SLASH_TOKEN: return UnlinkedExprOperation.floorDivide;
|
| + default:
|
| + throw "Unhandled openratorKind $operatorKind";
|
| + }
|
| +}
|
|
|