6bfdd5239b
Tests are now run over entire libraries instead of their sub-trees
that are deemed to be ready for the serialization by the verifier.
The update revealed two scoping bugs. This CL fixes them as well,
namely the following:
* Result expression of a block expression should be in the scope of
the block. That is, the variables declared in the block are
visible in the result expression.
* Local function declarations should be visible in the blocks they
are declared in. Accidentally, the Bind combinator was used
instead of Rebind, resulting in local functions being visible in
their own bodies, but not in the blocks they are declared in.
Change-Id: I856045464caa934228d5f259a4d2d582e77deb88
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/155124
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Dmitry Stefantsov <dmitryas@google.com>
2191 lines
81 KiB
Dart
2191 lines
81 KiB
Dart
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
library kernel.text_serializer;
|
|
|
|
import '../ast.dart';
|
|
|
|
import 'serializer_combinators.dart';
|
|
|
|
import '../visitor.dart' show ExpressionVisitor;
|
|
|
|
abstract class Tagger<T> {
|
|
String tag(T object);
|
|
}
|
|
|
|
class NameTagger implements Tagger<Name> {
|
|
const NameTagger();
|
|
|
|
String tag(Name name) => name.isPrivate ? "private" : "public";
|
|
}
|
|
|
|
TextSerializer<Name> publicName =
|
|
Wrapped((w) => w.name, (u) => Name(u), const DartString());
|
|
|
|
TextSerializer<Name> privateName = Wrapped(
|
|
(w) => Tuple2(w.name, w.library.canonicalName),
|
|
(u) => Name.byReference(u.first, u.second.getReference()),
|
|
Tuple2Serializer(DartString(), CanonicalNameSerializer()));
|
|
|
|
TextSerializer<Name> nameSerializer = new Case(
|
|
const NameTagger(), {"public": publicName, "private": privateName});
|
|
|
|
class ExpressionTagger extends ExpressionVisitor<String>
|
|
implements Tagger<Expression> {
|
|
const ExpressionTagger();
|
|
|
|
String tag(Expression expression) => expression.accept(this);
|
|
|
|
String visitStringLiteral(StringLiteral _) => "string";
|
|
String visitIntLiteral(IntLiteral _) => "int";
|
|
String visitDoubleLiteral(DoubleLiteral _) => "double";
|
|
String visitBoolLiteral(BoolLiteral _) => "bool";
|
|
String visitNullLiteral(NullLiteral _) => "null";
|
|
String visitInvalidExpression(InvalidExpression _) => "invalid";
|
|
String visitNot(Not _) => "not";
|
|
String visitLogicalExpression(LogicalExpression expression) {
|
|
return expression.operator;
|
|
}
|
|
|
|
String visitStringConcatenation(StringConcatenation _) => "concat";
|
|
String visitSymbolLiteral(SymbolLiteral _) => "symbol";
|
|
String visitThisExpression(ThisExpression _) => "this";
|
|
String visitRethrow(Rethrow _) => "rethrow";
|
|
String visitThrow(Throw _) => "throw";
|
|
String visitAwaitExpression(AwaitExpression _) => "await";
|
|
String visitConditionalExpression(ConditionalExpression _) => "cond";
|
|
String visitIsExpression(IsExpression _) => "is";
|
|
String visitAsExpression(AsExpression _) => "as";
|
|
String visitTypeLiteral(TypeLiteral _) => "type";
|
|
String visitListLiteral(ListLiteral expression) {
|
|
return expression.isConst ? "const-list" : "list";
|
|
}
|
|
|
|
String visitSetLiteral(SetLiteral expression) {
|
|
return expression.isConst ? "const-set" : "set";
|
|
}
|
|
|
|
String visitMapLiteral(MapLiteral expression) {
|
|
return expression.isConst ? "const-map" : "map";
|
|
}
|
|
|
|
String visitLet(Let _) => "let";
|
|
|
|
String visitPropertyGet(PropertyGet _) => "get-prop";
|
|
String visitPropertySet(PropertySet _) => "set-prop";
|
|
String visitSuperPropertyGet(SuperPropertyGet _) => "get-super";
|
|
String visitSuperPropertySet(SuperPropertySet _) => "set-super";
|
|
String visitMethodInvocation(MethodInvocation _) => "invoke-method";
|
|
String visitSuperMethodInvocation(SuperMethodInvocation _) => "invoke-super";
|
|
|
|
String visitVariableGet(VariableGet _) => "get-var";
|
|
String visitVariableSet(VariableSet _) => "set-var";
|
|
String visitStaticGet(StaticGet _) => "get-static";
|
|
String visitStaticSet(StaticSet _) => "set-static";
|
|
String visitDirectPropertyGet(DirectPropertyGet _) => "get-direct-prop";
|
|
String visitDirectPropertySet(DirectPropertySet _) => "set-direct-prop";
|
|
String visitStaticInvocation(StaticInvocation expression) {
|
|
return expression.isConst ? "invoke-const-static" : "invoke-static";
|
|
}
|
|
|
|
String visitDirectMethodInvocation(DirectMethodInvocation _) {
|
|
return "invoke-direct-method";
|
|
}
|
|
|
|
String visitConstructorInvocation(ConstructorInvocation expression) {
|
|
return expression.isConst
|
|
? "invoke-const-constructor"
|
|
: "invoke-constructor";
|
|
}
|
|
|
|
String visitFunctionExpression(FunctionExpression _) => "fun";
|
|
String visitListConcatenation(ListConcatenation _) => "lists";
|
|
String visitSetConcatenation(SetConcatenation _) => "sets";
|
|
String visitMapConcatenation(MapConcatenation _) => "maps";
|
|
String visitBlockExpression(BlockExpression _) => "let-block";
|
|
String visitInstantiation(Instantiation _) => "apply";
|
|
String visitNullCheck(NullCheck _) => "not-null";
|
|
String visitFileUriExpression(FileUriExpression _) => "with-uri";
|
|
String visitCheckLibraryIsLoaded(CheckLibraryIsLoaded _) => "is-loaded";
|
|
String visitLoadLibrary(LoadLibrary _) => "load";
|
|
String visitConstantExpression(ConstantExpression _) => "const";
|
|
String visitInstanceCreation(InstanceCreation _) => "object";
|
|
}
|
|
|
|
const TextSerializer<InvalidExpression> invalidExpressionSerializer =
|
|
const Wrapped(
|
|
unwrapInvalidExpression, wrapInvalidExpression, const DartString());
|
|
|
|
String unwrapInvalidExpression(InvalidExpression expression) {
|
|
return expression.message;
|
|
}
|
|
|
|
InvalidExpression wrapInvalidExpression(String message) {
|
|
return new InvalidExpression(message);
|
|
}
|
|
|
|
TextSerializer<Not> notSerializer =
|
|
new Wrapped(unwrapNot, wrapNot, expressionSerializer);
|
|
|
|
Expression unwrapNot(Not expression) => expression.operand;
|
|
|
|
Not wrapNot(Expression operand) => new Not(operand);
|
|
|
|
TextSerializer<LogicalExpression> logicalAndSerializer = new Wrapped(
|
|
unwrapLogicalExpression,
|
|
wrapLogicalAnd,
|
|
new Tuple2Serializer(expressionSerializer, expressionSerializer));
|
|
|
|
Tuple2<Expression, Expression> unwrapLogicalExpression(
|
|
LogicalExpression expression) {
|
|
return new Tuple2(expression.left, expression.right);
|
|
}
|
|
|
|
LogicalExpression wrapLogicalAnd(Tuple2<Expression, Expression> tuple) {
|
|
return new LogicalExpression(tuple.first, '&&', tuple.second);
|
|
}
|
|
|
|
TextSerializer<LogicalExpression> logicalOrSerializer = new Wrapped(
|
|
unwrapLogicalExpression,
|
|
wrapLogicalOr,
|
|
new Tuple2Serializer(expressionSerializer, expressionSerializer));
|
|
|
|
LogicalExpression wrapLogicalOr(Tuple2<Expression, Expression> tuple) {
|
|
return new LogicalExpression(tuple.first, '||', tuple.second);
|
|
}
|
|
|
|
TextSerializer<StringConcatenation> stringConcatenationSerializer = new Wrapped(
|
|
unwrapStringConcatenation,
|
|
wrapStringConcatenation,
|
|
new ListSerializer(expressionSerializer));
|
|
|
|
List<Expression> unwrapStringConcatenation(StringConcatenation expression) {
|
|
return expression.expressions;
|
|
}
|
|
|
|
StringConcatenation wrapStringConcatenation(List<Expression> expressions) {
|
|
return new StringConcatenation(expressions);
|
|
}
|
|
|
|
const TextSerializer<StringLiteral> stringLiteralSerializer =
|
|
const Wrapped(unwrapStringLiteral, wrapStringLiteral, const DartString());
|
|
|
|
String unwrapStringLiteral(StringLiteral literal) => literal.value;
|
|
|
|
StringLiteral wrapStringLiteral(String value) => new StringLiteral(value);
|
|
|
|
const TextSerializer<IntLiteral> intLiteralSerializer =
|
|
const Wrapped(unwrapIntLiteral, wrapIntLiteral, const DartInt());
|
|
|
|
int unwrapIntLiteral(IntLiteral literal) => literal.value;
|
|
|
|
IntLiteral wrapIntLiteral(int value) => new IntLiteral(value);
|
|
|
|
const TextSerializer<DoubleLiteral> doubleLiteralSerializer =
|
|
const Wrapped(unwrapDoubleLiteral, wrapDoubleLiteral, const DartDouble());
|
|
|
|
double unwrapDoubleLiteral(DoubleLiteral literal) => literal.value;
|
|
|
|
DoubleLiteral wrapDoubleLiteral(double value) => new DoubleLiteral(value);
|
|
|
|
const TextSerializer<BoolLiteral> boolLiteralSerializer =
|
|
const Wrapped(unwrapBoolLiteral, wrapBoolLiteral, const DartBool());
|
|
|
|
bool unwrapBoolLiteral(BoolLiteral literal) => literal.value;
|
|
|
|
BoolLiteral wrapBoolLiteral(bool value) => new BoolLiteral(value);
|
|
|
|
const TextSerializer<NullLiteral> nullLiteralSerializer =
|
|
const Wrapped(unwrapNullLiteral, wrapNullLiteral, const Nothing());
|
|
|
|
void unwrapNullLiteral(NullLiteral literal) {}
|
|
|
|
NullLiteral wrapNullLiteral(void ignored) => new NullLiteral();
|
|
|
|
const TextSerializer<SymbolLiteral> symbolLiteralSerializer =
|
|
const Wrapped(unwrapSymbolLiteral, wrapSymbolLiteral, const DartString());
|
|
|
|
String unwrapSymbolLiteral(SymbolLiteral expression) => expression.value;
|
|
|
|
SymbolLiteral wrapSymbolLiteral(String value) => new SymbolLiteral(value);
|
|
|
|
const TextSerializer<ThisExpression> thisExpressionSerializer =
|
|
const Wrapped(unwrapThisExpression, wrapThisExpression, const Nothing());
|
|
|
|
void unwrapThisExpression(ThisExpression expression) {}
|
|
|
|
ThisExpression wrapThisExpression(void ignored) => new ThisExpression();
|
|
|
|
const TextSerializer<Rethrow> rethrowSerializer =
|
|
const Wrapped(unwrapRethrow, wrapRethrow, const Nothing());
|
|
|
|
void unwrapRethrow(Rethrow expression) {}
|
|
|
|
Rethrow wrapRethrow(void ignored) => new Rethrow();
|
|
|
|
TextSerializer<Throw> throwSerializer =
|
|
new Wrapped(unwrapThrow, wrapThrow, expressionSerializer);
|
|
|
|
Expression unwrapThrow(Throw expression) => expression.expression;
|
|
|
|
Throw wrapThrow(Expression expression) => new Throw(expression);
|
|
|
|
TextSerializer<AwaitExpression> awaitExpressionSerializer = new Wrapped(
|
|
unwrapAwaitExpression, wrapAwaitExpression, expressionSerializer);
|
|
|
|
Expression unwrapAwaitExpression(AwaitExpression expression) =>
|
|
expression.operand;
|
|
|
|
AwaitExpression wrapAwaitExpression(Expression operand) =>
|
|
new AwaitExpression(operand);
|
|
|
|
TextSerializer<ConditionalExpression> conditionalExpressionSerializer =
|
|
new Wrapped(
|
|
unwrapConditionalExpression,
|
|
wrapConditionalExpression,
|
|
new Tuple4Serializer(expressionSerializer, dartTypeSerializer,
|
|
expressionSerializer, expressionSerializer));
|
|
|
|
Tuple4<Expression, DartType, Expression, Expression>
|
|
unwrapConditionalExpression(ConditionalExpression expression) {
|
|
return new Tuple4(expression.condition, expression.staticType,
|
|
expression.then, expression.otherwise);
|
|
}
|
|
|
|
ConditionalExpression wrapConditionalExpression(
|
|
Tuple4<Expression, DartType, Expression, Expression> tuple) {
|
|
return new ConditionalExpression(
|
|
tuple.first, tuple.third, tuple.fourth, tuple.second);
|
|
}
|
|
|
|
TextSerializer<IsExpression> isExpressionSerializer = new Wrapped(
|
|
unwrapIsExpression,
|
|
wrapIsExpression,
|
|
new Tuple2Serializer(expressionSerializer, dartTypeSerializer));
|
|
|
|
Tuple2<Expression, DartType> unwrapIsExpression(IsExpression expression) {
|
|
return new Tuple2(expression.operand, expression.type);
|
|
}
|
|
|
|
IsExpression wrapIsExpression(Tuple2<Expression, DartType> tuple) {
|
|
return new IsExpression(tuple.first, tuple.second);
|
|
}
|
|
|
|
TextSerializer<AsExpression> asExpressionSerializer = new Wrapped(
|
|
unwrapAsExpression,
|
|
wrapAsExpression,
|
|
new Tuple2Serializer(expressionSerializer, dartTypeSerializer));
|
|
|
|
Tuple2<Expression, DartType> unwrapAsExpression(AsExpression expression) {
|
|
return new Tuple2(expression.operand, expression.type);
|
|
}
|
|
|
|
AsExpression wrapAsExpression(Tuple2<Expression, DartType> tuple) {
|
|
return new AsExpression(tuple.first, tuple.second);
|
|
}
|
|
|
|
TextSerializer<TypeLiteral> typeLiteralSerializer =
|
|
new Wrapped(unwrapTypeLiteral, wrapTypeLiteral, dartTypeSerializer);
|
|
|
|
DartType unwrapTypeLiteral(TypeLiteral expression) => expression.type;
|
|
|
|
TypeLiteral wrapTypeLiteral(DartType type) => new TypeLiteral(type);
|
|
|
|
TextSerializer<ListLiteral> listLiteralSerializer = new Wrapped(
|
|
unwrapListLiteral,
|
|
wrapListLiteral,
|
|
new Tuple2Serializer(
|
|
dartTypeSerializer, new ListSerializer(expressionSerializer)));
|
|
|
|
Tuple2<DartType, List<Expression>> unwrapListLiteral(ListLiteral expression) {
|
|
return new Tuple2(expression.typeArgument, expression.expressions);
|
|
}
|
|
|
|
ListLiteral wrapListLiteral(Tuple2<DartType, List<Expression>> tuple) {
|
|
return new ListLiteral(tuple.second,
|
|
typeArgument: tuple.first, isConst: false);
|
|
}
|
|
|
|
TextSerializer<ListLiteral> constListLiteralSerializer = new Wrapped(
|
|
unwrapListLiteral,
|
|
wrapConstListLiteral,
|
|
new Tuple2Serializer(
|
|
dartTypeSerializer, new ListSerializer(expressionSerializer)));
|
|
|
|
ListLiteral wrapConstListLiteral(Tuple2<DartType, List<Expression>> tuple) {
|
|
return new ListLiteral(tuple.second,
|
|
typeArgument: tuple.first, isConst: true);
|
|
}
|
|
|
|
TextSerializer<SetLiteral> setLiteralSerializer = new Wrapped(
|
|
unwrapSetLiteral,
|
|
wrapSetLiteral,
|
|
new Tuple2Serializer(
|
|
dartTypeSerializer, new ListSerializer(expressionSerializer)));
|
|
|
|
Tuple2<DartType, List<Expression>> unwrapSetLiteral(SetLiteral expression) {
|
|
return new Tuple2(expression.typeArgument, expression.expressions);
|
|
}
|
|
|
|
SetLiteral wrapSetLiteral(Tuple2<DartType, List<Expression>> tuple) {
|
|
return new SetLiteral(tuple.second,
|
|
typeArgument: tuple.first, isConst: false);
|
|
}
|
|
|
|
TextSerializer<SetLiteral> constSetLiteralSerializer = new Wrapped(
|
|
unwrapSetLiteral,
|
|
wrapConstSetLiteral,
|
|
new Tuple2Serializer(
|
|
dartTypeSerializer, new ListSerializer(expressionSerializer)));
|
|
|
|
SetLiteral wrapConstSetLiteral(Tuple2<DartType, List<Expression>> tuple) {
|
|
return new SetLiteral(tuple.second, typeArgument: tuple.first, isConst: true);
|
|
}
|
|
|
|
TextSerializer<MapLiteral> mapLiteralSerializer = new Wrapped(
|
|
unwrapMapLiteral,
|
|
wrapMapLiteral,
|
|
new Tuple3Serializer(dartTypeSerializer, dartTypeSerializer,
|
|
new ListSerializer(expressionSerializer)));
|
|
|
|
Tuple3<DartType, DartType, List<Expression>> unwrapMapLiteral(
|
|
MapLiteral expression) {
|
|
List<Expression> entries = new List(2 * expression.entries.length);
|
|
for (int from = 0, to = 0; from < expression.entries.length; ++from) {
|
|
MapEntry entry = expression.entries[from];
|
|
entries[to++] = entry.key;
|
|
entries[to++] = entry.value;
|
|
}
|
|
return new Tuple3(expression.keyType, expression.valueType, entries);
|
|
}
|
|
|
|
MapLiteral wrapMapLiteral(Tuple3<DartType, DartType, List<Expression>> tuple) {
|
|
List<MapEntry> entries = new List(tuple.third.length ~/ 2);
|
|
for (int from = 0, to = 0; to < entries.length; ++to) {
|
|
entries[to] = new MapEntry(tuple.third[from++], tuple.third[from++]);
|
|
}
|
|
return new MapLiteral(entries,
|
|
keyType: tuple.first, valueType: tuple.second, isConst: false);
|
|
}
|
|
|
|
TextSerializer<MapLiteral> constMapLiteralSerializer = new Wrapped(
|
|
unwrapMapLiteral,
|
|
wrapConstMapLiteral,
|
|
new Tuple3Serializer(dartTypeSerializer, dartTypeSerializer,
|
|
new ListSerializer(expressionSerializer)));
|
|
|
|
MapLiteral wrapConstMapLiteral(
|
|
Tuple3<DartType, DartType, List<Expression>> tuple) {
|
|
List<MapEntry> entries = new List(tuple.third.length ~/ 2);
|
|
for (int from = 0, to = 0; to < entries.length; ++to) {
|
|
entries[to] = new MapEntry(tuple.third[from++], tuple.third[from++]);
|
|
}
|
|
return new MapLiteral(entries,
|
|
keyType: tuple.first, valueType: tuple.second, isConst: true);
|
|
}
|
|
|
|
TextSerializer<Let> letSerializer = new Wrapped(unwrapLet, wrapLet,
|
|
new Bind(variableDeclarationSerializer, expressionSerializer));
|
|
|
|
Tuple2<VariableDeclaration, Expression> unwrapLet(Let expression) {
|
|
return new Tuple2(expression.variable, expression.body);
|
|
}
|
|
|
|
Let wrapLet(Tuple2<VariableDeclaration, Expression> tuple) {
|
|
return new Let(tuple.first, tuple.second);
|
|
}
|
|
|
|
TextSerializer<PropertyGet> propertyGetSerializer = new Wrapped(
|
|
unwrapPropertyGet,
|
|
wrapPropertyGet,
|
|
new Tuple2Serializer(expressionSerializer, nameSerializer));
|
|
|
|
Tuple2<Expression, Name> unwrapPropertyGet(PropertyGet expression) {
|
|
return new Tuple2(expression.receiver, expression.name);
|
|
}
|
|
|
|
PropertyGet wrapPropertyGet(Tuple2<Expression, Name> tuple) {
|
|
return new PropertyGet(tuple.first, tuple.second);
|
|
}
|
|
|
|
TextSerializer<PropertySet> propertySetSerializer = new Wrapped(
|
|
unwrapPropertySet,
|
|
wrapPropertySet,
|
|
new Tuple3Serializer(
|
|
expressionSerializer, nameSerializer, expressionSerializer));
|
|
|
|
Tuple3<Expression, Name, Expression> unwrapPropertySet(PropertySet expression) {
|
|
return new Tuple3(expression.receiver, expression.name, expression.value);
|
|
}
|
|
|
|
PropertySet wrapPropertySet(Tuple3<Expression, Name, Expression> tuple) {
|
|
return new PropertySet(tuple.first, tuple.second, tuple.third);
|
|
}
|
|
|
|
TextSerializer<SuperPropertyGet> superPropertyGetSerializer =
|
|
new Wrapped(unwrapSuperPropertyGet, wrapSuperPropertyGet, nameSerializer);
|
|
|
|
Name unwrapSuperPropertyGet(SuperPropertyGet expression) {
|
|
return expression.name;
|
|
}
|
|
|
|
SuperPropertyGet wrapSuperPropertyGet(Name name) {
|
|
return new SuperPropertyGet(name);
|
|
}
|
|
|
|
TextSerializer<SuperPropertySet> superPropertySetSerializer = new Wrapped(
|
|
unwrapSuperPropertySet,
|
|
wrapSuperPropertySet,
|
|
new Tuple2Serializer(nameSerializer, expressionSerializer));
|
|
|
|
Tuple2<Name, Expression> unwrapSuperPropertySet(SuperPropertySet expression) {
|
|
return new Tuple2(expression.name, expression.value);
|
|
}
|
|
|
|
SuperPropertySet wrapSuperPropertySet(Tuple2<Name, Expression> tuple) {
|
|
return new SuperPropertySet(tuple.first, tuple.second, null);
|
|
}
|
|
|
|
TextSerializer<MethodInvocation> methodInvocationSerializer = new Wrapped(
|
|
unwrapMethodInvocation,
|
|
wrapMethodInvocation,
|
|
new Tuple3Serializer(
|
|
expressionSerializer, nameSerializer, argumentsSerializer));
|
|
|
|
Tuple3<Expression, Name, Arguments> unwrapMethodInvocation(
|
|
MethodInvocation expression) {
|
|
return new Tuple3(expression.receiver, expression.name, expression.arguments);
|
|
}
|
|
|
|
MethodInvocation wrapMethodInvocation(
|
|
Tuple3<Expression, Name, Arguments> tuple) {
|
|
return new MethodInvocation(tuple.first, tuple.second, tuple.third);
|
|
}
|
|
|
|
TextSerializer<SuperMethodInvocation> superMethodInvocationSerializer =
|
|
new Wrapped(unwrapSuperMethodInvocation, wrapSuperMethodInvocation,
|
|
new Tuple2Serializer(nameSerializer, argumentsSerializer));
|
|
|
|
Tuple2<Name, Arguments> unwrapSuperMethodInvocation(
|
|
SuperMethodInvocation expression) {
|
|
return new Tuple2(expression.name, expression.arguments);
|
|
}
|
|
|
|
SuperMethodInvocation wrapSuperMethodInvocation(Tuple2<Name, Arguments> tuple) {
|
|
return new SuperMethodInvocation(tuple.first, tuple.second);
|
|
}
|
|
|
|
TextSerializer<VariableGet> variableGetSerializer = new Wrapped(
|
|
unwrapVariableGet,
|
|
wrapVariableGet,
|
|
new Tuple2Serializer(const ScopedUse<VariableDeclaration>(),
|
|
new Optional(dartTypeSerializer)));
|
|
|
|
Tuple2<VariableDeclaration, DartType> unwrapVariableGet(VariableGet node) {
|
|
return new Tuple2<VariableDeclaration, DartType>(
|
|
node.variable, node.promotedType);
|
|
}
|
|
|
|
VariableGet wrapVariableGet(Tuple2<VariableDeclaration, DartType> tuple) {
|
|
return new VariableGet(tuple.first, tuple.second);
|
|
}
|
|
|
|
TextSerializer<VariableSet> variableSetSerializer = new Wrapped(
|
|
unwrapVariableSet,
|
|
wrapVariableSet,
|
|
new Tuple2Serializer(
|
|
const ScopedUse<VariableDeclaration>(), expressionSerializer));
|
|
|
|
Tuple2<VariableDeclaration, Expression> unwrapVariableSet(VariableSet node) {
|
|
return new Tuple2<VariableDeclaration, Expression>(node.variable, node.value);
|
|
}
|
|
|
|
VariableSet wrapVariableSet(Tuple2<VariableDeclaration, Expression> tuple) {
|
|
return new VariableSet(tuple.first, tuple.second);
|
|
}
|
|
|
|
class CanonicalNameSerializer extends TextSerializer<CanonicalName> {
|
|
static const String delimiter = "::";
|
|
|
|
const CanonicalNameSerializer();
|
|
|
|
static void writeName(CanonicalName name, StringBuffer buffer) {
|
|
if (!name.isRoot) {
|
|
if (!name.parent.isRoot) {
|
|
writeName(name.parent, buffer);
|
|
buffer.write(delimiter);
|
|
}
|
|
buffer.write(name.name);
|
|
}
|
|
}
|
|
|
|
CanonicalName readFrom(Iterator<Object> stream, DeserializationState state) {
|
|
String string = const DartString().readFrom(stream, state);
|
|
CanonicalName name = state.nameRoot;
|
|
for (String s in string.split(delimiter)) {
|
|
name = name.getChild(s);
|
|
}
|
|
return name;
|
|
}
|
|
|
|
void writeTo(
|
|
StringBuffer buffer, CanonicalName name, SerializationState state) {
|
|
StringBuffer sb = new StringBuffer();
|
|
writeName(name, sb);
|
|
const DartString().writeTo(buffer, sb.toString(), state);
|
|
}
|
|
}
|
|
|
|
const TextSerializer<StaticGet> staticGetSerializer = const Wrapped(
|
|
unwrapStaticGet, wrapStaticGet, const CanonicalNameSerializer());
|
|
|
|
CanonicalName unwrapStaticGet(StaticGet expression) {
|
|
return expression.targetReference.canonicalName;
|
|
}
|
|
|
|
StaticGet wrapStaticGet(CanonicalName name) {
|
|
return new StaticGet.byReference(name.getReference());
|
|
}
|
|
|
|
TextSerializer<StaticSet> staticSetSerializer = new Wrapped(
|
|
unwrapStaticSet,
|
|
wrapStaticSet,
|
|
new Tuple2Serializer(
|
|
const CanonicalNameSerializer(), expressionSerializer));
|
|
|
|
Tuple2<CanonicalName, Expression> unwrapStaticSet(StaticSet expression) {
|
|
return new Tuple2(expression.targetReference.canonicalName, expression.value);
|
|
}
|
|
|
|
StaticSet wrapStaticSet(Tuple2<CanonicalName, Expression> tuple) {
|
|
return new StaticSet.byReference(tuple.first.getReference(), tuple.second);
|
|
}
|
|
|
|
TextSerializer<DirectPropertyGet> directPropertyGetSerializer = new Wrapped(
|
|
unwrapDirectPropertyGet,
|
|
wrapDirectPropertyGet,
|
|
new Tuple2Serializer(
|
|
expressionSerializer, const CanonicalNameSerializer()));
|
|
|
|
Tuple2<Expression, CanonicalName> unwrapDirectPropertyGet(
|
|
DirectPropertyGet expression) {
|
|
return new Tuple2(
|
|
expression.receiver, expression.targetReference.canonicalName);
|
|
}
|
|
|
|
DirectPropertyGet wrapDirectPropertyGet(
|
|
Tuple2<Expression, CanonicalName> tuple) {
|
|
return new DirectPropertyGet.byReference(
|
|
tuple.first, tuple.second.getReference());
|
|
}
|
|
|
|
TextSerializer<DirectPropertySet> directPropertySetSerializer = new Wrapped(
|
|
unwrapDirectPropertySet,
|
|
wrapDirectPropertySet,
|
|
new Tuple3Serializer(expressionSerializer, const CanonicalNameSerializer(),
|
|
expressionSerializer));
|
|
|
|
Tuple3<Expression, CanonicalName, Expression> unwrapDirectPropertySet(
|
|
DirectPropertySet expression) {
|
|
return new Tuple3(expression.receiver,
|
|
expression.targetReference.canonicalName, expression.value);
|
|
}
|
|
|
|
DirectPropertySet wrapDirectPropertySet(
|
|
Tuple3<Expression, CanonicalName, Expression> tuple) {
|
|
return new DirectPropertySet.byReference(
|
|
tuple.first, tuple.second.getReference(), tuple.third);
|
|
}
|
|
|
|
TextSerializer<StaticInvocation> staticInvocationSerializer = new Wrapped(
|
|
unwrapStaticInvocation,
|
|
wrapStaticInvocation,
|
|
new Tuple2Serializer(const CanonicalNameSerializer(), argumentsSerializer));
|
|
|
|
Tuple2<CanonicalName, Arguments> unwrapStaticInvocation(
|
|
StaticInvocation expression) {
|
|
return new Tuple2(
|
|
expression.targetReference.canonicalName, expression.arguments);
|
|
}
|
|
|
|
StaticInvocation wrapStaticInvocation(Tuple2<CanonicalName, Arguments> tuple) {
|
|
return new StaticInvocation.byReference(
|
|
tuple.first.getReference(), tuple.second,
|
|
isConst: false);
|
|
}
|
|
|
|
TextSerializer<StaticInvocation> constStaticInvocationSerializer = new Wrapped(
|
|
unwrapStaticInvocation,
|
|
wrapConstStaticInvocation,
|
|
new Tuple2Serializer(const CanonicalNameSerializer(), argumentsSerializer));
|
|
|
|
StaticInvocation wrapConstStaticInvocation(
|
|
Tuple2<CanonicalName, Arguments> tuple) {
|
|
return new StaticInvocation.byReference(
|
|
tuple.first.getReference(), tuple.second,
|
|
isConst: true);
|
|
}
|
|
|
|
TextSerializer<DirectMethodInvocation> directMethodInvocationSerializer =
|
|
new Wrapped(
|
|
unwrapDirectMethodInvocation,
|
|
wrapDirectMethodInvocation,
|
|
new Tuple3Serializer(expressionSerializer,
|
|
const CanonicalNameSerializer(), argumentsSerializer));
|
|
|
|
Tuple3<Expression, CanonicalName, Arguments> unwrapDirectMethodInvocation(
|
|
DirectMethodInvocation expression) {
|
|
return new Tuple3(expression.receiver,
|
|
expression.targetReference.canonicalName, expression.arguments);
|
|
}
|
|
|
|
DirectMethodInvocation wrapDirectMethodInvocation(
|
|
Tuple3<Expression, CanonicalName, Arguments> tuple) {
|
|
return new DirectMethodInvocation.byReference(
|
|
tuple.first, tuple.second.getReference(), tuple.third);
|
|
}
|
|
|
|
TextSerializer<ConstructorInvocation> constructorInvocationSerializer =
|
|
new Wrapped(
|
|
unwrapConstructorInvocation,
|
|
wrapConstructorInvocation,
|
|
new Tuple2Serializer(
|
|
const CanonicalNameSerializer(), argumentsSerializer));
|
|
|
|
Tuple2<CanonicalName, Arguments> unwrapConstructorInvocation(
|
|
ConstructorInvocation expression) {
|
|
return new Tuple2(
|
|
expression.targetReference.canonicalName, expression.arguments);
|
|
}
|
|
|
|
ConstructorInvocation wrapConstructorInvocation(
|
|
Tuple2<CanonicalName, Arguments> tuple) {
|
|
return new ConstructorInvocation.byReference(
|
|
tuple.first.getReference(), tuple.second,
|
|
isConst: false);
|
|
}
|
|
|
|
TextSerializer<ConstructorInvocation> constConstructorInvocationSerializer =
|
|
new Wrapped(unwrapConstructorInvocation, wrapConstConstructorInvocation,
|
|
Tuple2Serializer(const CanonicalNameSerializer(), argumentsSerializer));
|
|
|
|
ConstructorInvocation wrapConstConstructorInvocation(
|
|
Tuple2<CanonicalName, Arguments> tuple) {
|
|
return new ConstructorInvocation.byReference(
|
|
tuple.first.getReference(), tuple.second,
|
|
isConst: true);
|
|
}
|
|
|
|
TextSerializer<FunctionExpression> functionExpressionSerializer = new Wrapped(
|
|
unwrapFunctionExpression, wrapFunctionExpression, functionNodeSerializer);
|
|
|
|
FunctionNode unwrapFunctionExpression(FunctionExpression expression) {
|
|
return expression.function;
|
|
}
|
|
|
|
FunctionExpression wrapFunctionExpression(FunctionNode node) {
|
|
return new FunctionExpression(node);
|
|
}
|
|
|
|
TextSerializer<ListConcatenation> listConcatenationSerializer = Wrapped(
|
|
(lc) => Tuple2(lc.typeArgument, lc.lists),
|
|
(t) => ListConcatenation(t.second, typeArgument: t.first),
|
|
Tuple2Serializer(dartTypeSerializer, ListSerializer(expressionSerializer)));
|
|
|
|
TextSerializer<SetConcatenation> setConcatenationSerializer = Wrapped(
|
|
(sc) => Tuple2(sc.typeArgument, sc.sets),
|
|
(t) => SetConcatenation(t.second, typeArgument: t.first),
|
|
Tuple2Serializer(dartTypeSerializer, ListSerializer(expressionSerializer)));
|
|
|
|
TextSerializer<MapConcatenation> mapConcatenationSerializer = Wrapped(
|
|
(mc) => Tuple3(mc.keyType, mc.valueType, mc.maps),
|
|
(t) => MapConcatenation(t.third, keyType: t.first, valueType: t.second),
|
|
Tuple3Serializer(dartTypeSerializer, dartTypeSerializer,
|
|
ListSerializer(expressionSerializer)));
|
|
|
|
TextSerializer<BlockExpression> blockExpressionSerializer = Wrapped(
|
|
(w) => Tuple2(w.body.statements, w.value),
|
|
(u) => BlockExpression(Block(u.first), u.second),
|
|
const BlockSerializer());
|
|
|
|
TextSerializer<Instantiation> instantiationSerializer = Wrapped(
|
|
(i) => Tuple2(i.expression, i.typeArguments),
|
|
(t) => Instantiation(t.first, t.second),
|
|
Tuple2Serializer(expressionSerializer, ListSerializer(dartTypeSerializer)));
|
|
|
|
TextSerializer<NullCheck> nullCheckSerializer =
|
|
Wrapped((nc) => nc.operand, (op) => NullCheck(op), expressionSerializer);
|
|
|
|
TextSerializer<FileUriExpression> fileUriExpressionSerializer = Wrapped(
|
|
(fue) => Tuple2(fue.expression, fue.fileUri),
|
|
(t) => FileUriExpression(t.first, t.second),
|
|
Tuple2Serializer(expressionSerializer, const UriSerializer()));
|
|
|
|
TextSerializer<CheckLibraryIsLoaded> checkLibraryIsLoadedSerializer = Wrapped(
|
|
(clil) => clil.import,
|
|
(i) => CheckLibraryIsLoaded(i),
|
|
libraryDependencySerializer);
|
|
|
|
TextSerializer<LoadLibrary> loadLibrarySerializer = Wrapped(
|
|
(ll) => ll.import, (i) => LoadLibrary(i), libraryDependencySerializer);
|
|
|
|
TextSerializer<ConstantExpression> constantExpressionSerializer = Wrapped(
|
|
(ce) => Tuple2(ce.constant, ce.type),
|
|
(t) => ConstantExpression(t.first, t.second),
|
|
Tuple2Serializer(constantSerializer, dartTypeSerializer));
|
|
|
|
TextSerializer<InstanceCreation> instanceCreationSerializer = Wrapped(
|
|
(ic) => Tuple6(
|
|
ic.classReference.canonicalName,
|
|
ic.typeArguments,
|
|
ic.fieldValues.keys.map((r) => r.canonicalName).toList(),
|
|
ic.fieldValues.values.toList(),
|
|
ic.asserts,
|
|
ic.unusedArguments),
|
|
(t) => InstanceCreation(t.first.getReference(), t.second,
|
|
Map.fromIterables(t.third, t.fourth), t.fifth, t.sixth),
|
|
Tuple6Serializer(
|
|
CanonicalNameSerializer(),
|
|
ListSerializer(dartTypeSerializer),
|
|
ListSerializer(CanonicalNameSerializer()),
|
|
ListSerializer(expressionSerializer),
|
|
ListSerializer(assertStatementSerializer),
|
|
ListSerializer(expressionSerializer)));
|
|
|
|
Case<Expression> expressionSerializer =
|
|
new Case.uninitialized(const ExpressionTagger());
|
|
|
|
TextSerializer<NamedExpression> namedExpressionSerializer = new Wrapped(
|
|
unwrapNamedExpression,
|
|
wrapNamedExpression,
|
|
new Tuple2Serializer(const DartString(), expressionSerializer));
|
|
|
|
Tuple2<String, Expression> unwrapNamedExpression(NamedExpression expression) {
|
|
return new Tuple2(expression.name, expression.value);
|
|
}
|
|
|
|
NamedExpression wrapNamedExpression(Tuple2<String, Expression> tuple) {
|
|
return new NamedExpression(tuple.first, tuple.second);
|
|
}
|
|
|
|
TextSerializer<Arguments> argumentsSerializer = new Wrapped(
|
|
unwrapArguments,
|
|
wrapArguments,
|
|
Tuple3Serializer(
|
|
new ListSerializer(dartTypeSerializer),
|
|
new ListSerializer(expressionSerializer),
|
|
new ListSerializer(namedExpressionSerializer)));
|
|
|
|
Tuple3<List<DartType>, List<Expression>, List<NamedExpression>> unwrapArguments(
|
|
Arguments arguments) {
|
|
return new Tuple3(arguments.types, arguments.positional, arguments.named);
|
|
}
|
|
|
|
Arguments wrapArguments(
|
|
Tuple3<List<DartType>, List<Expression>, List<NamedExpression>> tuple) {
|
|
return new Arguments(tuple.second, types: tuple.first, named: tuple.third);
|
|
}
|
|
|
|
const Map<int, String> variableDeclarationFlagToName = const {
|
|
VariableDeclaration.FlagFinal: "final",
|
|
VariableDeclaration.FlagConst: "const",
|
|
VariableDeclaration.FlagFieldFormal: "field-formal",
|
|
VariableDeclaration.FlagCovariant: "covariant",
|
|
VariableDeclaration.FlagInScope: "in-scope",
|
|
VariableDeclaration.FlagGenericCovariantImpl: "generic-covariant-impl",
|
|
VariableDeclaration.FlagLate: "late",
|
|
VariableDeclaration.FlagRequired: "required",
|
|
};
|
|
|
|
class VariableDeclarationFlagTagger implements Tagger<int> {
|
|
String tag(int flag) {
|
|
return variableDeclarationFlagToName[flag] ??
|
|
(throw StateError("Unknown VariableDeclaration flag value: ${flag}."));
|
|
}
|
|
}
|
|
|
|
TextSerializer<int> variableDeclarationFlagsSerializer = Wrapped(
|
|
(w) => List.generate(30, (i) => w & (1 << i)).where((f) => f != 0).toList(),
|
|
(u) => u.fold(0, (fs, f) => fs |= f),
|
|
ListSerializer(Case(
|
|
VariableDeclarationFlagTagger(),
|
|
Map.fromIterable(variableDeclarationFlagToName.entries,
|
|
key: (e) => e.value,
|
|
value: (e) => Wrapped((_) => null, (_) => e.key, Nothing())))));
|
|
|
|
TextSerializer<VariableDeclaration> variableDeclarationSerializer = Wrapped(
|
|
(v) => Tuple2(v.name, v),
|
|
(t) => t.second..name = t.first,
|
|
Binder<VariableDeclaration>(
|
|
new Wrapped(
|
|
(w) => Tuple4(w.flags, w.type, w.initializer, w.annotations),
|
|
(u) => u.fourth.fold(
|
|
VariableDeclaration(null,
|
|
flags: u.first, type: u.second, initializer: u.third),
|
|
(v, a) => v..addAnnotation(a)),
|
|
Tuple4Serializer(
|
|
variableDeclarationFlagsSerializer,
|
|
dartTypeSerializer,
|
|
new Optional(expressionSerializer),
|
|
new ListSerializer(expressionSerializer))),
|
|
));
|
|
|
|
TextSerializer<TypeParameter> typeParameterSerializer = Wrapped(
|
|
(p) => Tuple2(p.name, p),
|
|
(t) => t.second..name = t.first,
|
|
Binder(Wrapped((_) => null, (_) => TypeParameter(), const Nothing())));
|
|
|
|
TextSerializer<List<TypeParameter>> typeParametersSerializer = new Zip(
|
|
new Rebind(
|
|
new Zip(
|
|
new Rebind(new ListSerializer(typeParameterSerializer),
|
|
new ListSerializer(dartTypeSerializer)),
|
|
zipTypeParameterBound,
|
|
unzipTypeParameterBound),
|
|
new ListSerializer(dartTypeSerializer)),
|
|
zipTypeParameterDefaultType,
|
|
unzipTypeParameterDefaultType);
|
|
|
|
TypeParameter zipTypeParameterBound(TypeParameter node, DartType bound) {
|
|
return node..bound = bound;
|
|
}
|
|
|
|
Tuple2<TypeParameter, DartType> unzipTypeParameterBound(TypeParameter node) {
|
|
return new Tuple2(node, node.bound);
|
|
}
|
|
|
|
TypeParameter zipTypeParameterDefaultType(
|
|
TypeParameter node, DartType defaultType) {
|
|
return node..defaultType = defaultType;
|
|
}
|
|
|
|
Tuple2<TypeParameter, DartType> unzipTypeParameterDefaultType(
|
|
TypeParameter node) {
|
|
return new Tuple2(node, node.defaultType);
|
|
}
|
|
|
|
class DartTypeTagger extends DartTypeVisitor<String>
|
|
implements Tagger<DartType> {
|
|
const DartTypeTagger();
|
|
|
|
String tag(DartType type) => type.accept(this);
|
|
|
|
String visitInvalidType(InvalidType _) => "invalid";
|
|
String visitDynamicType(DynamicType _) => "dynamic";
|
|
String visitVoidType(VoidType _) => "void";
|
|
String visitBottomType(BottomType _) => "bottom";
|
|
String visitFunctionType(FunctionType _) => "->";
|
|
String visitTypeParameterType(TypeParameterType _) => "par";
|
|
String visitInterfaceType(InterfaceType _) => "interface";
|
|
String visitNeverType(NeverType _) => "never";
|
|
String visitTypedefType(TypedefType _) => "typedef";
|
|
String visitFutureOrType(FutureOrType _) => "futureor";
|
|
}
|
|
|
|
const TextSerializer<InvalidType> invalidTypeSerializer =
|
|
const Wrapped(unwrapInvalidType, wrapInvalidType, const Nothing());
|
|
|
|
void unwrapInvalidType(InvalidType type) {}
|
|
|
|
InvalidType wrapInvalidType(void ignored) => const InvalidType();
|
|
|
|
const TextSerializer<DynamicType> dynamicTypeSerializer =
|
|
const Wrapped(unwrapDynamicType, wrapDynamicType, const Nothing());
|
|
|
|
void unwrapDynamicType(DynamicType type) {}
|
|
|
|
DynamicType wrapDynamicType(void ignored) => const DynamicType();
|
|
|
|
const TextSerializer<VoidType> voidTypeSerializer =
|
|
const Wrapped(unwrapVoidType, wrapVoidType, const Nothing());
|
|
|
|
void unwrapVoidType(VoidType type) {}
|
|
|
|
VoidType wrapVoidType(void ignored) => const VoidType();
|
|
|
|
const TextSerializer<BottomType> bottomTypeSerializer =
|
|
const Wrapped(unwrapBottomType, wrapBottomType, const Nothing());
|
|
|
|
void unwrapBottomType(BottomType type) {}
|
|
|
|
BottomType wrapBottomType(void ignored) => const BottomType();
|
|
|
|
const TextSerializer<NeverType> neverTypeSerializer =
|
|
const Wrapped(unwrapNeverType, wrapNeverType, const Nothing());
|
|
|
|
void unwrapNeverType(NeverType type) {}
|
|
|
|
NeverType wrapNeverType(void ignored) => const NeverType(Nullability.legacy);
|
|
|
|
// TODO(dmitryas): Also handle nameParameters, and typedefType.
|
|
TextSerializer<FunctionType> functionTypeSerializer = new Wrapped(
|
|
unwrapFunctionType,
|
|
wrapFunctionType,
|
|
new Bind(
|
|
typeParametersSerializer,
|
|
new Tuple4Serializer(
|
|
new ListSerializer(dartTypeSerializer),
|
|
new ListSerializer(dartTypeSerializer),
|
|
new ListSerializer(namedTypeSerializer),
|
|
dartTypeSerializer)));
|
|
|
|
Tuple2<List<TypeParameter>,
|
|
Tuple4<List<DartType>, List<DartType>, List<NamedType>, DartType>>
|
|
unwrapFunctionType(FunctionType type) {
|
|
return new Tuple2(
|
|
type.typeParameters,
|
|
new Tuple4(
|
|
type.positionalParameters.sublist(0, type.requiredParameterCount),
|
|
type.positionalParameters.sublist(type.requiredParameterCount),
|
|
type.namedParameters,
|
|
type.returnType));
|
|
}
|
|
|
|
FunctionType wrapFunctionType(
|
|
Tuple2<List<TypeParameter>,
|
|
Tuple4<List<DartType>, List<DartType>, List<NamedType>, DartType>>
|
|
tuple) {
|
|
return new FunctionType(tuple.second.first + tuple.second.second,
|
|
tuple.second.fourth, Nullability.legacy,
|
|
requiredParameterCount: tuple.second.first.length,
|
|
typeParameters: tuple.first,
|
|
namedParameters: tuple.second.third);
|
|
}
|
|
|
|
TextSerializer<NamedType> namedTypeSerializer = new Wrapped(unwrapNamedType,
|
|
wrapNamedType, Tuple2Serializer(const DartString(), dartTypeSerializer));
|
|
|
|
Tuple2<String, DartType> unwrapNamedType(NamedType namedType) {
|
|
return new Tuple2(namedType.name, namedType.type);
|
|
}
|
|
|
|
NamedType wrapNamedType(Tuple2<String, DartType> tuple) {
|
|
return new NamedType(tuple.first, tuple.second);
|
|
}
|
|
|
|
TextSerializer<TypeParameterType> typeParameterTypeSerializer = new Wrapped(
|
|
unwrapTypeParameterType,
|
|
wrapTypeParameterType,
|
|
Tuple2Serializer(
|
|
new ScopedUse<TypeParameter>(), new Optional(dartTypeSerializer)));
|
|
|
|
Tuple2<TypeParameter, DartType> unwrapTypeParameterType(
|
|
TypeParameterType node) {
|
|
return new Tuple2(node.parameter, node.promotedBound);
|
|
}
|
|
|
|
TypeParameterType wrapTypeParameterType(Tuple2<TypeParameter, DartType> tuple) {
|
|
return new TypeParameterType(tuple.first, Nullability.legacy, tuple.second);
|
|
}
|
|
|
|
TextSerializer<InterfaceType> interfaceTypeSerializer = new Wrapped(
|
|
unwrapInterfaceType,
|
|
wrapInterfaceType,
|
|
Tuple2Serializer(const CanonicalNameSerializer(),
|
|
new ListSerializer(dartTypeSerializer)));
|
|
|
|
Tuple2<CanonicalName, List<DartType>> unwrapInterfaceType(InterfaceType node) {
|
|
return new Tuple2(node.className.canonicalName, node.typeArguments);
|
|
}
|
|
|
|
InterfaceType wrapInterfaceType(Tuple2<CanonicalName, List<DartType>> tuple) {
|
|
return new InterfaceType.byReference(
|
|
tuple.first.reference, Nullability.legacy, tuple.second);
|
|
}
|
|
|
|
TextSerializer<TypedefType> typedefTypeSerializer = new Wrapped(
|
|
unwrapTypedefType,
|
|
wrapTypedefType,
|
|
Tuple2Serializer(const CanonicalNameSerializer(),
|
|
new ListSerializer(dartTypeSerializer)));
|
|
|
|
Tuple2<CanonicalName, List<DartType>> unwrapTypedefType(TypedefType node) {
|
|
return new Tuple2(node.typedefReference.canonicalName, node.typeArguments);
|
|
}
|
|
|
|
TypedefType wrapTypedefType(Tuple2<CanonicalName, List<DartType>> tuple) {
|
|
return new TypedefType.byReference(
|
|
tuple.first.reference, Nullability.legacy, tuple.second);
|
|
}
|
|
|
|
TextSerializer<FutureOrType> futureOrTypeSerializer =
|
|
new Wrapped(unwrapFutureOrType, wrapFutureOrType, dartTypeSerializer);
|
|
|
|
DartType unwrapFutureOrType(FutureOrType node) {
|
|
return node.typeArgument;
|
|
}
|
|
|
|
FutureOrType wrapFutureOrType(DartType typeArgument) {
|
|
return new FutureOrType(typeArgument, Nullability.legacy);
|
|
}
|
|
|
|
Case<DartType> dartTypeSerializer =
|
|
new Case.uninitialized(const DartTypeTagger());
|
|
|
|
class StatementTagger extends StatementVisitor<String>
|
|
implements Tagger<Statement> {
|
|
const StatementTagger();
|
|
|
|
String tag(Statement statement) => statement.accept(this);
|
|
|
|
String visitExpressionStatement(ExpressionStatement _) => "expr";
|
|
String visitReturnStatement(ReturnStatement node) {
|
|
return node.expression == null ? "ret-void" : "ret";
|
|
}
|
|
|
|
String visitYieldStatement(YieldStatement _) => "yield";
|
|
String visitBlock(Block _) => "block";
|
|
String visitVariableDeclaration(VariableDeclaration _) => "local";
|
|
String visitIfStatement(IfStatement node) {
|
|
return node.otherwise == null ? "if" : "if-else";
|
|
}
|
|
|
|
String visitEmptyStatement(EmptyStatement node) => "skip";
|
|
String visitWhileStatement(WhileStatement node) => "while";
|
|
String visitDoStatement(DoStatement node) => "do-while";
|
|
String visitForStatement(ForStatement node) => "for";
|
|
String visitForInStatement(ForInStatement node) {
|
|
return node.isAsync ? "await-for-in" : "for-in";
|
|
}
|
|
|
|
String visitAssertStatement(AssertStatement node) => "assert";
|
|
String visitAssertBlock(AssertBlock node) => "assert-block";
|
|
String visitLabeledStatement(LabeledStatement node) => "label";
|
|
String visitBreakStatement(BreakStatement node) => "break";
|
|
String visitTryFinally(TryFinally node) => "try-finally";
|
|
String visitTryCatch(TryCatch node) => "try-catch";
|
|
String visitSwitchStatement(SwitchStatement node) => "switch";
|
|
String visitContinueSwitchStatement(ContinueSwitchStatement node) =>
|
|
"continue";
|
|
String visitFunctionDeclaration(FunctionDeclaration node) => "local-fun";
|
|
}
|
|
|
|
TextSerializer<ExpressionStatement> expressionStatementSerializer = new Wrapped(
|
|
unwrapExpressionStatement, wrapExpressionStatement, expressionSerializer);
|
|
|
|
Expression unwrapExpressionStatement(ExpressionStatement statement) {
|
|
return statement.expression;
|
|
}
|
|
|
|
ExpressionStatement wrapExpressionStatement(Expression expression) {
|
|
return new ExpressionStatement(expression);
|
|
}
|
|
|
|
TextSerializer<ReturnStatement> returnStatementSerializer = new Wrapped(
|
|
unwrapReturnStatement, wrapReturnStatement, expressionSerializer);
|
|
|
|
Expression unwrapReturnStatement(ReturnStatement statement) {
|
|
return statement.expression;
|
|
}
|
|
|
|
ReturnStatement wrapReturnStatement(Expression expression) {
|
|
return new ReturnStatement(expression);
|
|
}
|
|
|
|
TextSerializer<ReturnStatement> returnVoidStatementSerializer = new Wrapped(
|
|
unwrapReturnVoidStatement, wrapReturnVoidStatement, const Nothing());
|
|
|
|
void unwrapReturnVoidStatement(void ignored) {}
|
|
|
|
ReturnStatement wrapReturnVoidStatement(void ignored) => new ReturnStatement();
|
|
|
|
TextSerializer<YieldStatement> yieldStatementSerializer =
|
|
new Wrapped(unwrapYieldStatement, wrapYieldStatement, expressionSerializer);
|
|
|
|
Expression unwrapYieldStatement(YieldStatement node) => node.expression;
|
|
|
|
YieldStatement wrapYieldStatement(Expression expression) {
|
|
return new YieldStatement(expression);
|
|
}
|
|
|
|
TextSerializer<AssertStatement> assertStatementSerializer = Wrapped(
|
|
(a) => Tuple2(a.condition, a.message),
|
|
(t) => AssertStatement(t.first, message: t.second),
|
|
Tuple2Serializer(expressionSerializer, Optional(expressionSerializer)));
|
|
|
|
TextSerializer<Block> blockSerializer = new Wrapped(
|
|
(w) => Tuple2(w.statements, null),
|
|
(u) => Block(u.first),
|
|
const BlockSerializer());
|
|
|
|
TextSerializer<AssertBlock> assertBlockSerializer = new Wrapped(
|
|
(w) => Tuple2(w.statements, null), (u) => u.first, const BlockSerializer());
|
|
|
|
/// Serializer for [Block]s.
|
|
///
|
|
/// [BlockSerializer] is a combination of [ListSerializer] and [Bind]. As in
|
|
/// the case of [ListSerializer], [BlockSerializer] is a sequence of statements.
|
|
/// As in the case of [Bind], a statement in a block can be a
|
|
/// [VariableDeclaration] introducing binders that are bound in the rest of the
|
|
/// statements in the block. Effectively, [BlockSerializer] could have been
|
|
/// expressed in terms of [ListSerializer] and [Bind], but that would transform
|
|
/// blocks like {stmt1; stmt2; stmt3;} into {stmt1; {stmt2; {stmt3; {}}}} via
|
|
/// the round-trip, and an extra pass will be required to flatten the
|
|
/// unnecessary nested blocks. Instead, [BlockSerializer] is implemented
|
|
/// without direct invocations of either [ListSerializer] or [Bind], but with a
|
|
/// certain internal correspondence to how they work.
|
|
class BlockSerializer
|
|
extends TextSerializer<Tuple2<List<Statement>, Expression>> {
|
|
const BlockSerializer();
|
|
|
|
Tuple2<List<Statement>, Expression> readFrom(
|
|
Iterator<Object> stream, DeserializationState state) {
|
|
if (stream.current is! Iterator) {
|
|
throw StateError("Expected a list, found an atom: '${stream.current}'.");
|
|
}
|
|
Iterator<Object> list = stream.current;
|
|
list.moveNext();
|
|
List<Statement> statements = [];
|
|
DeserializationState currentState = state;
|
|
while (list.current != null) {
|
|
currentState = new DeserializationState(
|
|
new DeserializationEnvironment(currentState.environment),
|
|
currentState.nameRoot);
|
|
statements.add(statementSerializer.readFrom(list, currentState));
|
|
currentState.environment.extend();
|
|
}
|
|
stream.moveNext();
|
|
Expression expression =
|
|
new Optional(expressionSerializer).readFrom(stream, currentState);
|
|
return new Tuple2(statements, expression);
|
|
}
|
|
|
|
void writeTo(StringBuffer buffer, Tuple2<List<Statement>, Expression> tuple,
|
|
SerializationState state) {
|
|
buffer.write('(');
|
|
SerializationState currentState = state;
|
|
for (int i = 0; i < tuple.first.length; ++i) {
|
|
if (i != 0) buffer.write(' ');
|
|
currentState = new SerializationState(
|
|
new SerializationEnvironment(currentState.environment));
|
|
statementSerializer.writeTo(buffer, tuple.first[i], currentState);
|
|
currentState.environment.extend();
|
|
}
|
|
buffer.write(') ');
|
|
new Optional(expressionSerializer)
|
|
.writeTo(buffer, tuple.second, currentState);
|
|
}
|
|
}
|
|
|
|
TextSerializer<IfStatement> ifStatementSerializer = new Wrapped(
|
|
unwrapIfStatement,
|
|
wrapIfStatement,
|
|
Tuple2Serializer(expressionSerializer, statementSerializer));
|
|
|
|
Tuple2<Expression, Statement> unwrapIfStatement(IfStatement node) {
|
|
return new Tuple2(node.condition, node.then);
|
|
}
|
|
|
|
IfStatement wrapIfStatement(Tuple2<Expression, Statement> tuple) {
|
|
return new IfStatement(tuple.first, tuple.second, null);
|
|
}
|
|
|
|
TextSerializer<IfStatement> ifElseStatementSerializer = new Wrapped(
|
|
unwrapIfElseStatement,
|
|
wrapIfElseStatement,
|
|
Tuple3Serializer(
|
|
expressionSerializer, statementSerializer, statementSerializer));
|
|
|
|
Tuple3<Expression, Statement, Statement> unwrapIfElseStatement(
|
|
IfStatement node) {
|
|
return new Tuple3(node.condition, node.then, node.otherwise);
|
|
}
|
|
|
|
IfStatement wrapIfElseStatement(
|
|
Tuple3<Expression, Statement, Statement> tuple) {
|
|
return new IfStatement(tuple.first, tuple.second, tuple.third);
|
|
}
|
|
|
|
TextSerializer<EmptyStatement> emptyStatementSerializer =
|
|
new Wrapped(unwrapEmptyStatement, wrapEmptyStatement, const Nothing());
|
|
|
|
void unwrapEmptyStatement(EmptyStatement node) {}
|
|
|
|
EmptyStatement wrapEmptyStatement(void ignored) => new EmptyStatement();
|
|
|
|
TextSerializer<WhileStatement> whileStatementSerializer = new Wrapped(
|
|
unwrapWhileStatement,
|
|
wrapWhileStatement,
|
|
new Tuple2Serializer(expressionSerializer, statementSerializer));
|
|
|
|
Tuple2<Expression, Statement> unwrapWhileStatement(WhileStatement node) {
|
|
return new Tuple2(node.condition, node.body);
|
|
}
|
|
|
|
WhileStatement wrapWhileStatement(Tuple2<Expression, Statement> tuple) {
|
|
return new WhileStatement(tuple.first, tuple.second);
|
|
}
|
|
|
|
TextSerializer<DoStatement> doStatementSerializer = new Wrapped(
|
|
unwrapDoStatement,
|
|
wrapDoStatement,
|
|
new Tuple2Serializer(statementSerializer, expressionSerializer));
|
|
|
|
Tuple2<Statement, Expression> unwrapDoStatement(DoStatement node) {
|
|
return new Tuple2(node.body, node.condition);
|
|
}
|
|
|
|
DoStatement wrapDoStatement(Tuple2<Statement, Expression> tuple) {
|
|
return new DoStatement(tuple.first, tuple.second);
|
|
}
|
|
|
|
TextSerializer<ForStatement> forStatementSerializer = new Wrapped(
|
|
(w) => Tuple2(w.variables, Tuple3(w.condition, w.updates, w.body)),
|
|
(u) =>
|
|
ForStatement(u.first, u.second.first, u.second.second, u.second.third),
|
|
new Bind(
|
|
ListSerializer(variableDeclarationSerializer),
|
|
new Tuple3Serializer(Optional(expressionSerializer),
|
|
new ListSerializer(expressionSerializer), statementSerializer)));
|
|
|
|
TextSerializer<ForInStatement> forInStatementSerializer = new Wrapped(
|
|
unwrapForInStatement,
|
|
wrapForInStatement,
|
|
new Tuple2Serializer(expressionSerializer,
|
|
new Bind(variableDeclarationSerializer, statementSerializer)));
|
|
|
|
Tuple2<Expression, Tuple2<VariableDeclaration, Statement>> unwrapForInStatement(
|
|
ForInStatement node) {
|
|
return new Tuple2(node.iterable, new Tuple2(node.variable, node.body));
|
|
}
|
|
|
|
ForInStatement wrapForInStatement(
|
|
Tuple2<Expression, Tuple2<VariableDeclaration, Statement>> tuple) {
|
|
return new ForInStatement(
|
|
tuple.second.first, tuple.first, tuple.second.second);
|
|
}
|
|
|
|
TextSerializer<ForInStatement> awaitForInStatementSerializer = new Wrapped(
|
|
unwrapForInStatement,
|
|
wrapAwaitForInStatement,
|
|
new Tuple2Serializer(expressionSerializer,
|
|
new Bind(variableDeclarationSerializer, statementSerializer)));
|
|
|
|
ForInStatement wrapAwaitForInStatement(
|
|
Tuple2<Expression, Tuple2<VariableDeclaration, Statement>> tuple) {
|
|
return new ForInStatement(
|
|
tuple.second.first, tuple.first, tuple.second.second,
|
|
isAsync: true);
|
|
}
|
|
|
|
TextSerializer<LabeledStatement> labeledStatementSerializer =
|
|
Wrapped<Tuple2<LabeledStatement, Statement>, LabeledStatement>(
|
|
(ls) => Tuple2(ls, ls.body),
|
|
(t) => t.first..body = t.second,
|
|
Bind(
|
|
Wrapped(
|
|
(ls) => Tuple2("L", ls),
|
|
(t) => t.second,
|
|
Binder(Wrapped(
|
|
(_) => null, (_) => LabeledStatement(null), Nothing()))),
|
|
statementSerializer));
|
|
|
|
TextSerializer<BreakStatement> breakSerializer = new Wrapped(
|
|
unwrapBreakStatement,
|
|
wrapBreakStatement,
|
|
const ScopedUse<LabeledStatement>());
|
|
|
|
LabeledStatement unwrapBreakStatement(BreakStatement node) {
|
|
return node.target;
|
|
}
|
|
|
|
BreakStatement wrapBreakStatement(LabeledStatement node) {
|
|
return new BreakStatement(node);
|
|
}
|
|
|
|
TextSerializer<TryFinally> tryFinallySerializer = Wrapped(
|
|
(w) => Tuple2(w.body, w.finalizer),
|
|
(u) => TryFinally(u.first, u.second),
|
|
Tuple2Serializer(statementSerializer, statementSerializer));
|
|
|
|
TextSerializer<TryCatch> tryCatchSerializer = Wrapped(
|
|
(w) => Tuple2(w.body, w.catches),
|
|
(u) => TryCatch(u.first, u.second),
|
|
Tuple2Serializer(statementSerializer, ListSerializer(catchSerializer)));
|
|
|
|
TextSerializer<Catch> catchSerializer = Wrapped(
|
|
(w) => Tuple2(w.guard, Tuple2(Tuple2(w.exception, w.stackTrace), w.body)),
|
|
(u) => Catch(u.second.first.first, u.second.second,
|
|
stackTrace: u.second.first.second, guard: u.first),
|
|
Tuple2Serializer(
|
|
dartTypeSerializer,
|
|
Bind(
|
|
Tuple2Serializer(Optional(variableDeclarationSerializer),
|
|
Optional(variableDeclarationSerializer)),
|
|
statementSerializer)));
|
|
|
|
TextSerializer<SwitchStatement> switchStatementSerializer = Wrapped(
|
|
(w) => Tuple2(w.expression, w.cases),
|
|
(u) => SwitchStatement(u.first, u.second),
|
|
Tuple2Serializer(
|
|
expressionSerializer,
|
|
Zip(
|
|
Bind(ListSerializer<SwitchCase>(switchCaseSerializer),
|
|
ListSerializer(statementSerializer)),
|
|
(SwitchCase c, Statement b) => c..body = b,
|
|
(SwitchCase z) => Tuple2(z, z.body))));
|
|
|
|
class SwitchCaseTagger implements Tagger<SwitchCase> {
|
|
String tag(SwitchCase node) {
|
|
return node.isDefault ? "default" : "case";
|
|
}
|
|
}
|
|
|
|
TextSerializer<SwitchCase> switchCaseCaseSerializer = Wrapped(
|
|
(w) => Tuple2("L", w),
|
|
(u) => u.second,
|
|
Binder(Wrapped(
|
|
(w) => w.expressions,
|
|
(u) => SwitchCase(u, List.filled(u.length, 0), null),
|
|
ListSerializer(expressionSerializer))));
|
|
|
|
TextSerializer<SwitchCase> switchCaseDefaultSerializer = Wrapped(
|
|
(w) => Tuple2("L", w),
|
|
(u) => u.second,
|
|
Binder(
|
|
Wrapped((w) => null, (u) => SwitchCase.defaultCase(null), Nothing())));
|
|
|
|
TextSerializer<SwitchCase> switchCaseSerializer = Case(SwitchCaseTagger(), {
|
|
"case": switchCaseCaseSerializer,
|
|
"default": switchCaseDefaultSerializer,
|
|
});
|
|
|
|
TextSerializer<ContinueSwitchStatement> continueSwitchStatementSerializer =
|
|
Wrapped((w) => w.target, (u) => ContinueSwitchStatement(u), ScopedUse());
|
|
|
|
TextSerializer<FunctionDeclaration> functionDeclarationSerializer = Wrapped(
|
|
(w) => Tuple2(w.variable, w.function),
|
|
(u) => FunctionDeclaration(u.first, u.second),
|
|
Rebind(variableDeclarationSerializer, functionNodeSerializer));
|
|
|
|
Case<Statement> statementSerializer =
|
|
new Case.uninitialized(const StatementTagger());
|
|
|
|
const Map<AsyncMarker, String> asyncMarkerToName = {
|
|
AsyncMarker.Async: "async",
|
|
AsyncMarker.Sync: "sync",
|
|
AsyncMarker.AsyncStar: "async-star",
|
|
AsyncMarker.SyncStar: "sync-star",
|
|
AsyncMarker.SyncYielding: "sync-yielding",
|
|
};
|
|
|
|
class AsyncMarkerTagger implements Tagger<AsyncMarker> {
|
|
const AsyncMarkerTagger();
|
|
|
|
String tag(AsyncMarker node) {
|
|
return asyncMarkerToName[node] ?? (throw new UnsupportedError("${node}"));
|
|
}
|
|
}
|
|
|
|
TextSerializer<AsyncMarker> asyncMarkerSerializer = Case(
|
|
AsyncMarkerTagger(),
|
|
Map.fromIterable(asyncMarkerToName.entries,
|
|
key: (e) => e.value,
|
|
value: (e) => Wrapped((_) => null, (_) => e.key, Nothing())));
|
|
|
|
TextSerializer<Tuple2<FunctionNode, List<Initializer>>>
|
|
functionNodeWithInitializersSerializer = Wrapped(
|
|
(w) => Tuple2(
|
|
w.first.asyncMarker,
|
|
Tuple2(
|
|
Tuple2(
|
|
w.first.typeParameters,
|
|
Tuple3(
|
|
w.first.positionalParameters
|
|
.sublist(0, w.first.requiredParameterCount),
|
|
w.first.positionalParameters
|
|
.sublist(w.first.requiredParameterCount),
|
|
w.first.namedParameters)),
|
|
Tuple3(w.first.returnType, w.second, w.first.body))),
|
|
(u) => Tuple2(
|
|
FunctionNode(u.second.second.third,
|
|
typeParameters: u.second.first.first,
|
|
positionalParameters:
|
|
u.second.first.second.first + u.second.first.second.second,
|
|
namedParameters: u.second.first.second.third,
|
|
requiredParameterCount: u.second.first.second.first.length,
|
|
returnType: u.second.second.first,
|
|
asyncMarker: u.first),
|
|
u.second.second.second),
|
|
Tuple2Serializer(
|
|
asyncMarkerSerializer,
|
|
Bind(
|
|
Rebind(
|
|
typeParametersSerializer,
|
|
Tuple3Serializer(
|
|
ListSerializer(variableDeclarationSerializer),
|
|
ListSerializer(variableDeclarationSerializer),
|
|
ListSerializer(variableDeclarationSerializer))),
|
|
Tuple3Serializer(
|
|
dartTypeSerializer,
|
|
Optional(ListSerializer(initializerSerializer)),
|
|
Optional(statementSerializer)))));
|
|
|
|
TextSerializer<FunctionNode> functionNodeSerializer = Wrapped(
|
|
(w) => Tuple2(w, null),
|
|
(u) => u.first,
|
|
functionNodeWithInitializersSerializer);
|
|
|
|
const Map<int, String> procedureFlagToName = const {
|
|
Procedure.FlagStatic: "static",
|
|
Procedure.FlagAbstract: "abstract",
|
|
Procedure.FlagExternal: "external",
|
|
Procedure.FlagConst: "const",
|
|
Procedure.FlagForwardingStub: "forwarding-stub",
|
|
Procedure.FlagForwardingSemiStub: "forwarding-semi-stub",
|
|
Procedure.FlagRedirectingFactoryConstructor:
|
|
"redirecting-factory-constructor",
|
|
Procedure.FlagNoSuchMethodForwarder: "no-such-method-forwarder",
|
|
Procedure.FlagExtensionMember: "extension-member",
|
|
Procedure.FlagMemberSignature: "member-signature",
|
|
Procedure.FlagNonNullableByDefault: "non-nullable-by-default",
|
|
};
|
|
|
|
class ProcedureFlagTagger implements Tagger<int> {
|
|
const ProcedureFlagTagger();
|
|
|
|
String tag(int flag) {
|
|
return procedureFlagToName[flag] ??
|
|
(throw StateError("Unknown Procedure flag value: ${flag}."));
|
|
}
|
|
}
|
|
|
|
TextSerializer<int> procedureFlagsSerializer = Wrapped(
|
|
(w) => List.generate(30, (i) => w & (1 << i)).where((f) => f != 0).toList(),
|
|
(u) => u.fold(0, (fs, f) => fs |= f),
|
|
ListSerializer(Case(
|
|
ProcedureFlagTagger(),
|
|
Map.fromIterable(procedureFlagToName.entries,
|
|
key: (e) => e.value,
|
|
value: (e) => Wrapped((_) => null, (_) => e.key, Nothing())))));
|
|
|
|
const Map<int, String> fieldFlagToName = const {
|
|
Field.FlagFinal: "final",
|
|
Field.FlagConst: "const",
|
|
Field.FlagStatic: "static",
|
|
Field.FlagHasImplicitGetter: "has-implicit-getter",
|
|
Field.FlagHasImplicitSetter: "has-implicit-setter",
|
|
Field.FlagCovariant: "covariant",
|
|
Field.FlagGenericCovariantImpl: "generic-covariant-impl",
|
|
Field.FlagLate: "late",
|
|
Field.FlagExtensionMember: "extension-member",
|
|
Field.FlagNonNullableByDefault: "non-nullable-by-default",
|
|
Field.FlagInternalImplementation: "internal-implementation",
|
|
};
|
|
|
|
class FieldFlagTagger implements Tagger<int> {
|
|
const FieldFlagTagger();
|
|
|
|
String tag(int flag) {
|
|
return fieldFlagToName[flag] ??
|
|
(throw StateError("Unknown Field flag value: ${flag}."));
|
|
}
|
|
}
|
|
|
|
TextSerializer<int> fieldFlagsSerializer = Wrapped(
|
|
(w) => List.generate(30, (i) => w & (1 << i)).where((f) => f != 0).toList(),
|
|
(u) => u.fold(0, (fs, f) => fs |= f),
|
|
ListSerializer(Case(
|
|
FieldFlagTagger(),
|
|
Map.fromIterable(fieldFlagToName.entries,
|
|
key: (e) => e.value,
|
|
value: (e) => Wrapped((_) => null, (_) => e.key, Nothing())))));
|
|
|
|
const Map<int, String> constructorFlagToName = const {
|
|
Constructor.FlagConst: "const",
|
|
Constructor.FlagExternal: "external",
|
|
Constructor.FlagSynthetic: "synthetic",
|
|
Constructor.FlagNonNullableByDefault: "non-nullable-by-default",
|
|
};
|
|
|
|
class ConstructorFlagTagger implements Tagger<int> {
|
|
const ConstructorFlagTagger();
|
|
|
|
String tag(int flag) {
|
|
return constructorFlagToName[flag] ??
|
|
(throw StateError("Unknown Constructor flag value: ${flag}."));
|
|
}
|
|
}
|
|
|
|
TextSerializer<int> constructorFlagsSerializer = Wrapped(
|
|
(w) => List.generate(30, (i) => w & (1 << i)).where((f) => f != 0).toList(),
|
|
(u) => u.fold(0, (fs, f) => fs |= f),
|
|
ListSerializer(Case(
|
|
ConstructorFlagTagger(),
|
|
Map.fromIterable(constructorFlagToName.entries,
|
|
key: (e) => e.value,
|
|
value: (e) => Wrapped((_) => null, (_) => e.key, Nothing())))));
|
|
|
|
const Map<int, String> redirectingFactoryConstructorFlagToName = const {
|
|
RedirectingFactoryConstructor.FlagConst: "const",
|
|
RedirectingFactoryConstructor.FlagExternal: "external",
|
|
RedirectingFactoryConstructor.FlagNonNullableByDefault:
|
|
"non-nullable-by-default",
|
|
};
|
|
|
|
class RedirectingFactoryConstructorFlagTagger implements Tagger<int> {
|
|
const RedirectingFactoryConstructorFlagTagger();
|
|
|
|
String tag(int flag) {
|
|
return redirectingFactoryConstructorFlagToName[flag] ??
|
|
(throw StateError(
|
|
"Unknown RedirectingFactoryConstructor flag value: ${flag}."));
|
|
}
|
|
}
|
|
|
|
TextSerializer<int> redirectingFactoryConstructorFlagsSerializer = Wrapped(
|
|
(w) => List.generate(30, (i) => w & (1 << i)).where((f) => f != 0).toList(),
|
|
(u) => u.fold(0, (fs, f) => fs |= f),
|
|
ListSerializer(Case(
|
|
RedirectingFactoryConstructorFlagTagger(),
|
|
Map.fromIterable(redirectingFactoryConstructorFlagToName.entries,
|
|
key: (e) => e.value,
|
|
value: (e) => Wrapped((_) => null, (_) => e.key, Nothing())))));
|
|
|
|
class MemberTagger implements Tagger<Member> {
|
|
const MemberTagger();
|
|
|
|
String tag(Member node) {
|
|
if (node is Field) {
|
|
return "field";
|
|
} else if (node is Constructor) {
|
|
return "constructor";
|
|
} else if (node is RedirectingFactoryConstructor) {
|
|
return "redirecting-factory-constructor";
|
|
} else if (node is Procedure) {
|
|
switch (node.kind) {
|
|
case ProcedureKind.Method:
|
|
return "method";
|
|
case ProcedureKind.Getter:
|
|
return "getter";
|
|
case ProcedureKind.Setter:
|
|
return "setter";
|
|
case ProcedureKind.Operator:
|
|
return "operator";
|
|
case ProcedureKind.Factory:
|
|
return "factory";
|
|
default:
|
|
throw new UnsupportedError("MemberTagger.tag(${node.kind})");
|
|
}
|
|
} else {
|
|
throw UnimplementedError("MemberTagger.tag(${node.runtimeType})");
|
|
}
|
|
}
|
|
}
|
|
|
|
TextSerializer<Field> fieldSerializer = Wrapped(
|
|
(w) => Tuple4(w.name, w.flags, w.type, w.initializer),
|
|
(u) =>
|
|
Field(u.first, type: u.third, initializer: u.fourth)..flags = u.second,
|
|
Tuple4Serializer(nameSerializer, fieldFlagsSerializer, dartTypeSerializer,
|
|
Optional(expressionSerializer)));
|
|
|
|
TextSerializer<Procedure> methodSerializer = Wrapped(
|
|
(w) => Tuple3(w.name, w.flags, w.function),
|
|
(u) => Procedure(u.first, ProcedureKind.Method, u.third)..flags = u.second,
|
|
Tuple3Serializer(
|
|
nameSerializer, procedureFlagsSerializer, functionNodeSerializer));
|
|
|
|
TextSerializer<Procedure> getterSerializer = Wrapped(
|
|
(w) => Tuple3(w.name, w.flags, w.function),
|
|
(u) => Procedure(u.first, ProcedureKind.Getter, u.third)..flags = u.second,
|
|
Tuple3Serializer(
|
|
nameSerializer, procedureFlagsSerializer, functionNodeSerializer));
|
|
|
|
TextSerializer<Procedure> setterSerializer = Wrapped(
|
|
(w) => Tuple3(w.name, w.flags, w.function),
|
|
(u) => Procedure(u.first, ProcedureKind.Setter, u.third)..flags = u.second,
|
|
Tuple3Serializer(
|
|
nameSerializer, procedureFlagsSerializer, functionNodeSerializer));
|
|
|
|
TextSerializer<Procedure> operatorSerializer = Wrapped(
|
|
(w) => Tuple3(w.name, w.flags, w.function),
|
|
(u) =>
|
|
Procedure(u.first, ProcedureKind.Operator, u.third)..flags = u.second,
|
|
Tuple3Serializer(
|
|
nameSerializer, procedureFlagsSerializer, functionNodeSerializer));
|
|
|
|
TextSerializer<Procedure> factorySerializer = Wrapped(
|
|
(w) => Tuple3(w.name, w.flags, w.function),
|
|
(u) => Procedure(u.first, ProcedureKind.Factory, u.third)..flags = u.second,
|
|
Tuple3Serializer(
|
|
nameSerializer, procedureFlagsSerializer, functionNodeSerializer));
|
|
|
|
TextSerializer<Constructor> constructorSerializer = Wrapped(
|
|
(w) => Tuple3(w.name, w.flags, Tuple2(w.function, w.initializers)),
|
|
(u) =>
|
|
Constructor(u.third.first, name: u.first, initializers: u.third.second)
|
|
..flags = u.second,
|
|
Tuple3Serializer(nameSerializer, constructorFlagsSerializer,
|
|
functionNodeWithInitializersSerializer));
|
|
|
|
TextSerializer<RedirectingFactoryConstructor>
|
|
redirectingFactoryConstructorSerializer = Wrapped(
|
|
(w) => Tuple4(
|
|
w.name,
|
|
w.flags,
|
|
w.targetReference.canonicalName,
|
|
Tuple2(
|
|
w.typeParameters,
|
|
Tuple4(
|
|
w.positionalParameters
|
|
.take(w.requiredParameterCount)
|
|
.toList(),
|
|
w.positionalParameters
|
|
.skip(w.requiredParameterCount)
|
|
.toList(),
|
|
w.namedParameters,
|
|
w.typeArguments))),
|
|
(u) => RedirectingFactoryConstructor(u.third,
|
|
name: u.first,
|
|
typeParameters: u.fourth.first,
|
|
positionalParameters:
|
|
u.fourth.second.first + u.fourth.second.second,
|
|
requiredParameterCount: u.fourth.second.first.length,
|
|
namedParameters: u.fourth.second.third,
|
|
typeArguments: u.fourth.second.fourth)
|
|
..flags = u.second,
|
|
Tuple4Serializer(
|
|
nameSerializer,
|
|
redirectingFactoryConstructorFlagsSerializer,
|
|
CanonicalNameSerializer(),
|
|
Bind(
|
|
typeParametersSerializer,
|
|
Tuple4Serializer(
|
|
ListSerializer(variableDeclarationSerializer),
|
|
ListSerializer(variableDeclarationSerializer),
|
|
ListSerializer(variableDeclarationSerializer),
|
|
ListSerializer(dartTypeSerializer)))));
|
|
|
|
Case<Member> memberSerializer = new Case.uninitialized(const MemberTagger());
|
|
|
|
TextSerializer<LibraryPart> libraryPartSerializer = Wrapped(
|
|
(w) => Tuple2(w.partUri, w.annotations),
|
|
(u) => LibraryPart(u.second, u.first),
|
|
Tuple2Serializer(DartString(), ListSerializer(expressionSerializer)));
|
|
|
|
class LibraryTagger implements Tagger<Library> {
|
|
const LibraryTagger();
|
|
|
|
String tag(Library node) {
|
|
return node.isNonNullableByDefault ? "null-safe" : "legacy";
|
|
}
|
|
}
|
|
|
|
const Map<int, String> libraryFlagToName = const {
|
|
Library.SyntheticFlag: "synthetic",
|
|
Library.NonNullableByDefaultFlag: "nnbd",
|
|
Library.NonNullableByDefaultModeBit1Weak: "nnbd-weak",
|
|
Library.NonNullableByDefaultModeBit2Strong: "nnbd-strong",
|
|
};
|
|
|
|
class LibraryFlagTagger implements Tagger<int> {
|
|
const LibraryFlagTagger();
|
|
|
|
String tag(int flag) {
|
|
return libraryFlagToName[flag] ??
|
|
(throw StateError("Unknown Library flag value: ${flag}."));
|
|
}
|
|
}
|
|
|
|
TextSerializer<int> libraryFlagsSerializer = Wrapped(
|
|
(w) => List.generate(30, (i) => w & (1 << i)).where((f) => f != 0).toList(),
|
|
(u) => u.fold(0, (fs, f) => fs |= f),
|
|
ListSerializer(Case(
|
|
LibraryFlagTagger(),
|
|
Map.fromIterable(libraryFlagToName.entries,
|
|
key: (e) => e.value,
|
|
value: (e) => Wrapped((_) => null, (_) => e.key, Nothing())))));
|
|
|
|
TextSerializer<Library> librarySerializer = new Wrapped(
|
|
(w) => Tuple7(w.importUri, w.flags, w.parts, [...w.fields, ...w.procedures],
|
|
w.classes, w.typedefs, w.extensions),
|
|
(u) => Library(u.first,
|
|
parts: u.third,
|
|
fields: u.fourth.where((m) => m is Field).cast<Field>().toList(),
|
|
procedures:
|
|
u.fourth.where((m) => m is Procedure).cast<Procedure>().toList(),
|
|
classes: u.fifth,
|
|
typedefs: u.sixth,
|
|
extensions: u.seventh)
|
|
..flags = u.second,
|
|
Tuple7Serializer(
|
|
UriSerializer(),
|
|
libraryFlagsSerializer,
|
|
ListSerializer(libraryPartSerializer),
|
|
ListSerializer(memberSerializer),
|
|
ListSerializer(classSerializer),
|
|
ListSerializer(typedefSerializer),
|
|
ListSerializer(extensionSerializer)),
|
|
);
|
|
|
|
TextSerializer<Component> componentSerializer = Wrapped(
|
|
(w) => w.libraries,
|
|
(u) => Component(nameRoot: CanonicalName.root(), libraries: u),
|
|
ListSerializer(librarySerializer));
|
|
|
|
class ShowHideTagger implements Tagger<Combinator> {
|
|
String tag(Combinator node) => node.isShow ? "show" : "hide";
|
|
}
|
|
|
|
TextSerializer<Combinator> showSerializer = Wrapped(
|
|
(c) => c.names, (ns) => Combinator(true, ns), ListSerializer(DartString()));
|
|
|
|
TextSerializer<Combinator> hideSerializer = Wrapped((c) => c.names,
|
|
(ns) => Combinator(false, ns), ListSerializer(DartString()));
|
|
|
|
Case<Combinator> showHideSerializer = new Case(ShowHideTagger(), {
|
|
"show": showSerializer,
|
|
"hide": hideSerializer,
|
|
});
|
|
|
|
TextSerializer<LibraryDependency> libraryDependencySerializer = Wrapped(
|
|
(ld) => Tuple5(ld.importedLibraryReference.canonicalName, ld.name,
|
|
ld.combinators, ld.flags, ld.annotations),
|
|
(t) => LibraryDependency.byReference(
|
|
t.fourth, t.fifth, t.first.getReference(), t.second, t.third),
|
|
Tuple5Serializer(
|
|
CanonicalNameSerializer(),
|
|
Optional(DartString()),
|
|
ListSerializer(showHideSerializer),
|
|
DartInt(),
|
|
ListSerializer(expressionSerializer)));
|
|
|
|
class ConstantTagger extends ConstantVisitor<String>
|
|
implements Tagger<Constant> {
|
|
const ConstantTagger();
|
|
|
|
String tag(Constant node) => node.accept(this);
|
|
|
|
String visitBoolConstant(BoolConstant node) => "const-bool";
|
|
String visitDoubleConstant(DoubleConstant node) => "const-double";
|
|
String visitInstanceConstant(InstanceConstant node) => "const-object";
|
|
String visitIntConstant(IntConstant node) => "const-int";
|
|
String visitListConstant(ListConstant node) => "const-list";
|
|
String visitMapConstant(MapConstant node) => "const-map";
|
|
String visitNullConstant(NullConstant node) => "const-null";
|
|
String visitPartialInstantiationConstant(PartialInstantiationConstant node) =>
|
|
"const-apply";
|
|
String visitSetConstant(SetConstant node) => "const-set";
|
|
String visitStringConstant(StringConstant node) => "const-string";
|
|
String visitSymbolConstant(SymbolConstant node) => "const-symbol";
|
|
String visitTearOffConstant(TearOffConstant node) => "const-tearoff";
|
|
String visitTypeLiteralConstant(TypeLiteralConstant node) => "const-type";
|
|
String visitUnevaluatedConstant(UnevaluatedConstant node) => "const-expr";
|
|
}
|
|
|
|
TextSerializer<BoolConstant> boolConstantSerializer =
|
|
Wrapped((w) => w.value, (u) => BoolConstant(u), DartBool());
|
|
|
|
TextSerializer<DoubleConstant> doubleConstantSerializer =
|
|
Wrapped((w) => w.value, (u) => DoubleConstant(u), DartDouble());
|
|
|
|
TextSerializer<IntConstant> intConstantSerializer =
|
|
Wrapped((w) => w.value, (u) => IntConstant(u), DartInt());
|
|
|
|
TextSerializer<ListConstant> listConstantSerializer = Wrapped(
|
|
(w) => Tuple2(w.typeArgument, w.entries),
|
|
(u) => ListConstant(u.first, u.second),
|
|
Tuple2Serializer(dartTypeSerializer, ListSerializer(constantSerializer)));
|
|
|
|
TextSerializer<MapConstant> mapConstantSerializer = Wrapped(
|
|
(w) => Tuple3(w.keyType, w.valueType, w.entries),
|
|
(u) => MapConstant(u.first, u.second, u.third),
|
|
Tuple3Serializer(
|
|
dartTypeSerializer,
|
|
dartTypeSerializer,
|
|
Zip(
|
|
Tuple2Serializer(ListSerializer(constantSerializer),
|
|
ListSerializer(constantSerializer)),
|
|
(k, v) => ConstantMapEntry(k, v),
|
|
(z) => Tuple2(z.key, z.value))));
|
|
|
|
TextSerializer<NullConstant> nullConstantSerializer =
|
|
Wrapped((w) => null, (u) => NullConstant(), Nothing());
|
|
|
|
TextSerializer<PartialInstantiationConstant>
|
|
partialInstantiationConstantSerializer = Wrapped(
|
|
(w) => Tuple2(w.tearOffConstant, w.types),
|
|
(u) => PartialInstantiationConstant(u.first, u.second),
|
|
Tuple2Serializer(
|
|
tearOffConstantSerializer, ListSerializer(dartTypeSerializer)));
|
|
|
|
TextSerializer<SetConstant> setConstantSerializer = Wrapped(
|
|
(w) => Tuple2(w.typeArgument, w.entries),
|
|
(u) => SetConstant(u.first, u.second),
|
|
Tuple2Serializer(dartTypeSerializer, ListSerializer(constantSerializer)));
|
|
|
|
TextSerializer<StringConstant> stringConstantSerializer =
|
|
Wrapped((w) => w.value, (u) => StringConstant(u), DartString());
|
|
|
|
TextSerializer<SymbolConstant> symbolConstantSerializer = Wrapped(
|
|
(w) => Tuple2(w.name, w.libraryReference?.canonicalName),
|
|
(u) => SymbolConstant(u.first, u.second?.getReference()),
|
|
Tuple2Serializer(DartString(), Optional(CanonicalNameSerializer())));
|
|
|
|
TextSerializer<TearOffConstant> tearOffConstantSerializer = Wrapped(
|
|
(w) => w.procedureReference.canonicalName,
|
|
(u) => TearOffConstant.byReference(u.getReference()),
|
|
CanonicalNameSerializer());
|
|
|
|
TextSerializer<TypeLiteralConstant> typeLiteralConstantSerializer =
|
|
Wrapped((w) => w.type, (u) => TypeLiteralConstant(u), dartTypeSerializer);
|
|
|
|
TextSerializer<UnevaluatedConstant> unevaluatedConstantSerializer = Wrapped(
|
|
(w) => w.expression, (u) => UnevaluatedConstant(u), expressionSerializer);
|
|
|
|
TextSerializer<InstanceConstant> instanceConstantSerializer =
|
|
Wrapped<
|
|
Tuple4<CanonicalName, List<DartType>, List<CanonicalName>,
|
|
List<Constant>>,
|
|
InstanceConstant>(
|
|
(w) => Tuple4(
|
|
w.classReference.canonicalName,
|
|
w.typeArguments,
|
|
w.fieldValues.keys.map((r) => r.canonicalName).toList(),
|
|
w.fieldValues.values.toList()),
|
|
(u) => InstanceConstant(u.first.getReference(), u.second,
|
|
Map.fromIterables(u.third.map((c) => c.getReference()), u.fourth)),
|
|
Tuple4Serializer(
|
|
CanonicalNameSerializer(),
|
|
ListSerializer(dartTypeSerializer),
|
|
ListSerializer(CanonicalNameSerializer()),
|
|
ListSerializer(constantSerializer)));
|
|
|
|
Case<Constant> constantSerializer = Case.uninitialized(ConstantTagger());
|
|
|
|
class InitializerTagger implements Tagger<Initializer> {
|
|
const InitializerTagger();
|
|
|
|
String tag(Initializer node) {
|
|
if (node is AssertInitializer) {
|
|
return "assert";
|
|
} else if (node is FieldInitializer) {
|
|
return "field";
|
|
} else if (node is InvalidInitializer) {
|
|
return "invalid";
|
|
} else if (node is LocalInitializer) {
|
|
return "local";
|
|
} else if (node is RedirectingInitializer) {
|
|
return "redirecting";
|
|
} else if (node is SuperInitializer) {
|
|
return "super";
|
|
} else {
|
|
throw UnimplementedError("InitializerTagger.tag(${node.runtimeType}).");
|
|
}
|
|
}
|
|
}
|
|
|
|
TextSerializer<AssertInitializer> assertInitializerSerializer = Wrapped(
|
|
(w) => w.statement, (u) => AssertInitializer(u), statementSerializer);
|
|
|
|
TextSerializer<FieldInitializer> fieldInitializerSerializer = Wrapped(
|
|
(w) => Tuple2(w.fieldReference.canonicalName, w.value),
|
|
(u) => FieldInitializer.byReference(u.first.getReference(), u.second),
|
|
Tuple2Serializer(CanonicalNameSerializer(), expressionSerializer));
|
|
|
|
TextSerializer<InvalidInitializer> invalidInitializerSerializer =
|
|
Wrapped((_) => null, (_) => InvalidInitializer(), Nothing());
|
|
|
|
TextSerializer<LocalInitializer> localInitializerSerializer = Wrapped(
|
|
(w) => w.variable,
|
|
(u) => LocalInitializer(u),
|
|
variableDeclarationSerializer);
|
|
|
|
TextSerializer<RedirectingInitializer> redirectingInitializerSerializer =
|
|
Wrapped(
|
|
(w) => Tuple2(w.targetReference.canonicalName, w.arguments),
|
|
(u) => RedirectingInitializer.byReference(
|
|
u.first.getReference(), u.second),
|
|
Tuple2Serializer(CanonicalNameSerializer(), argumentsSerializer));
|
|
|
|
TextSerializer<SuperInitializer> superInitializerSerializer = Wrapped(
|
|
(w) => Tuple2(w.targetReference.canonicalName, w.arguments),
|
|
(u) => SuperInitializer.byReference(u.first.getReference(), u.second),
|
|
Tuple2Serializer(CanonicalNameSerializer(), argumentsSerializer));
|
|
|
|
Case<Initializer> initializerSerializer =
|
|
Case.uninitialized(InitializerTagger());
|
|
|
|
TextSerializer<Supertype> supertypeSerializer = Wrapped(
|
|
(w) => Tuple2(w.className.canonicalName, w.typeArguments),
|
|
(u) => Supertype.byReference(u.first.getReference(), u.second),
|
|
Tuple2Serializer(
|
|
CanonicalNameSerializer(), ListSerializer(dartTypeSerializer)));
|
|
|
|
const Map<int, String> classFlagToName = const {
|
|
Class.FlagAbstract: "abstract",
|
|
Class.FlagEnum: "enum",
|
|
Class.FlagAnonymousMixin: "anonymous-mixin",
|
|
Class.FlagEliminatedMixin: "eliminated-mixin",
|
|
Class.FlagMixinDeclaration: "mixin-declaration",
|
|
Class.FlagHasConstConstructor: "has-const-constructor",
|
|
};
|
|
|
|
class ClassFlagTagger implements Tagger<int> {
|
|
const ClassFlagTagger();
|
|
|
|
String tag(int flag) {
|
|
return classFlagToName[flag] ??
|
|
(throw StateError("Unknown Class flag value: ${flag}."));
|
|
}
|
|
}
|
|
|
|
TextSerializer<int> classFlagsSerializer = Wrapped(
|
|
(w) => List.generate(30, (i) => w & (1 << i)).where((f) => f != 0).toList(),
|
|
(u) => u.fold(0, (fs, f) => fs |= f),
|
|
ListSerializer(Case(
|
|
ClassFlagTagger(),
|
|
Map.fromIterable(classFlagToName.entries,
|
|
key: (e) => e.value,
|
|
value: (e) => Wrapped((_) => null, (_) => e.key, Nothing())))));
|
|
|
|
TextSerializer<Class> classSerializer = Wrapped(
|
|
(w) => Tuple3(
|
|
w.name,
|
|
w.flags,
|
|
Tuple2(
|
|
w.typeParameters,
|
|
Tuple4(w.supertype, w.mixedInType, w.implementedTypes,
|
|
<Member>[...w.fields, ...w.constructors, ...w.procedures]))),
|
|
(u) => Class(
|
|
name: u.first,
|
|
typeParameters: u.third.first,
|
|
supertype: u.third.second.first,
|
|
mixedInType: u.third.second.second,
|
|
implementedTypes: u.third.second.third,
|
|
fields: u.third.second.fourth
|
|
.where((m) => m is Field)
|
|
.cast<Field>()
|
|
.toList(),
|
|
constructors: u.third.second.fourth
|
|
.where((m) => m is Constructor)
|
|
.cast<Constructor>()
|
|
.toList(),
|
|
procedures: u.third.second.fourth
|
|
.where((m) => m is Procedure)
|
|
.cast<Procedure>()
|
|
.toList())
|
|
..flags = u.second,
|
|
Tuple3Serializer(
|
|
DartString(),
|
|
classFlagsSerializer,
|
|
Bind(
|
|
typeParametersSerializer,
|
|
Tuple4Serializer(
|
|
Optional(supertypeSerializer),
|
|
Optional(supertypeSerializer),
|
|
ListSerializer(supertypeSerializer),
|
|
ListSerializer(memberSerializer)))));
|
|
|
|
TextSerializer<Typedef> typedefSerializer = Wrapped(
|
|
(w) => Tuple2(w.name, Tuple2(w.typeParameters, w.type)),
|
|
(u) => Typedef(u.first, u.second.second, typeParameters: u.second.first),
|
|
Tuple2Serializer(
|
|
DartString(), Bind(typeParametersSerializer, dartTypeSerializer)));
|
|
|
|
const Map<int, String> extensionMemberDescriptorFlagToName = const {
|
|
ExtensionMemberDescriptor.FlagStatic: "static",
|
|
};
|
|
|
|
class ExtensionMemberDescriptorFlagTagger implements Tagger<int> {
|
|
const ExtensionMemberDescriptorFlagTagger();
|
|
|
|
String tag(int flag) {
|
|
return extensionMemberDescriptorFlagToName[flag] ??
|
|
(throw StateError(
|
|
"Unknown ExtensionMemberDescriptor flag value: ${flag}."));
|
|
}
|
|
}
|
|
|
|
TextSerializer<int> extensionMemberDescriptorFlagsSerializer = Wrapped(
|
|
(w) => List.generate(30, (i) => w & (1 << i)).where((f) => f != 0).toList(),
|
|
(u) => u.fold(0, (fs, f) => fs |= f),
|
|
ListSerializer(Case(
|
|
ExtensionMemberDescriptorFlagTagger(),
|
|
Map.fromIterable(extensionMemberDescriptorFlagToName.entries,
|
|
key: (e) => e.value,
|
|
value: (e) => Wrapped((_) => null, (_) => e.key, Nothing())))));
|
|
|
|
const Map<ExtensionMemberKind, String> extensionMemberKindToName = const {
|
|
ExtensionMemberKind.Field: "field",
|
|
ExtensionMemberKind.Method: "method",
|
|
ExtensionMemberKind.Getter: "getter",
|
|
ExtensionMemberKind.Setter: "setter",
|
|
ExtensionMemberKind.Operator: "operator",
|
|
ExtensionMemberKind.TearOff: "tearOff",
|
|
};
|
|
|
|
class ExtensionMemberKindTagger implements Tagger<ExtensionMemberKind> {
|
|
const ExtensionMemberKindTagger();
|
|
|
|
String tag(ExtensionMemberKind kind) {
|
|
return extensionMemberKindToName[kind] ??
|
|
(throw StateError("Unknown ExtensionMemberKind flag value: ${kind}."));
|
|
}
|
|
}
|
|
|
|
TextSerializer<ExtensionMemberKind> extensionMemberKindSerializer = Case(
|
|
ExtensionMemberKindTagger(),
|
|
Map.fromIterable(extensionMemberKindToName.entries,
|
|
key: (e) => e.value,
|
|
value: (e) => Wrapped((_) => null, (_) => e.key, Nothing())));
|
|
|
|
TextSerializer<ExtensionMemberDescriptor> extensionMemberDescriptorSerializer =
|
|
Wrapped(
|
|
(w) => Tuple4(w.name, w.kind, w.flags, w.member.canonicalName),
|
|
(u) => ExtensionMemberDescriptor()
|
|
..name = u.first
|
|
..kind = u.second
|
|
..flags = u.third
|
|
..member = u.fourth.getReference(),
|
|
Tuple4Serializer(
|
|
nameSerializer,
|
|
extensionMemberKindSerializer,
|
|
extensionMemberDescriptorFlagsSerializer,
|
|
CanonicalNameSerializer()));
|
|
|
|
TextSerializer<Extension> extensionSerializer = Wrapped(
|
|
(w) => Tuple3(w.name, Tuple2(w.typeParameters, w.onType), w.members),
|
|
(u) => Extension(
|
|
name: u.first,
|
|
typeParameters: u.second.first,
|
|
onType: u.second.second,
|
|
members: u.third),
|
|
Tuple3Serializer(
|
|
DartString(),
|
|
Bind(typeParametersSerializer, dartTypeSerializer),
|
|
ListSerializer(extensionMemberDescriptorSerializer)));
|
|
|
|
void initializeSerializers() {
|
|
expressionSerializer.registerTags({
|
|
"string": stringLiteralSerializer,
|
|
"int": intLiteralSerializer,
|
|
"double": doubleLiteralSerializer,
|
|
"bool": boolLiteralSerializer,
|
|
"null": nullLiteralSerializer,
|
|
"invalid": invalidExpressionSerializer,
|
|
"not": notSerializer,
|
|
"&&": logicalAndSerializer,
|
|
"||": logicalOrSerializer,
|
|
"concat": stringConcatenationSerializer,
|
|
"symbol": symbolLiteralSerializer,
|
|
"this": thisExpressionSerializer,
|
|
"rethrow": rethrowSerializer,
|
|
"throw": throwSerializer,
|
|
"await": awaitExpressionSerializer,
|
|
"cond": conditionalExpressionSerializer,
|
|
"is": isExpressionSerializer,
|
|
"as": asExpressionSerializer,
|
|
"type": typeLiteralSerializer,
|
|
"list": listLiteralSerializer,
|
|
"const-list": constListLiteralSerializer,
|
|
"set": setLiteralSerializer,
|
|
"const-set": constSetLiteralSerializer,
|
|
"map": mapLiteralSerializer,
|
|
"const-map": constMapLiteralSerializer,
|
|
"let": letSerializer,
|
|
"get-prop": propertyGetSerializer,
|
|
"set-prop": propertySetSerializer,
|
|
"get-super": superPropertyGetSerializer,
|
|
"set-super": superPropertySetSerializer,
|
|
"invoke-method": methodInvocationSerializer,
|
|
"invoke-super": superMethodInvocationSerializer,
|
|
"get-var": variableGetSerializer,
|
|
"set-var": variableSetSerializer,
|
|
"get-static": staticGetSerializer,
|
|
"set-static": staticSetSerializer,
|
|
"get-direct-prop": directPropertyGetSerializer,
|
|
"set-direct-prop": directPropertySetSerializer,
|
|
"invoke-static": staticInvocationSerializer,
|
|
"invoke-const-static": constStaticInvocationSerializer,
|
|
"invoke-direct-method": directMethodInvocationSerializer,
|
|
"invoke-constructor": constructorInvocationSerializer,
|
|
"invoke-const-constructor": constConstructorInvocationSerializer,
|
|
"fun": functionExpressionSerializer,
|
|
"lists": listConcatenationSerializer,
|
|
"sets": setConcatenationSerializer,
|
|
"maps": mapConcatenationSerializer,
|
|
"let-block": blockExpressionSerializer,
|
|
"apply": instantiationSerializer,
|
|
"not-null": nullCheckSerializer,
|
|
"with-uri": fileUriExpressionSerializer,
|
|
"is-loaded": checkLibraryIsLoadedSerializer,
|
|
"load": loadLibrarySerializer,
|
|
"const": constantExpressionSerializer,
|
|
"object": instanceCreationSerializer,
|
|
});
|
|
dartTypeSerializer.registerTags({
|
|
"invalid": invalidTypeSerializer,
|
|
"dynamic": dynamicTypeSerializer,
|
|
"void": voidTypeSerializer,
|
|
"bottom": bottomTypeSerializer,
|
|
"->": functionTypeSerializer,
|
|
"par": typeParameterTypeSerializer,
|
|
"interface": interfaceTypeSerializer,
|
|
"never": neverTypeSerializer,
|
|
"typedef": typedefTypeSerializer,
|
|
"futureor": futureOrTypeSerializer,
|
|
});
|
|
statementSerializer.registerTags({
|
|
"expr": expressionStatementSerializer,
|
|
"ret": returnStatementSerializer,
|
|
"ret-void": returnVoidStatementSerializer,
|
|
"yield": yieldStatementSerializer,
|
|
"block": blockSerializer,
|
|
"local": variableDeclarationSerializer,
|
|
"if": ifStatementSerializer,
|
|
"if-else": ifElseStatementSerializer,
|
|
"skip": emptyStatementSerializer,
|
|
"while": whileStatementSerializer,
|
|
"do-while": doStatementSerializer,
|
|
"for": forStatementSerializer,
|
|
"for-in": forInStatementSerializer,
|
|
"await-for-in": awaitForInStatementSerializer,
|
|
"assert": assertStatementSerializer,
|
|
"assert-block": assertBlockSerializer,
|
|
"label": labeledStatementSerializer,
|
|
"break": breakSerializer,
|
|
"try-finally": tryFinallySerializer,
|
|
"try-catch": tryCatchSerializer,
|
|
"switch": switchStatementSerializer,
|
|
"continue": continueSwitchStatementSerializer,
|
|
"local-fun": functionDeclarationSerializer,
|
|
});
|
|
memberSerializer.registerTags({
|
|
"field": fieldSerializer,
|
|
"method": methodSerializer,
|
|
"getter": getterSerializer,
|
|
"setter": setterSerializer,
|
|
"operator": operatorSerializer,
|
|
"factory": factorySerializer,
|
|
"constructor": constructorSerializer,
|
|
"redirecting-factory-constructor": redirectingFactoryConstructorSerializer,
|
|
});
|
|
constantSerializer.registerTags({
|
|
"const-bool": boolConstantSerializer,
|
|
"const-double": doubleConstantSerializer,
|
|
"const-int": intConstantSerializer,
|
|
"const-list": listConstantSerializer,
|
|
"const-map": mapConstantSerializer,
|
|
"const-null": nullConstantSerializer,
|
|
"const-apply": partialInstantiationConstantSerializer,
|
|
"const-set": setConstantSerializer,
|
|
"const-string": stringConstantSerializer,
|
|
"const-symbol": symbolConstantSerializer,
|
|
"const-tearoff": tearOffConstantSerializer,
|
|
"const-type": typeLiteralConstantSerializer,
|
|
"const-expr": unevaluatedConstantSerializer,
|
|
"const-object": instanceConstantSerializer,
|
|
});
|
|
initializerSerializer.registerTags({
|
|
"assert": assertInitializerSerializer,
|
|
"field": fieldInitializerSerializer,
|
|
"invalid": invalidInitializerSerializer,
|
|
"local": localInitializerSerializer,
|
|
"redirecting": redirectingInitializerSerializer,
|
|
"super": superInitializerSerializer,
|
|
});
|
|
}
|