7695118aa2
This adds support for detecting macro classes from .dill TEST=pkg/front_end/testcases/macros/macro_class.dart Change-Id: I8d45cafff1b4edaff7e090384be1a1cf9c8087ae Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/224948 Reviewed-by: Chloe Stefantsova <cstefantsova@google.com> Commit-Queue: Johnni Winther <johnniwinther@google.com>
2916 lines
107 KiB
Dart
2916 lines
107 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';
|
|
|
|
abstract class Tagger<T> {
|
|
String tag(T object);
|
|
}
|
|
|
|
class NameTagger implements Tagger<Name> {
|
|
const NameTagger();
|
|
|
|
@override
|
|
String tag(Name name) => name.isPrivate ? "private" : "public";
|
|
}
|
|
|
|
TextSerializer<Name> publicName =
|
|
Wrapped<String, Name>((w) => w.text, (u) => Name(u), const DartString());
|
|
|
|
TextSerializer<Name> privateName = Wrapped<Tuple2<String, CanonicalName>, Name>(
|
|
(w) => Tuple2(w.text, w.library!.reference.canonicalName!),
|
|
(u) => Name.byReference(u.first, u.second.reference),
|
|
Tuple2Serializer(DartString(), CanonicalNameSerializer()));
|
|
|
|
TextSerializer<Name> nameSerializer = new Case(
|
|
const NameTagger(), {"public": publicName, "private": privateName});
|
|
|
|
class ExpressionTagger extends ExpressionVisitor<String>
|
|
implements Tagger<Expression> {
|
|
const ExpressionTagger();
|
|
|
|
@override
|
|
String tag(Expression expression) => expression.accept(this);
|
|
|
|
@override
|
|
String visitStringLiteral(StringLiteral _) => "string";
|
|
@override
|
|
String visitIntLiteral(IntLiteral _) => "int";
|
|
@override
|
|
String visitDoubleLiteral(DoubleLiteral _) => "double";
|
|
@override
|
|
String visitBoolLiteral(BoolLiteral _) => "bool";
|
|
@override
|
|
String visitNullLiteral(NullLiteral _) => "null";
|
|
@override
|
|
String visitInvalidExpression(InvalidExpression _) => "invalid";
|
|
@override
|
|
String visitNot(Not _) => "not";
|
|
@override
|
|
String visitLogicalExpression(LogicalExpression expression) {
|
|
return logicalExpressionOperatorToString(expression.operatorEnum);
|
|
}
|
|
|
|
@override
|
|
String visitStringConcatenation(StringConcatenation _) => "concat";
|
|
@override
|
|
String visitSymbolLiteral(SymbolLiteral _) => "symbol";
|
|
@override
|
|
String visitThisExpression(ThisExpression _) => "this";
|
|
@override
|
|
String visitRethrow(Rethrow _) => "rethrow";
|
|
@override
|
|
String visitThrow(Throw _) => "throw";
|
|
@override
|
|
String visitAwaitExpression(AwaitExpression _) => "await";
|
|
@override
|
|
String visitConditionalExpression(ConditionalExpression _) => "cond";
|
|
@override
|
|
String visitIsExpression(IsExpression _) => "is";
|
|
@override
|
|
String visitAsExpression(AsExpression _) => "as";
|
|
@override
|
|
String visitTypeLiteral(TypeLiteral _) => "type";
|
|
@override
|
|
String visitListLiteral(ListLiteral expression) {
|
|
return expression.isConst ? "const-list" : "list";
|
|
}
|
|
|
|
@override
|
|
String visitSetLiteral(SetLiteral expression) {
|
|
return expression.isConst ? "const-set" : "set";
|
|
}
|
|
|
|
@override
|
|
String visitMapLiteral(MapLiteral expression) {
|
|
return expression.isConst ? "const-map" : "map";
|
|
}
|
|
|
|
@override
|
|
String visitLet(Let _) => "let";
|
|
|
|
@override
|
|
String visitInstanceGet(InstanceGet _) => "get-instance";
|
|
@override
|
|
String visitInstanceSet(InstanceSet _) => "set-instance";
|
|
@override
|
|
String visitDynamicGet(DynamicGet _) => "get-dynamic";
|
|
@override
|
|
String visitDynamicSet(DynamicSet _) => "set-dynamic";
|
|
@override
|
|
String visitInstanceTearOff(InstanceTearOff _) => "tearoff-instance";
|
|
@override
|
|
String visitFunctionTearOff(FunctionTearOff _) => "tearoff-function";
|
|
@override
|
|
String visitSuperPropertyGet(SuperPropertyGet _) => "get-super";
|
|
@override
|
|
String visitSuperPropertySet(SuperPropertySet _) => "set-super";
|
|
@override
|
|
String visitInstanceInvocation(InstanceInvocation _) => "invoke-instance";
|
|
@override
|
|
String visitInstanceGetterInvocation(InstanceGetterInvocation _) =>
|
|
"invoke-instance-getter";
|
|
@override
|
|
String visitDynamicInvocation(DynamicInvocation _) => "invoke-dynamic";
|
|
@override
|
|
String visitFunctionInvocation(FunctionInvocation _) => "invoke-function";
|
|
@override
|
|
String visitLocalFunctionInvocation(LocalFunctionInvocation _) =>
|
|
"invoke-local-function";
|
|
@override
|
|
String visitEqualsNull(EqualsNull _) => "equals-null";
|
|
@override
|
|
String visitEqualsCall(EqualsCall _) => "equals-call";
|
|
@override
|
|
String visitSuperMethodInvocation(SuperMethodInvocation _) => "invoke-super";
|
|
|
|
@override
|
|
String visitVariableGet(VariableGet _) => "get-var";
|
|
@override
|
|
String visitVariableSet(VariableSet _) => "set-var";
|
|
@override
|
|
String visitStaticGet(StaticGet _) => "get-static";
|
|
@override
|
|
String visitStaticSet(StaticSet _) => "set-static";
|
|
@override
|
|
String visitStaticTearOff(StaticTearOff _) => "tearoff-static";
|
|
@override
|
|
String visitConstructorTearOff(ConstructorTearOff _) => "tearoff-constructor";
|
|
@override
|
|
String visitRedirectingFactoryTearOff(RedirectingFactoryTearOff _) =>
|
|
"tearoff-redirecting-factory";
|
|
@override
|
|
String visitTypedefTearOff(TypedefTearOff _) => "tearoff-typedef";
|
|
@override
|
|
String visitStaticInvocation(StaticInvocation expression) {
|
|
return expression.isConst ? "invoke-const-static" : "invoke-static";
|
|
}
|
|
|
|
@override
|
|
String visitConstructorInvocation(ConstructorInvocation expression) {
|
|
return expression.isConst
|
|
? "invoke-const-constructor"
|
|
: "invoke-constructor";
|
|
}
|
|
|
|
@override
|
|
String visitFunctionExpression(FunctionExpression _) => "fun";
|
|
@override
|
|
String visitListConcatenation(ListConcatenation _) => "lists";
|
|
@override
|
|
String visitSetConcatenation(SetConcatenation _) => "sets";
|
|
@override
|
|
String visitMapConcatenation(MapConcatenation _) => "maps";
|
|
@override
|
|
String visitBlockExpression(BlockExpression _) => "let-block";
|
|
@override
|
|
String visitInstantiation(Instantiation _) => "apply";
|
|
@override
|
|
String visitNullCheck(NullCheck _) => "not-null";
|
|
@override
|
|
String visitFileUriExpression(FileUriExpression _) => "with-uri";
|
|
@override
|
|
String visitCheckLibraryIsLoaded(CheckLibraryIsLoaded _) => "is-loaded";
|
|
@override
|
|
String visitLoadLibrary(LoadLibrary _) => "load";
|
|
@override
|
|
String visitConstantExpression(ConstantExpression _) => "const";
|
|
@override
|
|
String visitInstanceCreation(InstanceCreation _) => "object";
|
|
|
|
@override
|
|
String defaultExpression(Expression node) {
|
|
throw new UnimplementedError(
|
|
'Unimplemented expression $node (${node.runtimeType})');
|
|
}
|
|
}
|
|
|
|
TextSerializer<InvalidExpression> invalidExpressionSerializer =
|
|
new Wrapped<Tuple2<String?, Expression?>, InvalidExpression>(
|
|
unwrapInvalidExpression,
|
|
wrapInvalidExpression,
|
|
Tuple2Serializer<String?, Expression?>(
|
|
Optional(DartString()), Optional(expressionSerializer)));
|
|
|
|
Tuple2<String?, Expression?> unwrapInvalidExpression(
|
|
InvalidExpression expression) {
|
|
return Tuple2(expression.message, expression.expression);
|
|
}
|
|
|
|
InvalidExpression wrapInvalidExpression(Tuple2<String?, Expression?> tuple) {
|
|
return new InvalidExpression(tuple.first, tuple.second);
|
|
}
|
|
|
|
TextSerializer<Not> notSerializer =
|
|
new Wrapped<Expression, Not>(unwrapNot, wrapNot, expressionSerializer);
|
|
|
|
Expression unwrapNot(Not expression) => expression.operand;
|
|
|
|
Not wrapNot(Expression operand) => new Not(operand);
|
|
|
|
TextSerializer<LogicalExpression> logicalAndSerializer =
|
|
new Wrapped<Tuple2<Expression, Expression>, LogicalExpression>(
|
|
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, LogicalExpressionOperator.AND, tuple.second);
|
|
}
|
|
|
|
TextSerializer<LogicalExpression> logicalOrSerializer =
|
|
new Wrapped<Tuple2<Expression, Expression>, LogicalExpression>(
|
|
unwrapLogicalExpression,
|
|
wrapLogicalOr,
|
|
new Tuple2Serializer(expressionSerializer, expressionSerializer));
|
|
|
|
LogicalExpression wrapLogicalOr(Tuple2<Expression, Expression> tuple) {
|
|
return new LogicalExpression(
|
|
tuple.first, LogicalExpressionOperator.OR, tuple.second);
|
|
}
|
|
|
|
TextSerializer<StringConcatenation> stringConcatenationSerializer =
|
|
new Wrapped<List<Expression>, StringConcatenation>(
|
|
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<String, StringLiteral>(
|
|
unwrapStringLiteral, wrapStringLiteral, const DartString());
|
|
|
|
String unwrapStringLiteral(StringLiteral literal) => literal.value;
|
|
|
|
StringLiteral wrapStringLiteral(String value) => new StringLiteral(value);
|
|
|
|
const TextSerializer<IntLiteral> intLiteralSerializer =
|
|
const Wrapped<int, IntLiteral>(
|
|
unwrapIntLiteral, wrapIntLiteral, const DartInt());
|
|
|
|
int unwrapIntLiteral(IntLiteral literal) => literal.value;
|
|
|
|
IntLiteral wrapIntLiteral(int value) => new IntLiteral(value);
|
|
|
|
const TextSerializer<DoubleLiteral> doubleLiteralSerializer =
|
|
const Wrapped<double, DoubleLiteral>(
|
|
unwrapDoubleLiteral, wrapDoubleLiteral, const DartDouble());
|
|
|
|
double unwrapDoubleLiteral(DoubleLiteral literal) => literal.value;
|
|
|
|
DoubleLiteral wrapDoubleLiteral(double value) => new DoubleLiteral(value);
|
|
|
|
const TextSerializer<BoolLiteral> boolLiteralSerializer =
|
|
const Wrapped<bool, BoolLiteral>(
|
|
unwrapBoolLiteral, wrapBoolLiteral, const DartBool());
|
|
|
|
bool unwrapBoolLiteral(BoolLiteral literal) => literal.value;
|
|
|
|
BoolLiteral wrapBoolLiteral(bool value) => new BoolLiteral(value);
|
|
|
|
const TextSerializer<NullLiteral> nullLiteralSerializer =
|
|
const Wrapped<void, NullLiteral>(
|
|
unwrapNullLiteral, wrapNullLiteral, const Nothing());
|
|
|
|
void unwrapNullLiteral(NullLiteral literal) {}
|
|
|
|
NullLiteral wrapNullLiteral(void ignored) => new NullLiteral();
|
|
|
|
const TextSerializer<SymbolLiteral> symbolLiteralSerializer =
|
|
const Wrapped<String, SymbolLiteral>(
|
|
unwrapSymbolLiteral, wrapSymbolLiteral, const DartString());
|
|
|
|
String unwrapSymbolLiteral(SymbolLiteral expression) => expression.value;
|
|
|
|
SymbolLiteral wrapSymbolLiteral(String value) => new SymbolLiteral(value);
|
|
|
|
const TextSerializer<ThisExpression> thisExpressionSerializer =
|
|
const Wrapped<void, ThisExpression>(
|
|
unwrapThisExpression, wrapThisExpression, const Nothing());
|
|
|
|
void unwrapThisExpression(ThisExpression expression) {}
|
|
|
|
ThisExpression wrapThisExpression(void ignored) => new ThisExpression();
|
|
|
|
const TextSerializer<Rethrow> rethrowSerializer =
|
|
const Wrapped<void, Rethrow>(unwrapRethrow, wrapRethrow, const Nothing());
|
|
|
|
void unwrapRethrow(Rethrow expression) {}
|
|
|
|
Rethrow wrapRethrow(void ignored) => new Rethrow();
|
|
|
|
TextSerializer<Throw> throwSerializer = new Wrapped<Expression, Throw>(
|
|
unwrapThrow, wrapThrow, expressionSerializer);
|
|
|
|
Expression unwrapThrow(Throw expression) => expression.expression;
|
|
|
|
Throw wrapThrow(Expression expression) => new Throw(expression);
|
|
|
|
TextSerializer<AwaitExpression> awaitExpressionSerializer =
|
|
new Wrapped<Expression, AwaitExpression>(
|
|
unwrapAwaitExpression, wrapAwaitExpression, expressionSerializer);
|
|
|
|
Expression unwrapAwaitExpression(AwaitExpression expression) =>
|
|
expression.operand;
|
|
|
|
AwaitExpression wrapAwaitExpression(Expression operand) =>
|
|
new AwaitExpression(operand);
|
|
|
|
TextSerializer<ConditionalExpression> conditionalExpressionSerializer =
|
|
new Wrapped<Tuple4<Expression, DartType, Expression, Expression>,
|
|
ConditionalExpression>(
|
|
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<Tuple2<Expression, DartType>, IsExpression>(
|
|
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<Tuple2<Expression, DartType>, AsExpression>(
|
|
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<DartType, TypeLiteral>(
|
|
unwrapTypeLiteral, wrapTypeLiteral, dartTypeSerializer);
|
|
|
|
DartType unwrapTypeLiteral(TypeLiteral expression) => expression.type;
|
|
|
|
TypeLiteral wrapTypeLiteral(DartType type) => new TypeLiteral(type);
|
|
|
|
TextSerializer<ListLiteral> listLiteralSerializer =
|
|
new Wrapped<Tuple2<DartType, List<Expression>>, ListLiteral>(
|
|
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<Tuple2<DartType, List<Expression>>, ListLiteral>(
|
|
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<Tuple2<DartType, List<Expression>>, SetLiteral>(
|
|
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<Tuple2<DartType, List<Expression>>, SetLiteral>(
|
|
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<Tuple3<DartType, DartType, List<Expression>>, MapLiteral>(
|
|
unwrapMapLiteral,
|
|
wrapMapLiteral,
|
|
new Tuple3Serializer(dartTypeSerializer, dartTypeSerializer,
|
|
new ListSerializer(expressionSerializer)));
|
|
|
|
Tuple3<DartType, DartType, List<Expression>> unwrapMapLiteral(
|
|
MapLiteral expression) {
|
|
List<Expression> entries =
|
|
new List.filled(2 * expression.entries.length, dummyExpression);
|
|
for (int from = 0, to = 0; from < expression.entries.length; ++from) {
|
|
MapLiteralEntry 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<MapLiteralEntry> entries =
|
|
new List.filled(tuple.third.length ~/ 2, dummyMapLiteralEntry);
|
|
for (int from = 0, to = 0; to < entries.length; ++to) {
|
|
entries[to] = new MapLiteralEntry(tuple.third[from++], tuple.third[from++]);
|
|
}
|
|
return new MapLiteral(entries,
|
|
keyType: tuple.first, valueType: tuple.second, isConst: false);
|
|
}
|
|
|
|
TextSerializer<MapLiteral> constMapLiteralSerializer =
|
|
new Wrapped<Tuple3<DartType, DartType, List<Expression>>, MapLiteral>(
|
|
unwrapMapLiteral,
|
|
wrapConstMapLiteral,
|
|
new Tuple3Serializer(dartTypeSerializer, dartTypeSerializer,
|
|
new ListSerializer(expressionSerializer)));
|
|
|
|
MapLiteral wrapConstMapLiteral(
|
|
Tuple3<DartType, DartType, List<Expression>> tuple) {
|
|
List<MapLiteralEntry> entries =
|
|
new List.filled(tuple.third.length ~/ 2, dummyMapLiteralEntry);
|
|
for (int from = 0, to = 0; to < entries.length; ++to) {
|
|
entries[to] = new MapLiteralEntry(tuple.third[from++], tuple.third[from++]);
|
|
}
|
|
return new MapLiteral(entries,
|
|
keyType: tuple.first, valueType: tuple.second, isConst: true);
|
|
}
|
|
|
|
TextSerializer<Let> letSerializer =
|
|
new Wrapped<Tuple2<VariableDeclaration, Expression>, Let>(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<InstanceGet> instanceGetSerializer = new Wrapped<
|
|
Tuple5<InstanceAccessKind, Expression, Name, CanonicalName, DartType>,
|
|
InstanceGet>(
|
|
unwrapInstanceGet,
|
|
wrapInstanceGet,
|
|
new Tuple5Serializer(instanceAccessKindSerializer, expressionSerializer,
|
|
nameSerializer, canonicalNameSerializer, dartTypeSerializer));
|
|
|
|
Tuple5<InstanceAccessKind, Expression, Name, CanonicalName, DartType>
|
|
unwrapInstanceGet(InstanceGet expression) {
|
|
return new Tuple5(
|
|
expression.kind,
|
|
expression.receiver,
|
|
expression.name,
|
|
expression.interfaceTargetReference.canonicalName!,
|
|
expression.resultType);
|
|
}
|
|
|
|
InstanceGet wrapInstanceGet(
|
|
Tuple5<InstanceAccessKind, Expression, Name, CanonicalName, DartType>
|
|
tuple) {
|
|
return new InstanceGet.byReference(tuple.first, tuple.second, tuple.third,
|
|
interfaceTargetReference: tuple.fourth.reference,
|
|
resultType: tuple.fifth);
|
|
}
|
|
|
|
TextSerializer<InstanceSet> instanceSetSerializer = new Wrapped<
|
|
Tuple5<InstanceAccessKind, Expression, Name, Expression, CanonicalName>,
|
|
InstanceSet>(
|
|
unwrapInstanceSet,
|
|
wrapInstanceSet,
|
|
new Tuple5Serializer(instanceAccessKindSerializer, expressionSerializer,
|
|
nameSerializer, expressionSerializer, canonicalNameSerializer));
|
|
|
|
Tuple5<InstanceAccessKind, Expression, Name, Expression, CanonicalName>
|
|
unwrapInstanceSet(InstanceSet expression) {
|
|
return new Tuple5(expression.kind, expression.receiver, expression.name,
|
|
expression.value, expression.interfaceTargetReference.canonicalName!);
|
|
}
|
|
|
|
InstanceSet wrapInstanceSet(
|
|
Tuple5<InstanceAccessKind, Expression, Name, Expression, CanonicalName>
|
|
tuple) {
|
|
return new InstanceSet.byReference(
|
|
tuple.first, tuple.second, tuple.third, tuple.fourth,
|
|
interfaceTargetReference: tuple.fifth.reference);
|
|
}
|
|
|
|
TextSerializer<DynamicGet> dynamicGetSerializer =
|
|
new Wrapped<Tuple3<DynamicAccessKind, Expression, Name>, DynamicGet>(
|
|
unwrapDynamicGet,
|
|
wrapDynamicGet,
|
|
new Tuple3Serializer(
|
|
dynamicAccessKindSerializer, expressionSerializer, nameSerializer));
|
|
|
|
Tuple3<DynamicAccessKind, Expression, Name> unwrapDynamicGet(
|
|
DynamicGet expression) {
|
|
return new Tuple3(expression.kind, expression.receiver, expression.name);
|
|
}
|
|
|
|
DynamicGet wrapDynamicGet(Tuple3<DynamicAccessKind, Expression, Name> tuple) {
|
|
return new DynamicGet(tuple.first, tuple.second, tuple.third);
|
|
}
|
|
|
|
TextSerializer<DynamicSet> dynamicSetSerializer = new Wrapped<
|
|
Tuple4<DynamicAccessKind, Expression, Name, Expression>, DynamicSet>(
|
|
unwrapDynamicSet,
|
|
wrapDynamicSet,
|
|
new Tuple4Serializer(dynamicAccessKindSerializer, expressionSerializer,
|
|
nameSerializer, expressionSerializer));
|
|
|
|
Tuple4<DynamicAccessKind, Expression, Name, Expression> unwrapDynamicSet(
|
|
DynamicSet expression) {
|
|
return new Tuple4(
|
|
expression.kind, expression.receiver, expression.name, expression.value);
|
|
}
|
|
|
|
DynamicSet wrapDynamicSet(
|
|
Tuple4<DynamicAccessKind, Expression, Name, Expression> tuple) {
|
|
return new DynamicSet(tuple.first, tuple.second, tuple.third, tuple.fourth);
|
|
}
|
|
|
|
TextSerializer<InstanceTearOff> instanceTearOffSerializer = new Wrapped<
|
|
Tuple5<InstanceAccessKind, Expression, Name, CanonicalName, DartType>,
|
|
InstanceTearOff>(
|
|
unwrapInstanceTearOff,
|
|
wrapInstanceTearOff,
|
|
new Tuple5Serializer(instanceAccessKindSerializer, expressionSerializer,
|
|
nameSerializer, canonicalNameSerializer, dartTypeSerializer));
|
|
|
|
Tuple5<InstanceAccessKind, Expression, Name, CanonicalName, DartType>
|
|
unwrapInstanceTearOff(InstanceTearOff expression) {
|
|
return new Tuple5(
|
|
expression.kind,
|
|
expression.receiver,
|
|
expression.name,
|
|
expression.interfaceTargetReference.canonicalName!,
|
|
expression.resultType);
|
|
}
|
|
|
|
InstanceTearOff wrapInstanceTearOff(
|
|
Tuple5<InstanceAccessKind, Expression, Name, CanonicalName, DartType>
|
|
tuple) {
|
|
return new InstanceTearOff.byReference(tuple.first, tuple.second, tuple.third,
|
|
interfaceTargetReference: tuple.fourth.reference,
|
|
resultType: tuple.fifth);
|
|
}
|
|
|
|
TextSerializer<FunctionTearOff> functionTearOffSerializer =
|
|
new Wrapped<Expression, FunctionTearOff>(
|
|
unwrapFunctionTearOff, wrapFunctionTearOff, expressionSerializer);
|
|
|
|
Expression unwrapFunctionTearOff(FunctionTearOff expression) {
|
|
return expression.receiver;
|
|
}
|
|
|
|
FunctionTearOff wrapFunctionTearOff(Expression expression) {
|
|
return new FunctionTearOff(expression);
|
|
}
|
|
|
|
TextSerializer<SuperPropertyGet> superPropertyGetSerializer =
|
|
new Wrapped<Name, SuperPropertyGet>(
|
|
unwrapSuperPropertyGet, wrapSuperPropertyGet, nameSerializer);
|
|
|
|
Name unwrapSuperPropertyGet(SuperPropertyGet expression) {
|
|
return expression.name;
|
|
}
|
|
|
|
SuperPropertyGet wrapSuperPropertyGet(Name name) {
|
|
return new SuperPropertyGet(name);
|
|
}
|
|
|
|
TextSerializer<SuperPropertySet> superPropertySetSerializer =
|
|
new Wrapped<Tuple2<Name, Expression>, SuperPropertySet>(
|
|
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);
|
|
}
|
|
|
|
const Map<InstanceAccessKind, String> instanceAccessKindToName = const {
|
|
InstanceAccessKind.Instance: "instance",
|
|
InstanceAccessKind.Object: "object",
|
|
InstanceAccessKind.Nullable: "nullable",
|
|
InstanceAccessKind.Inapplicable: "inapplicable",
|
|
};
|
|
|
|
class InstanceAccessKindTagger implements Tagger<InstanceAccessKind> {
|
|
const InstanceAccessKindTagger();
|
|
|
|
@override
|
|
String tag(InstanceAccessKind kind) {
|
|
return instanceAccessKindToName[kind] ??
|
|
(throw StateError("Unknown InstanceAccessKind flag value: ${kind}."));
|
|
}
|
|
}
|
|
|
|
TextSerializer<InstanceAccessKind> instanceAccessKindSerializer =
|
|
Case(InstanceAccessKindTagger(), convertFlagsMap(instanceAccessKindToName));
|
|
|
|
TextSerializer<InstanceInvocation> instanceInvocationSerializer = new Wrapped<
|
|
Tuple6<InstanceAccessKind, Expression, Name, Arguments, CanonicalName,
|
|
DartType>,
|
|
InstanceInvocation>(
|
|
unwrapInstanceInvocation,
|
|
wrapInstanceInvocation,
|
|
new Tuple6Serializer(
|
|
instanceAccessKindSerializer,
|
|
expressionSerializer,
|
|
nameSerializer,
|
|
argumentsSerializer,
|
|
canonicalNameSerializer,
|
|
dartTypeSerializer));
|
|
|
|
Tuple6<InstanceAccessKind, Expression, Name, Arguments, CanonicalName, DartType>
|
|
unwrapInstanceInvocation(InstanceInvocation expression) {
|
|
return new Tuple6(
|
|
expression.kind,
|
|
expression.receiver,
|
|
expression.name,
|
|
expression.arguments,
|
|
expression.interfaceTargetReference.canonicalName!,
|
|
expression.functionType);
|
|
}
|
|
|
|
InstanceInvocation wrapInstanceInvocation(
|
|
Tuple6<InstanceAccessKind, Expression, Name, Arguments, CanonicalName,
|
|
DartType>
|
|
tuple) {
|
|
return new InstanceInvocation.byReference(
|
|
tuple.first, tuple.second, tuple.third, tuple.fourth,
|
|
interfaceTargetReference: tuple.fifth.reference,
|
|
functionType: tuple.sixth as FunctionType);
|
|
}
|
|
|
|
TextSerializer<
|
|
InstanceGetterInvocation> instanceGetterInvocationSerializer = new Wrapped<
|
|
Tuple6<InstanceAccessKind, Expression, Name, Arguments, CanonicalName,
|
|
DartType?>,
|
|
InstanceGetterInvocation>(
|
|
unwrapInstanceGetterInvocation,
|
|
wrapInstanceGetterInvocation,
|
|
new Tuple6Serializer(
|
|
instanceAccessKindSerializer,
|
|
expressionSerializer,
|
|
nameSerializer,
|
|
argumentsSerializer,
|
|
const CanonicalNameSerializer(),
|
|
Optional(dartTypeSerializer)));
|
|
|
|
Tuple6<InstanceAccessKind, Expression, Name, Arguments, CanonicalName,
|
|
DartType?>
|
|
unwrapInstanceGetterInvocation(InstanceGetterInvocation expression) {
|
|
return new Tuple6(
|
|
expression.kind,
|
|
expression.receiver,
|
|
expression.name,
|
|
expression.arguments,
|
|
expression.interfaceTargetReference.canonicalName!,
|
|
expression.functionType);
|
|
}
|
|
|
|
InstanceGetterInvocation wrapInstanceGetterInvocation(
|
|
Tuple6<InstanceAccessKind, Expression, Name, Arguments, CanonicalName,
|
|
DartType?>
|
|
tuple) {
|
|
return new InstanceGetterInvocation.byReference(
|
|
tuple.first, tuple.second, tuple.third, tuple.fourth,
|
|
interfaceTargetReference: tuple.fifth.reference,
|
|
functionType: tuple.sixth as FunctionType?);
|
|
}
|
|
|
|
const Map<DynamicAccessKind, String> dynamicAccessKindToName = const {
|
|
DynamicAccessKind.Dynamic: "dynamic",
|
|
DynamicAccessKind.Never: "never",
|
|
DynamicAccessKind.Invalid: "invalid",
|
|
DynamicAccessKind.Unresolved: "unresolved",
|
|
};
|
|
|
|
class DynamicAccessKindTagger implements Tagger<DynamicAccessKind> {
|
|
const DynamicAccessKindTagger();
|
|
|
|
@override
|
|
String tag(DynamicAccessKind kind) {
|
|
return dynamicAccessKindToName[kind] ??
|
|
(throw StateError("Unknown DynamicAccessKind flag value: ${kind}."));
|
|
}
|
|
}
|
|
|
|
TextSerializer<DynamicAccessKind> dynamicAccessKindSerializer =
|
|
Case(DynamicAccessKindTagger(), convertFlagsMap(dynamicAccessKindToName));
|
|
|
|
TextSerializer<DynamicInvocation> dynamicInvocationSerializer = new Wrapped<
|
|
Tuple4<DynamicAccessKind, Expression, Name, Arguments>,
|
|
DynamicInvocation>(
|
|
unwrapDynamicInvocation,
|
|
wrapDynamicInvocation,
|
|
new Tuple4Serializer(dynamicAccessKindSerializer, expressionSerializer,
|
|
nameSerializer, argumentsSerializer));
|
|
|
|
Tuple4<DynamicAccessKind, Expression, Name, Arguments> unwrapDynamicInvocation(
|
|
DynamicInvocation expression) {
|
|
return new Tuple4(expression.kind, expression.receiver, expression.name,
|
|
expression.arguments);
|
|
}
|
|
|
|
DynamicInvocation wrapDynamicInvocation(
|
|
Tuple4<DynamicAccessKind, Expression, Name, Arguments> tuple) {
|
|
return new DynamicInvocation(
|
|
tuple.first, tuple.second, tuple.third, tuple.fourth);
|
|
}
|
|
|
|
const Map<FunctionAccessKind, String> functionAccessKindToName = const {
|
|
FunctionAccessKind.Function: "function",
|
|
FunctionAccessKind.FunctionType: "function-type",
|
|
FunctionAccessKind.Inapplicable: "inapplicable",
|
|
FunctionAccessKind.Nullable: "nullable",
|
|
};
|
|
|
|
class FunctionAccessKindTagger implements Tagger<FunctionAccessKind> {
|
|
const FunctionAccessKindTagger();
|
|
|
|
@override
|
|
String tag(FunctionAccessKind kind) {
|
|
return functionAccessKindToName[kind] ??
|
|
(throw StateError("Unknown FunctionAccessKind flag value: ${kind}."));
|
|
}
|
|
}
|
|
|
|
TextSerializer<FunctionAccessKind> functionAccessKindSerializer =
|
|
Case(FunctionAccessKindTagger(), convertFlagsMap(functionAccessKindToName));
|
|
|
|
TextSerializer<FunctionInvocation> functionInvocationSerializer = new Wrapped<
|
|
Tuple4<FunctionAccessKind, Expression, Arguments, DartType?>,
|
|
FunctionInvocation>(
|
|
unwrapFunctionInvocation,
|
|
wrapFunctionInvocation,
|
|
new Tuple4Serializer(functionAccessKindSerializer, expressionSerializer,
|
|
argumentsSerializer, new Optional(dartTypeSerializer)));
|
|
|
|
Tuple4<FunctionAccessKind, Expression, Arguments, DartType?>
|
|
unwrapFunctionInvocation(FunctionInvocation expression) {
|
|
return new Tuple4(expression.kind, expression.receiver, expression.arguments,
|
|
expression.functionType);
|
|
}
|
|
|
|
FunctionInvocation wrapFunctionInvocation(
|
|
Tuple4<FunctionAccessKind, Expression, Arguments, DartType?> tuple) {
|
|
return new FunctionInvocation(tuple.first, tuple.second, tuple.third,
|
|
functionType: tuple.fourth as FunctionType?);
|
|
}
|
|
|
|
TextSerializer<LocalFunctionInvocation> localFunctionInvocationSerializer =
|
|
new Wrapped<Tuple3<VariableDeclaration, Arguments, DartType>,
|
|
LocalFunctionInvocation>(
|
|
unwrapLocalFunctionInvocation,
|
|
wrapLocalFunctionInvocation,
|
|
new Tuple3Serializer(const ScopedUse<VariableDeclaration>(),
|
|
argumentsSerializer, dartTypeSerializer));
|
|
|
|
Tuple3<VariableDeclaration, Arguments, DartType> unwrapLocalFunctionInvocation(
|
|
LocalFunctionInvocation expression) {
|
|
return new Tuple3(
|
|
expression.variable, expression.arguments, expression.functionType);
|
|
}
|
|
|
|
LocalFunctionInvocation wrapLocalFunctionInvocation(
|
|
Tuple3<VariableDeclaration, Arguments, DartType> tuple) {
|
|
return new LocalFunctionInvocation(tuple.first, tuple.second,
|
|
functionType: tuple.third as FunctionType);
|
|
}
|
|
|
|
TextSerializer<EqualsNull> equalsNullSerializer =
|
|
new Wrapped<Expression, EqualsNull>(
|
|
unwrapEqualsNull, wrapEqualsNull, expressionSerializer);
|
|
|
|
Expression unwrapEqualsNull(EqualsNull expression) {
|
|
return expression.expression;
|
|
}
|
|
|
|
EqualsNull wrapEqualsNull(Expression expression) {
|
|
return new EqualsNull(expression);
|
|
}
|
|
|
|
TextSerializer<EqualsCall> equalsCallSerializer = new Wrapped<
|
|
Tuple4<Expression, Expression, CanonicalName, DartType>, EqualsCall>(
|
|
unwrapEqualsCall,
|
|
wrapEqualsCall,
|
|
new Tuple4Serializer(expressionSerializer, expressionSerializer,
|
|
canonicalNameSerializer, dartTypeSerializer));
|
|
|
|
Tuple4<Expression, Expression, CanonicalName, DartType> unwrapEqualsCall(
|
|
EqualsCall expression) {
|
|
return new Tuple4(
|
|
expression.left,
|
|
expression.right,
|
|
expression.interfaceTargetReference.canonicalName!,
|
|
expression.functionType);
|
|
}
|
|
|
|
EqualsCall wrapEqualsCall(
|
|
Tuple4<Expression, Expression, CanonicalName, DartType> tuple) {
|
|
return new EqualsCall.byReference(tuple.first, tuple.second,
|
|
interfaceTargetReference: tuple.third.reference,
|
|
functionType: tuple.fourth as FunctionType);
|
|
}
|
|
|
|
TextSerializer<SuperMethodInvocation> superMethodInvocationSerializer =
|
|
new Wrapped<Tuple2<Name, Arguments>, SuperMethodInvocation>(
|
|
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<Tuple2<VariableDeclaration, DartType?>, VariableGet>(
|
|
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<Tuple2<VariableDeclaration, Expression>, VariableSet>(
|
|
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);
|
|
}
|
|
|
|
const CanonicalNameSerializer canonicalNameSerializer =
|
|
const CanonicalNameSerializer();
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
@override
|
|
CanonicalName readFrom(
|
|
Iterator<Object?> stream, DeserializationState? state) {
|
|
if (state == null) {
|
|
throw StateError(
|
|
"No deserialization state provided for ${runtimeType}.readFrom.");
|
|
}
|
|
String string = const DartString().readFrom(stream, state);
|
|
CanonicalName name = state.nameRoot;
|
|
for (String s in string.split(delimiter)) {
|
|
name = name.getChild(s);
|
|
}
|
|
return name;
|
|
}
|
|
|
|
@override
|
|
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, canonicalNameSerializer);
|
|
|
|
CanonicalName unwrapStaticGet(StaticGet expression) {
|
|
return expression.targetReference.canonicalName!;
|
|
}
|
|
|
|
StaticGet wrapStaticGet(CanonicalName name) {
|
|
return new StaticGet.byReference(name.reference);
|
|
}
|
|
|
|
const TextSerializer<StaticTearOff> staticTearOffSerializer =
|
|
const Wrapped<CanonicalName, StaticTearOff>(
|
|
unwrapStaticTearOff, wrapStaticTearOff, canonicalNameSerializer);
|
|
|
|
CanonicalName unwrapStaticTearOff(StaticTearOff expression) {
|
|
return expression.targetReference.canonicalName!;
|
|
}
|
|
|
|
StaticTearOff wrapStaticTearOff(CanonicalName name) {
|
|
return new StaticTearOff.byReference(name.reference);
|
|
}
|
|
|
|
const TextSerializer<ConstructorTearOff> constructorTearOffSerializer =
|
|
const Wrapped<CanonicalName, ConstructorTearOff>(unwrapConstructorTearOff,
|
|
wrapConstructorTearOff, canonicalNameSerializer);
|
|
|
|
CanonicalName unwrapConstructorTearOff(ConstructorTearOff expression) {
|
|
return expression.targetReference.canonicalName!;
|
|
}
|
|
|
|
ConstructorTearOff wrapConstructorTearOff(CanonicalName name) {
|
|
return new ConstructorTearOff.byReference(name.reference);
|
|
}
|
|
|
|
const TextSerializer<RedirectingFactoryTearOff>
|
|
redirectingFactoryTearOffSerializer =
|
|
const Wrapped<CanonicalName, RedirectingFactoryTearOff>(
|
|
unwrapRedirectingFactoryTearOff,
|
|
wrapRedirectingFactoryTearOff,
|
|
canonicalNameSerializer);
|
|
|
|
CanonicalName unwrapRedirectingFactoryTearOff(
|
|
RedirectingFactoryTearOff expression) {
|
|
return expression.targetReference.canonicalName!;
|
|
}
|
|
|
|
RedirectingFactoryTearOff wrapRedirectingFactoryTearOff(CanonicalName name) {
|
|
return new RedirectingFactoryTearOff.byReference(name.reference);
|
|
}
|
|
|
|
final TextSerializer<TypedefTearOff> typedefTearOffSerializer = new Wrapped<
|
|
Tuple2<List<TypeParameter>, Tuple2<Expression, List<DartType>>>,
|
|
TypedefTearOff>(
|
|
unwrapTypedefTearOff,
|
|
wrapTypedefTearOff,
|
|
Bind(
|
|
typeParametersSerializer,
|
|
Tuple2Serializer(
|
|
expressionSerializer, ListSerializer(dartTypeSerializer))));
|
|
|
|
Tuple2<List<TypeParameter>, Tuple2<Expression, List<DartType>>>
|
|
unwrapTypedefTearOff(TypedefTearOff node) {
|
|
return new Tuple2(
|
|
node.typeParameters, new Tuple2(node.expression, node.typeArguments));
|
|
}
|
|
|
|
TypedefTearOff wrapTypedefTearOff(
|
|
Tuple2<List<TypeParameter>, Tuple2<Expression, List<DartType>>> tuple) {
|
|
return new TypedefTearOff(
|
|
tuple.first, tuple.second.first, tuple.second.second);
|
|
}
|
|
|
|
TextSerializer<StaticSet> staticSetSerializer =
|
|
new Wrapped<Tuple2<CanonicalName, Expression>, StaticSet>(
|
|
unwrapStaticSet,
|
|
wrapStaticSet,
|
|
new Tuple2Serializer(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.reference, tuple.second);
|
|
}
|
|
|
|
TextSerializer<StaticInvocation> staticInvocationSerializer =
|
|
new Wrapped<Tuple2<CanonicalName, Arguments>, StaticInvocation>(
|
|
unwrapStaticInvocation,
|
|
wrapStaticInvocation,
|
|
new Tuple2Serializer(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.reference, tuple.second,
|
|
isConst: false);
|
|
}
|
|
|
|
TextSerializer<StaticInvocation> constStaticInvocationSerializer =
|
|
new Wrapped<Tuple2<CanonicalName, Arguments>, StaticInvocation>(
|
|
unwrapStaticInvocation,
|
|
wrapConstStaticInvocation,
|
|
new Tuple2Serializer(canonicalNameSerializer, argumentsSerializer));
|
|
|
|
StaticInvocation wrapConstStaticInvocation(
|
|
Tuple2<CanonicalName, Arguments> tuple) {
|
|
return new StaticInvocation.byReference(tuple.first.reference, tuple.second,
|
|
isConst: true);
|
|
}
|
|
|
|
TextSerializer<ConstructorInvocation> constructorInvocationSerializer =
|
|
new Wrapped<Tuple2<CanonicalName, Arguments>, ConstructorInvocation>(
|
|
unwrapConstructorInvocation,
|
|
wrapConstructorInvocation,
|
|
new Tuple2Serializer(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.reference, tuple.second,
|
|
isConst: false);
|
|
}
|
|
|
|
TextSerializer<ConstructorInvocation> constConstructorInvocationSerializer =
|
|
new Wrapped<Tuple2<CanonicalName, Arguments>, ConstructorInvocation>(
|
|
unwrapConstructorInvocation,
|
|
wrapConstConstructorInvocation,
|
|
Tuple2Serializer(canonicalNameSerializer, argumentsSerializer));
|
|
|
|
ConstructorInvocation wrapConstConstructorInvocation(
|
|
Tuple2<CanonicalName, Arguments> tuple) {
|
|
return new ConstructorInvocation.byReference(
|
|
tuple.first.reference, tuple.second,
|
|
isConst: true);
|
|
}
|
|
|
|
TextSerializer<FunctionExpression> functionExpressionSerializer =
|
|
new Wrapped<FunctionNode, FunctionExpression>(unwrapFunctionExpression,
|
|
wrapFunctionExpression, functionNodeSerializer);
|
|
|
|
FunctionNode unwrapFunctionExpression(FunctionExpression expression) {
|
|
return expression.function;
|
|
}
|
|
|
|
FunctionExpression wrapFunctionExpression(FunctionNode node) {
|
|
return new FunctionExpression(node);
|
|
}
|
|
|
|
TextSerializer<ListConcatenation> listConcatenationSerializer =
|
|
Wrapped<Tuple2<DartType, List<Expression>>, ListConcatenation>(
|
|
(lc) => Tuple2(lc.typeArgument, lc.lists),
|
|
(t) => ListConcatenation(t.second, typeArgument: t.first),
|
|
Tuple2Serializer(
|
|
dartTypeSerializer, ListSerializer(expressionSerializer)));
|
|
|
|
TextSerializer<SetConcatenation> setConcatenationSerializer =
|
|
Wrapped<Tuple2<DartType, List<Expression>>, SetConcatenation>(
|
|
(sc) => Tuple2(sc.typeArgument, sc.sets),
|
|
(t) => SetConcatenation(t.second, typeArgument: t.first),
|
|
Tuple2Serializer(
|
|
dartTypeSerializer, ListSerializer(expressionSerializer)));
|
|
|
|
TextSerializer<MapConcatenation> mapConcatenationSerializer =
|
|
Wrapped<Tuple3<DartType, DartType, List<Expression>>, MapConcatenation>(
|
|
(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<Tuple2<List<Statement>, Expression?>, BlockExpression>(
|
|
(w) => Tuple2(w.body.statements, w.value),
|
|
(u) => BlockExpression(Block(u.first), u.second!),
|
|
const BlockSerializer());
|
|
|
|
TextSerializer<Instantiation> instantiationSerializer =
|
|
Wrapped<Tuple2<Expression, List<DartType>>, Instantiation>(
|
|
(i) => Tuple2(i.expression, i.typeArguments),
|
|
(t) => Instantiation(t.first, t.second),
|
|
Tuple2Serializer(
|
|
expressionSerializer, ListSerializer(dartTypeSerializer)));
|
|
|
|
TextSerializer<NullCheck> nullCheckSerializer = Wrapped<Expression, NullCheck>(
|
|
(nc) => nc.operand, (op) => NullCheck(op), expressionSerializer);
|
|
|
|
TextSerializer<FileUriExpression> fileUriExpressionSerializer =
|
|
Wrapped<Tuple2<Expression, Uri>, FileUriExpression>(
|
|
(fue) => Tuple2(fue.expression, fue.fileUri),
|
|
(t) => FileUriExpression(t.first, t.second),
|
|
Tuple2Serializer(expressionSerializer, const UriSerializer()));
|
|
|
|
TextSerializer<CheckLibraryIsLoaded> checkLibraryIsLoadedSerializer =
|
|
Wrapped<LibraryDependency, CheckLibraryIsLoaded>((clil) => clil.import,
|
|
(i) => CheckLibraryIsLoaded(i), libraryDependencySerializer);
|
|
|
|
TextSerializer<LoadLibrary> loadLibrarySerializer =
|
|
Wrapped<LibraryDependency, LoadLibrary>(
|
|
(ll) => ll.import, (i) => LoadLibrary(i), libraryDependencySerializer);
|
|
|
|
TextSerializer<ConstantExpression> constantExpressionSerializer =
|
|
Wrapped<Tuple2<Constant, DartType>, ConstantExpression>(
|
|
(ce) => Tuple2(ce.constant, ce.type),
|
|
(t) => ConstantExpression(t.first, t.second),
|
|
Tuple2Serializer(constantSerializer, dartTypeSerializer));
|
|
|
|
TextSerializer<InstanceCreation> instanceCreationSerializer = Wrapped<
|
|
Tuple6<CanonicalName, List<DartType>, List<CanonicalName>,
|
|
List<Expression>, List<AssertStatement>, List<Expression>>,
|
|
InstanceCreation>(
|
|
(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.reference,
|
|
t.second,
|
|
Map.fromIterables(t.third.map((cn) => cn.reference), 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<Expression?> nullableExpressionSerializer =
|
|
new Optional(expressionSerializer);
|
|
|
|
TextSerializer<NamedExpression> namedExpressionSerializer =
|
|
new Wrapped<Tuple2<String, Expression>, NamedExpression>(
|
|
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<
|
|
Tuple3<List<DartType>, List<Expression>, List<NamedExpression>>,
|
|
Arguments>(
|
|
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.FlagInitializingFormal: "field-formal",
|
|
VariableDeclaration.FlagCovariantByDeclaration: "covariant",
|
|
VariableDeclaration.FlagCovariantByClass: "generic-covariant-impl",
|
|
VariableDeclaration.FlagLate: "late",
|
|
VariableDeclaration.FlagRequired: "required",
|
|
VariableDeclaration.FlagLowered: "lowered",
|
|
};
|
|
|
|
class VariableDeclarationFlagTagger implements Tagger<int> {
|
|
@override
|
|
String tag(int flag) {
|
|
return variableDeclarationFlagToName[flag] ??
|
|
(throw StateError("Unknown VariableDeclaration flag value: ${flag}."));
|
|
}
|
|
}
|
|
|
|
TextSerializer<int> variableDeclarationFlagsSerializer =
|
|
Wrapped<List<int>, int>(
|
|
(w) => List.generate(30, (i) => w & (1 << i))
|
|
.where((f) => f != 0)
|
|
.toList(),
|
|
(u) => u.fold(0, (fs, f) => fs |= f),
|
|
ListSerializer(Case(VariableDeclarationFlagTagger(),
|
|
convertFlagsMap(variableDeclarationFlagToName))));
|
|
|
|
TextSerializer<VariableDeclaration> variableDeclarationSerializer =
|
|
Wrapped<Tuple2<String?, VariableDeclaration>, VariableDeclaration>(
|
|
(v) => Tuple2(v.name, v),
|
|
(t) => t.second..name = t.first,
|
|
Binder<VariableDeclaration>(
|
|
new Wrapped<Tuple4<int, DartType, Expression?, List<Expression>>,
|
|
VariableDeclaration>(
|
|
(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<Tuple2<String?, TypeParameter>, TypeParameter>(
|
|
(p) => Tuple2(p.name, p),
|
|
(t) => t.second..name = t.first,
|
|
Binder<TypeParameter>(Wrapped<void, TypeParameter>(
|
|
(_) => 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();
|
|
|
|
@override
|
|
String tag(DartType type) => type.accept(this);
|
|
|
|
@override
|
|
String visitInvalidType(InvalidType _) => "invalid";
|
|
@override
|
|
String visitDynamicType(DynamicType _) => "dynamic";
|
|
@override
|
|
String visitVoidType(VoidType _) => "void";
|
|
@override
|
|
String visitFunctionType(FunctionType _) => "->";
|
|
@override
|
|
String visitTypeParameterType(TypeParameterType _) => "par";
|
|
@override
|
|
String visitInterfaceType(InterfaceType _) => "interface";
|
|
@override
|
|
String visitNeverType(NeverType _) => "never";
|
|
@override
|
|
String visitTypedefType(TypedefType _) => "typedef";
|
|
@override
|
|
String visitFutureOrType(FutureOrType _) => "futureor";
|
|
@override
|
|
String visitNullType(NullType _) => "null-type";
|
|
|
|
@override
|
|
String defaultDartType(DartType node) {
|
|
throw UnimplementedError('Unimplemented type $node (${node.runtimeType})');
|
|
}
|
|
}
|
|
|
|
const TextSerializer<InvalidType> invalidTypeSerializer =
|
|
const Wrapped<void, InvalidType>(
|
|
unwrapInvalidType, wrapInvalidType, const Nothing());
|
|
|
|
void unwrapInvalidType(InvalidType type) {}
|
|
|
|
InvalidType wrapInvalidType(void ignored) => const InvalidType();
|
|
|
|
const TextSerializer<DynamicType> dynamicTypeSerializer =
|
|
const Wrapped<void, DynamicType>(
|
|
unwrapDynamicType, wrapDynamicType, const Nothing());
|
|
|
|
void unwrapDynamicType(DynamicType type) {}
|
|
|
|
DynamicType wrapDynamicType(void ignored) => const DynamicType();
|
|
|
|
const TextSerializer<VoidType> voidTypeSerializer =
|
|
const Wrapped<void, VoidType>(
|
|
unwrapVoidType, wrapVoidType, const Nothing());
|
|
|
|
void unwrapVoidType(VoidType type) {}
|
|
|
|
VoidType wrapVoidType(void ignored) => const VoidType();
|
|
|
|
const TextSerializer<NeverType> neverTypeSerializer =
|
|
const Wrapped<void, NeverType>(
|
|
unwrapNeverType, wrapNeverType, const Nothing());
|
|
|
|
void unwrapNeverType(NeverType type) {}
|
|
|
|
NeverType wrapNeverType(void ignored) => const NeverType.legacy();
|
|
|
|
// TODO(dmitryas): Also handle nameParameters, and typedefType.
|
|
TextSerializer<FunctionType> functionTypeSerializer = new Wrapped<
|
|
Tuple2<List<TypeParameter>,
|
|
Tuple4<List<DartType>, List<DartType>, List<NamedType>, DartType>>,
|
|
FunctionType>(
|
|
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<Tuple2<String, DartType>, NamedType>(
|
|
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<Tuple2<TypeParameter, DartType?>, TypeParameterType>(
|
|
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<Tuple2<CanonicalName, List<DartType>>, InterfaceType>(
|
|
unwrapInterfaceType,
|
|
wrapInterfaceType,
|
|
Tuple2Serializer(
|
|
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<Tuple2<CanonicalName, List<DartType>>, TypedefType>(
|
|
unwrapTypedefType,
|
|
wrapTypedefType,
|
|
Tuple2Serializer(
|
|
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<DartType, FutureOrType>(
|
|
unwrapFutureOrType, wrapFutureOrType, dartTypeSerializer);
|
|
|
|
DartType unwrapFutureOrType(FutureOrType node) {
|
|
return node.typeArgument;
|
|
}
|
|
|
|
FutureOrType wrapFutureOrType(DartType typeArgument) {
|
|
return new FutureOrType(typeArgument, Nullability.legacy);
|
|
}
|
|
|
|
TextSerializer<NullType> nullTypeSerializer =
|
|
new Wrapped<void, NullType>(unwrapNullType, wrapNullType, const Nothing());
|
|
|
|
void unwrapNullType(NullType type) {}
|
|
|
|
NullType wrapNullType(void ignored) => const NullType();
|
|
|
|
Case<DartType> dartTypeSerializer =
|
|
new Case.uninitialized(const DartTypeTagger());
|
|
|
|
class StatementTagger extends StatementVisitor<String>
|
|
implements Tagger<Statement> {
|
|
const StatementTagger();
|
|
|
|
@override
|
|
String tag(Statement statement) => statement.accept(this);
|
|
|
|
@override
|
|
String visitExpressionStatement(ExpressionStatement _) => "expr";
|
|
@override
|
|
String visitReturnStatement(ReturnStatement node) {
|
|
return node.expression == null ? "ret-void" : "ret";
|
|
}
|
|
|
|
@override
|
|
String visitYieldStatement(YieldStatement _) => "yield";
|
|
@override
|
|
String visitBlock(Block _) => "block";
|
|
@override
|
|
String visitVariableDeclaration(VariableDeclaration _) => "local";
|
|
@override
|
|
String visitIfStatement(IfStatement node) {
|
|
return node.otherwise == null ? "if" : "if-else";
|
|
}
|
|
|
|
@override
|
|
String visitEmptyStatement(EmptyStatement node) => "skip";
|
|
@override
|
|
String visitWhileStatement(WhileStatement node) => "while";
|
|
@override
|
|
String visitDoStatement(DoStatement node) => "do-while";
|
|
@override
|
|
String visitForStatement(ForStatement node) => "for";
|
|
@override
|
|
String visitForInStatement(ForInStatement node) {
|
|
return node.isAsync ? "await-for-in" : "for-in";
|
|
}
|
|
|
|
@override
|
|
String visitAssertStatement(AssertStatement node) => "assert";
|
|
@override
|
|
String visitAssertBlock(AssertBlock node) => "assert-block";
|
|
@override
|
|
String visitLabeledStatement(LabeledStatement node) => "label";
|
|
@override
|
|
String visitBreakStatement(BreakStatement node) => "break";
|
|
@override
|
|
String visitTryFinally(TryFinally node) => "try-finally";
|
|
@override
|
|
String visitTryCatch(TryCatch node) => "try-catch";
|
|
@override
|
|
String visitSwitchStatement(SwitchStatement node) => "switch";
|
|
@override
|
|
String visitContinueSwitchStatement(ContinueSwitchStatement node) =>
|
|
"continue";
|
|
@override
|
|
String visitFunctionDeclaration(FunctionDeclaration node) => "local-fun";
|
|
|
|
@override
|
|
String defaultStatement(Statement node) {
|
|
throw new UnimplementedError(
|
|
"Unimplemented statement $node (${node.runtimeType})");
|
|
}
|
|
}
|
|
|
|
TextSerializer<ExpressionStatement> expressionStatementSerializer =
|
|
new Wrapped<Expression, ExpressionStatement>(unwrapExpressionStatement,
|
|
wrapExpressionStatement, expressionSerializer);
|
|
|
|
Expression unwrapExpressionStatement(ExpressionStatement statement) {
|
|
return statement.expression;
|
|
}
|
|
|
|
ExpressionStatement wrapExpressionStatement(Expression expression) {
|
|
return new ExpressionStatement(expression);
|
|
}
|
|
|
|
TextSerializer<ReturnStatement> returnStatementSerializer =
|
|
new Wrapped<Expression?, ReturnStatement>(
|
|
unwrapReturnStatement, wrapReturnStatement, expressionSerializer);
|
|
|
|
Expression? unwrapReturnStatement(ReturnStatement statement) {
|
|
return statement.expression;
|
|
}
|
|
|
|
ReturnStatement wrapReturnStatement(Expression? expression) {
|
|
return new ReturnStatement(expression);
|
|
}
|
|
|
|
TextSerializer<ReturnStatement> returnVoidStatementSerializer =
|
|
new Wrapped<void, ReturnStatement>(
|
|
unwrapReturnVoidStatement, wrapReturnVoidStatement, const Nothing());
|
|
|
|
void unwrapReturnVoidStatement(void ignored) {}
|
|
|
|
ReturnStatement wrapReturnVoidStatement(void ignored) => new ReturnStatement();
|
|
|
|
TextSerializer<YieldStatement> yieldStatementSerializer =
|
|
new Wrapped<Expression, YieldStatement>(
|
|
unwrapYieldStatement, wrapYieldStatement, expressionSerializer);
|
|
|
|
Expression unwrapYieldStatement(YieldStatement node) => node.expression;
|
|
|
|
YieldStatement wrapYieldStatement(Expression expression) {
|
|
return new YieldStatement(expression);
|
|
}
|
|
|
|
TextSerializer<AssertStatement> assertStatementSerializer =
|
|
Wrapped<Tuple4<Expression, Expression?, int, int>, AssertStatement>(
|
|
(a) => Tuple4(a.condition, a.message, a.conditionStartOffset,
|
|
a.conditionEndOffset),
|
|
(t) => AssertStatement(t.first,
|
|
message: t.second,
|
|
conditionStartOffset: t.third,
|
|
conditionEndOffset: t.fourth),
|
|
Tuple4Serializer(expressionSerializer, nullableExpressionSerializer,
|
|
const DartInt(), const DartInt()));
|
|
|
|
TextSerializer<Block> blockSerializer =
|
|
Wrapped<Tuple2<List<Statement>, Expression?>, Block>(
|
|
(w) => Tuple2(w.statements, null),
|
|
(u) => Block(u.first),
|
|
const BlockSerializer());
|
|
|
|
TextSerializer<AssertBlock> assertBlockSerializer =
|
|
Wrapped<Tuple2<List<Statement>, Expression?>, AssertBlock>(
|
|
(w) => Tuple2(w.statements, null),
|
|
(u) => AssertBlock(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();
|
|
|
|
@override
|
|
Tuple2<List<Statement>, Expression?> readFrom(
|
|
Iterator<Object?> stream, DeserializationState? state) {
|
|
if (state == null) {
|
|
throw StateError(
|
|
"No deserialization state provided for ${runtimeType}.readFrom.");
|
|
}
|
|
Object? iterator = stream.current;
|
|
if (iterator is! Iterator) {
|
|
throw StateError("Expected a list, found an atom: '${iterator}'.");
|
|
}
|
|
iterator.moveNext();
|
|
List<Statement> statements = [];
|
|
DeserializationState currentState = state;
|
|
while (iterator.current != null) {
|
|
currentState = new DeserializationState(
|
|
new DeserializationEnvironment(currentState.environment),
|
|
currentState.nameRoot);
|
|
statements.add(statementSerializer.readFrom(iterator, currentState));
|
|
currentState.environment.extend();
|
|
}
|
|
stream.moveNext();
|
|
Expression? expression =
|
|
nullableExpressionSerializer.readFrom(stream, currentState);
|
|
return new Tuple2(statements, expression);
|
|
}
|
|
|
|
@override
|
|
void writeTo(StringBuffer buffer, Tuple2<List<Statement>, Expression?> tuple,
|
|
SerializationState? state) {
|
|
if (state == null) {
|
|
throw StateError(
|
|
"No serialization state provided for ${runtimeType}.writeTo.");
|
|
}
|
|
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(') ');
|
|
nullableExpressionSerializer.writeTo(buffer, tuple.second, currentState);
|
|
}
|
|
}
|
|
|
|
TextSerializer<IfStatement> ifStatementSerializer =
|
|
new Wrapped<Tuple2<Expression, Statement>, IfStatement>(
|
|
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<Tuple3<Expression, Statement, Statement?>, IfStatement>(
|
|
unwrapIfElseStatement,
|
|
wrapIfElseStatement,
|
|
Tuple3Serializer<Expression, Statement, Statement?>(
|
|
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<void, EmptyStatement>(
|
|
unwrapEmptyStatement, wrapEmptyStatement, const Nothing());
|
|
|
|
void unwrapEmptyStatement(EmptyStatement node) {}
|
|
|
|
EmptyStatement wrapEmptyStatement(void ignored) => new EmptyStatement();
|
|
|
|
TextSerializer<WhileStatement> whileStatementSerializer =
|
|
new Wrapped<Tuple2<Expression, Statement>, WhileStatement>(
|
|
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<Tuple2<Statement, Expression>, DoStatement>(
|
|
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 = Wrapped<
|
|
Tuple2<List<VariableDeclaration>,
|
|
Tuple3<Expression?, List<Expression>, Statement>>,
|
|
ForStatement>(
|
|
(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<
|
|
Tuple2<Expression, Tuple2<VariableDeclaration, Statement>>,
|
|
ForInStatement>(
|
|
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<
|
|
Tuple2<Expression, Tuple2<VariableDeclaration, Statement>>,
|
|
ForInStatement>(
|
|
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<Tuple2<String?, LabeledStatement>, LabeledStatement>(
|
|
(ls) => Tuple2("L", ls),
|
|
(t) => t.second,
|
|
Binder(Wrapped<void, LabeledStatement>(
|
|
(_) => null, (_) => LabeledStatement(null), Nothing()))),
|
|
statementSerializer));
|
|
|
|
TextSerializer<BreakStatement> breakSerializer =
|
|
new Wrapped<LabeledStatement, BreakStatement>(unwrapBreakStatement,
|
|
wrapBreakStatement, const ScopedUse<LabeledStatement>());
|
|
|
|
LabeledStatement unwrapBreakStatement(BreakStatement node) {
|
|
return node.target;
|
|
}
|
|
|
|
BreakStatement wrapBreakStatement(LabeledStatement node) {
|
|
return new BreakStatement(node);
|
|
}
|
|
|
|
TextSerializer<TryFinally> tryFinallySerializer =
|
|
Wrapped<Tuple2<Statement, Statement>, TryFinally>(
|
|
(w) => Tuple2(w.body, w.finalizer),
|
|
(u) => TryFinally(u.first, u.second),
|
|
Tuple2Serializer(statementSerializer, statementSerializer));
|
|
|
|
TextSerializer<TryCatch> tryCatchSerializer =
|
|
Wrapped<Tuple2<Statement, List<Catch>>, TryCatch>(
|
|
(w) => Tuple2(w.body, w.catches),
|
|
(u) => TryCatch(u.first, u.second),
|
|
Tuple2Serializer(statementSerializer, ListSerializer(catchSerializer)));
|
|
|
|
TextSerializer<Catch> catchSerializer =
|
|
Wrapped<
|
|
Tuple2<
|
|
DartType,
|
|
Tuple2<Tuple2<VariableDeclaration?, VariableDeclaration?>,
|
|
Statement>>,
|
|
Catch>(
|
|
(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<Tuple2<Expression, List<SwitchCase>>, SwitchStatement>(
|
|
(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> {
|
|
@override
|
|
String tag(SwitchCase node) {
|
|
return node.isDefault ? "default" : "case";
|
|
}
|
|
}
|
|
|
|
TextSerializer<SwitchCase> switchCaseCaseSerializer =
|
|
Wrapped<Tuple2<String?, SwitchCase>, SwitchCase>(
|
|
(w) => Tuple2("L", w),
|
|
(u) => u.second,
|
|
Binder(Wrapped<List<Expression>, SwitchCase>(
|
|
(w) => w.expressions,
|
|
(u) => SwitchCase(u, List.filled(u.length, 0), null),
|
|
ListSerializer(expressionSerializer))));
|
|
|
|
TextSerializer<SwitchCase> switchCaseDefaultSerializer =
|
|
Wrapped<Tuple2<String?, SwitchCase>, SwitchCase>(
|
|
(w) => Tuple2("L", w),
|
|
(u) => u.second,
|
|
Binder(Wrapped<void, SwitchCase>(
|
|
(w) => null, (u) => SwitchCase.defaultCase(null), Nothing())));
|
|
|
|
TextSerializer<SwitchCase> switchCaseSerializer = Case(SwitchCaseTagger(), {
|
|
"case": switchCaseCaseSerializer,
|
|
"default": switchCaseDefaultSerializer,
|
|
});
|
|
|
|
TextSerializer<ContinueSwitchStatement> continueSwitchStatementSerializer =
|
|
Wrapped<SwitchCase, ContinueSwitchStatement>(
|
|
(w) => w.target, (u) => ContinueSwitchStatement(u), ScopedUse());
|
|
|
|
TextSerializer<FunctionDeclaration> functionDeclarationSerializer =
|
|
Wrapped<Tuple2<VariableDeclaration, FunctionNode>, FunctionDeclaration>(
|
|
(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();
|
|
|
|
@override
|
|
String tag(AsyncMarker node) {
|
|
return asyncMarkerToName[node] ?? (throw new UnsupportedError("${node}"));
|
|
}
|
|
}
|
|
|
|
TextSerializer<AsyncMarker> asyncMarkerSerializer =
|
|
Case(AsyncMarkerTagger(), convertFlagsMap(asyncMarkerToName));
|
|
|
|
// '/**/' comments added to guide formatting.
|
|
|
|
TextSerializer<Tuple2<FunctionNode, List<Initializer>?>> /**/
|
|
functionNodeWithInitializersSerializer = Wrapped<
|
|
Tuple2<
|
|
AsyncMarker,
|
|
Tuple2<
|
|
/**/
|
|
Tuple2<
|
|
/**/
|
|
List<TypeParameter>,
|
|
Tuple3<
|
|
List<VariableDeclaration>,
|
|
List<VariableDeclaration>,
|
|
List<VariableDeclaration>>>,
|
|
Tuple3<DartType, List<Initializer>?, Statement?>>>,
|
|
Tuple2<FunctionNode, List<Initializer>?>>(
|
|
(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<Tuple2<FunctionNode, List<Initializer>?>, FunctionNode>(
|
|
(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.FlagRedirectingFactory: "redirecting-factory-constructor",
|
|
Procedure.FlagExtensionMember: "extension-member",
|
|
Procedure.FlagNonNullableByDefault: "non-nullable-by-default",
|
|
Procedure.FlagSynthetic: "synthetic",
|
|
};
|
|
|
|
class ProcedureFlagTagger implements Tagger<int> {
|
|
const ProcedureFlagTagger();
|
|
|
|
@override
|
|
String tag(int flag) {
|
|
return procedureFlagToName[flag] ??
|
|
(throw StateError("Unknown Procedure flag value: ${flag}."));
|
|
}
|
|
}
|
|
|
|
TextSerializer<int> procedureFlagsSerializer = Wrapped<List<int>, int>(
|
|
(w) => List.generate(30, (i) => w & (1 << i)).where((f) => f != 0).toList(),
|
|
(u) => u.fold(0, (fs, f) => fs |= f),
|
|
ListSerializer(
|
|
Case(ProcedureFlagTagger(), convertFlagsMap(procedureFlagToName))));
|
|
|
|
const Map<int, String> fieldFlagToName = const {
|
|
Field.FlagFinal: "final",
|
|
Field.FlagConst: "const",
|
|
Field.FlagStatic: "static",
|
|
Field.FlagCovariant: "covariant",
|
|
Field.FlagCovariantByClass: "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();
|
|
|
|
@override
|
|
String tag(int flag) {
|
|
return fieldFlagToName[flag] ??
|
|
(throw StateError("Unknown Field flag value: ${flag}."));
|
|
}
|
|
}
|
|
|
|
TextSerializer<int> fieldFlagsSerializer = Wrapped<List<int>, int>(
|
|
(w) => List.generate(30, (i) => w & (1 << i)).where((f) => f != 0).toList(),
|
|
(u) => u.fold(0, (fs, f) => fs |= f),
|
|
ListSerializer(Case(FieldFlagTagger(), convertFlagsMap(fieldFlagToName))));
|
|
|
|
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();
|
|
|
|
@override
|
|
String tag(int flag) {
|
|
return constructorFlagToName[flag] ??
|
|
(throw StateError("Unknown Constructor flag value: ${flag}."));
|
|
}
|
|
}
|
|
|
|
TextSerializer<int> constructorFlagsSerializer = Wrapped<List<int>, int>(
|
|
(w) => List.generate(30, (i) => w & (1 << i)).where((f) => f != 0).toList(),
|
|
(u) => u.fold(0, (fs, f) => fs |= f),
|
|
ListSerializer(
|
|
Case(ConstructorFlagTagger(), convertFlagsMap(constructorFlagToName))));
|
|
|
|
const Map<int, String> redirectingFactoryFlagToName = const {
|
|
RedirectingFactory.FlagConst: "const",
|
|
RedirectingFactory.FlagExternal: "external",
|
|
RedirectingFactory.FlagNonNullableByDefault: "non-nullable-by-default",
|
|
};
|
|
|
|
class RedirectingFactoryFlagTagger implements Tagger<int> {
|
|
const RedirectingFactoryFlagTagger();
|
|
|
|
@override
|
|
String tag(int flag) {
|
|
return redirectingFactoryFlagToName[flag] ??
|
|
(throw StateError("Unknown RedirectingFactory flag value: ${flag}."));
|
|
}
|
|
}
|
|
|
|
TextSerializer<int> redirectingFactoryConstructorFlagsSerializer =
|
|
Wrapped<List<int>, int>(
|
|
(w) => List.generate(30, (i) => w & (1 << i))
|
|
.where((f) => f != 0)
|
|
.toList(),
|
|
(u) => u.fold(0, (fs, f) => fs |= f),
|
|
ListSerializer(Case(RedirectingFactoryFlagTagger(),
|
|
convertFlagsMap(redirectingFactoryFlagToName))));
|
|
|
|
class MemberTagger implements Tagger<Member> {
|
|
const MemberTagger();
|
|
|
|
@override
|
|
String tag(Member node) {
|
|
if (node is Field) {
|
|
return node.hasSetter ? "mutable-field" : "immutable-field";
|
|
} else if (node is Constructor) {
|
|
return "constructor";
|
|
} else if (node is RedirectingFactory) {
|
|
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> mutableFieldSerializer =
|
|
Wrapped<Tuple5<Name, int, DartType, Expression?, Uri>, Field>(
|
|
(w) => Tuple5(w.name, w.flags, w.type, w.initializer, w.fileUri),
|
|
(u) => Field.mutable(u.first,
|
|
type: u.third, initializer: u.fourth, fileUri: u.fifth)
|
|
..flags = u.second,
|
|
Tuple5Serializer(nameSerializer, fieldFlagsSerializer,
|
|
dartTypeSerializer, nullableExpressionSerializer, UriSerializer()));
|
|
|
|
TextSerializer<Field> immutableFieldSerializer =
|
|
Wrapped<Tuple5<Name, int, DartType, Expression?, Uri>, Field>(
|
|
(w) => Tuple5(w.name, w.flags, w.type, w.initializer, w.fileUri),
|
|
(u) => Field.immutable(u.first,
|
|
type: u.third, initializer: u.fourth, fileUri: u.fifth)
|
|
..flags = u.second,
|
|
Tuple5Serializer(nameSerializer, fieldFlagsSerializer,
|
|
dartTypeSerializer, nullableExpressionSerializer, UriSerializer()));
|
|
|
|
TextSerializer<Procedure> methodSerializer =
|
|
Wrapped<Tuple4<Name, int, FunctionNode, Uri>, Procedure>(
|
|
(w) => Tuple4(w.name, w.flags, w.function, w.fileUri),
|
|
(u) =>
|
|
Procedure(u.first, ProcedureKind.Method, u.third, fileUri: u.fourth)
|
|
..flags = u.second,
|
|
Tuple4Serializer(nameSerializer, procedureFlagsSerializer,
|
|
functionNodeSerializer, UriSerializer()));
|
|
|
|
TextSerializer<Procedure> getterSerializer =
|
|
Wrapped<Tuple4<Name, int, FunctionNode, Uri>, Procedure>(
|
|
(w) => Tuple4(w.name, w.flags, w.function, w.fileUri),
|
|
(u) =>
|
|
Procedure(u.first, ProcedureKind.Getter, u.third, fileUri: u.fourth)
|
|
..flags = u.second,
|
|
Tuple4Serializer(nameSerializer, procedureFlagsSerializer,
|
|
functionNodeSerializer, UriSerializer()));
|
|
|
|
TextSerializer<Procedure> setterSerializer =
|
|
Wrapped<Tuple4<Name, int, FunctionNode, Uri>, Procedure>(
|
|
(w) => Tuple4(w.name, w.flags, w.function, w.fileUri),
|
|
(u) =>
|
|
Procedure(u.first, ProcedureKind.Setter, u.third, fileUri: u.fourth)
|
|
..flags = u.second,
|
|
Tuple4Serializer(nameSerializer, procedureFlagsSerializer,
|
|
functionNodeSerializer, UriSerializer()));
|
|
|
|
TextSerializer<Procedure> operatorSerializer =
|
|
Wrapped<Tuple4<Name, int, FunctionNode, Uri>, Procedure>(
|
|
(w) => Tuple4(w.name, w.flags, w.function, w.fileUri),
|
|
(u) => Procedure(u.first, ProcedureKind.Operator, u.third,
|
|
fileUri: u.fourth)
|
|
..flags = u.second,
|
|
Tuple4Serializer(nameSerializer, procedureFlagsSerializer,
|
|
functionNodeSerializer, UriSerializer()));
|
|
|
|
TextSerializer<Procedure> factorySerializer =
|
|
Wrapped<Tuple4<Name, int, FunctionNode, Uri>, Procedure>(
|
|
(w) => Tuple4(w.name, w.flags, w.function, w.fileUri),
|
|
(u) => Procedure(u.first, ProcedureKind.Factory, u.third,
|
|
fileUri: u.fourth)
|
|
..flags = u.second,
|
|
Tuple4Serializer(nameSerializer, procedureFlagsSerializer,
|
|
functionNodeSerializer, UriSerializer()));
|
|
|
|
TextSerializer<Constructor> constructorSerializer = Wrapped<
|
|
Tuple4<Name, int, Tuple2<FunctionNode, List<Initializer>?>, Uri>,
|
|
Constructor>(
|
|
(w) =>
|
|
Tuple4(w.name, w.flags, Tuple2(w.function, w.initializers), w.fileUri),
|
|
(u) => Constructor(u.third.first,
|
|
name: u.first, initializers: u.third.second, fileUri: u.fourth)
|
|
..flags = u.second,
|
|
Tuple4Serializer(nameSerializer, constructorFlagsSerializer,
|
|
functionNodeWithInitializersSerializer, UriSerializer()));
|
|
|
|
TextSerializer<RedirectingFactory> redirectingFactoryConstructorSerializer
|
|
// Comment added to direct formatter.
|
|
= Wrapped<
|
|
Tuple6<Name, int, FunctionNode, CanonicalName, List<DartType>, Uri>,
|
|
RedirectingFactory>(
|
|
(w) => Tuple6(w.name, w.flags, w.function,
|
|
w.targetReference!.canonicalName!, w.typeArguments, w.fileUri),
|
|
(u) => RedirectingFactory(u.fourth.reference,
|
|
name: u.first,
|
|
function: u.third,
|
|
typeArguments: u.fifth,
|
|
fileUri: u.sixth)
|
|
..flags = u.second,
|
|
Tuple6Serializer(
|
|
nameSerializer,
|
|
redirectingFactoryConstructorFlagsSerializer,
|
|
functionNodeSerializer,
|
|
CanonicalNameSerializer(),
|
|
ListSerializer(dartTypeSerializer),
|
|
UriSerializer()));
|
|
|
|
Case<Member> memberSerializer = new Case.uninitialized(const MemberTagger());
|
|
|
|
TextSerializer<LibraryPart> libraryPartSerializer =
|
|
Wrapped<Tuple2<String, List<Expression>>, LibraryPart>(
|
|
(w) => Tuple2(w.partUri, w.annotations),
|
|
(u) => LibraryPart(u.second, u.first),
|
|
Tuple2Serializer(DartString(), ListSerializer(expressionSerializer)));
|
|
|
|
class LibraryTagger implements Tagger<Library> {
|
|
const LibraryTagger();
|
|
|
|
@override
|
|
String tag(Library node) {
|
|
return node.isNonNullableByDefault ? "null-safe" : "legacy";
|
|
}
|
|
}
|
|
|
|
const Map<int, String> libraryFlagToName = const {
|
|
Library.SyntheticFlag: "synthetic",
|
|
Library.NonNullableByDefaultFlag: "nnbd",
|
|
Library.NonNullableByDefaultModeBit1: "nnbd-bit1",
|
|
Library.NonNullableByDefaultModeBit2: "nnbd-bit2",
|
|
};
|
|
|
|
class LibraryFlagTagger implements Tagger<int> {
|
|
const LibraryFlagTagger();
|
|
|
|
@override
|
|
String tag(int flag) {
|
|
return libraryFlagToName[flag] ??
|
|
(throw StateError("Unknown Library flag value: ${flag}."));
|
|
}
|
|
}
|
|
|
|
TextSerializer<int> libraryFlagsSerializer = Wrapped<List<int>, int>(
|
|
(w) => List.generate(30, (i) => w & (1 << i)).where((f) => f != 0).toList(),
|
|
(u) => u.fold(0, (fs, f) => fs |= f),
|
|
ListSerializer(
|
|
Case(LibraryFlagTagger(), convertFlagsMap(libraryFlagToName))));
|
|
|
|
TextSerializer<Library> librarySerializer = new Wrapped<
|
|
Tuple8<Uri, int, List<LibraryPart>, List<Member>, List<Class>,
|
|
List<Typedef>, List<Extension>, Uri>,
|
|
Library>(
|
|
(w) => Tuple8(w.importUri, w.flags, w.parts, [...w.fields, ...w.procedures],
|
|
w.classes, w.typedefs, w.extensions, w.fileUri),
|
|
(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,
|
|
fileUri: u.eighth)
|
|
..flags = u.second,
|
|
Tuple8Serializer(
|
|
UriSerializer(),
|
|
libraryFlagsSerializer,
|
|
ListSerializer(libraryPartSerializer),
|
|
ListSerializer(memberSerializer),
|
|
ListSerializer(classSerializer),
|
|
ListSerializer(typedefSerializer),
|
|
ListSerializer(extensionSerializer),
|
|
UriSerializer()),
|
|
);
|
|
|
|
TextSerializer<Component> componentSerializer =
|
|
Wrapped<List<Library>, Component>(
|
|
(w) => w.libraries,
|
|
(u) => Component(nameRoot: CanonicalName.root(), libraries: u),
|
|
ListSerializer(librarySerializer));
|
|
|
|
class ShowHideTagger implements Tagger<Combinator> {
|
|
@override
|
|
String tag(Combinator node) => node.isShow ? "show" : "hide";
|
|
}
|
|
|
|
TextSerializer<Combinator> showSerializer = Wrapped<List<String>, Combinator>(
|
|
(c) => c.names, (ns) => Combinator(true, ns), ListSerializer(DartString()));
|
|
|
|
TextSerializer<Combinator> hideSerializer = Wrapped<List<String>, Combinator>(
|
|
(c) => c.names,
|
|
(ns) => Combinator(false, ns),
|
|
ListSerializer(DartString()));
|
|
|
|
Case<Combinator> showHideSerializer = new Case(ShowHideTagger(), {
|
|
"show": showSerializer,
|
|
"hide": hideSerializer,
|
|
});
|
|
|
|
TextSerializer<LibraryDependency> libraryDependencySerializer = Wrapped<
|
|
Tuple5<CanonicalName, String?, List<Combinator>, int, List<Expression>>,
|
|
LibraryDependency>(
|
|
(ld) => Tuple5(ld.importedLibraryReference.canonicalName!, ld.name,
|
|
ld.combinators, ld.flags, ld.annotations),
|
|
(t) => LibraryDependency.byReference(
|
|
t.fourth, t.fifth, t.first.reference, t.second, t.third),
|
|
Tuple5Serializer(
|
|
CanonicalNameSerializer(),
|
|
Optional(DartString()),
|
|
ListSerializer(showHideSerializer),
|
|
DartInt(),
|
|
ListSerializer(expressionSerializer)));
|
|
|
|
class ConstantTagger extends ConstantVisitor<String>
|
|
implements Tagger<Constant> {
|
|
const ConstantTagger();
|
|
|
|
@override
|
|
String tag(Constant node) => node.accept(this);
|
|
|
|
@override
|
|
String visitBoolConstant(BoolConstant node) => "const-bool";
|
|
@override
|
|
String visitDoubleConstant(DoubleConstant node) => "const-double";
|
|
@override
|
|
String visitInstanceConstant(InstanceConstant node) => "const-object";
|
|
@override
|
|
String visitIntConstant(IntConstant node) => "const-int";
|
|
@override
|
|
String visitListConstant(ListConstant node) => "const-list";
|
|
@override
|
|
String visitMapConstant(MapConstant node) => "const-map";
|
|
@override
|
|
String visitNullConstant(NullConstant node) => "const-null";
|
|
@override
|
|
String visitInstantiationConstant(InstantiationConstant node) =>
|
|
"const-apply";
|
|
@override
|
|
String visitSetConstant(SetConstant node) => "const-set";
|
|
@override
|
|
String visitStringConstant(StringConstant node) => "const-string";
|
|
@override
|
|
String visitSymbolConstant(SymbolConstant node) => "const-symbol";
|
|
@override
|
|
String visitStaticTearOffConstant(StaticTearOffConstant node) =>
|
|
"const-tearoff-static";
|
|
@override
|
|
String visitConstructorTearOffConstant(ConstructorTearOffConstant node) =>
|
|
"const-tearoff-constructor";
|
|
@override
|
|
String visitRedirectingFactoryTearOffConstant(
|
|
RedirectingFactoryTearOffConstant node) =>
|
|
"const-tearoff-redirecting-factory";
|
|
@override
|
|
String visitTypedefTearOffConstant(TypedefTearOffConstant node) =>
|
|
"const-tearoff-typedef";
|
|
@override
|
|
String visitTypeLiteralConstant(TypeLiteralConstant node) => "const-type";
|
|
@override
|
|
String visitUnevaluatedConstant(UnevaluatedConstant node) => "const-expr";
|
|
|
|
@override
|
|
String defaultConstant(Constant node) {
|
|
throw new UnimplementedError(
|
|
'Unimplemented constant $node (${node.runtimeType})');
|
|
}
|
|
}
|
|
|
|
TextSerializer<BoolConstant> boolConstantSerializer =
|
|
Wrapped<bool, BoolConstant>(
|
|
(w) => w.value, (u) => BoolConstant(u), DartBool());
|
|
|
|
TextSerializer<DoubleConstant> doubleConstantSerializer =
|
|
Wrapped<double, DoubleConstant>(
|
|
(w) => w.value, (u) => DoubleConstant(u), DartDouble());
|
|
|
|
TextSerializer<IntConstant> intConstantSerializer =
|
|
Wrapped<int, IntConstant>((w) => w.value, (u) => IntConstant(u), DartInt());
|
|
|
|
TextSerializer<ListConstant> listConstantSerializer =
|
|
Wrapped<Tuple2<DartType, List<Constant>>, ListConstant>(
|
|
(w) => Tuple2(w.typeArgument, w.entries),
|
|
(u) => ListConstant(u.first, u.second),
|
|
Tuple2Serializer(
|
|
dartTypeSerializer, ListSerializer(constantSerializer)));
|
|
|
|
TextSerializer<MapConstant> mapConstantSerializer =
|
|
Wrapped<Tuple3<DartType, DartType, List<ConstantMapEntry>>, MapConstant>(
|
|
(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)),
|
|
(Constant k, Constant v) => ConstantMapEntry(k, v),
|
|
(z) => Tuple2(z.key, z.value))));
|
|
|
|
TextSerializer<NullConstant> nullConstantSerializer =
|
|
Wrapped<void, NullConstant>((w) => null, (u) => NullConstant(), Nothing());
|
|
|
|
TextSerializer<InstantiationConstant> instantiationConstantSerializer =
|
|
Wrapped<Tuple2<Constant, List<DartType>>, InstantiationConstant>(
|
|
(w) => Tuple2(w.tearOffConstant, w.types),
|
|
(u) => InstantiationConstant(u.first, u.second),
|
|
Tuple2Serializer(
|
|
constantSerializer, ListSerializer(dartTypeSerializer)));
|
|
|
|
TextSerializer<SetConstant> setConstantSerializer =
|
|
Wrapped<Tuple2<DartType, List<Constant>>, SetConstant>(
|
|
(w) => Tuple2(w.typeArgument, w.entries),
|
|
(u) => SetConstant(u.first, u.second),
|
|
Tuple2Serializer(
|
|
dartTypeSerializer, ListSerializer(constantSerializer)));
|
|
|
|
TextSerializer<StringConstant> stringConstantSerializer =
|
|
Wrapped<String, StringConstant>(
|
|
(w) => w.value, (u) => StringConstant(u), DartString());
|
|
|
|
TextSerializer<SymbolConstant> symbolConstantSerializer =
|
|
Wrapped<Tuple2<String, CanonicalName?>, SymbolConstant>(
|
|
(w) => Tuple2(w.name, w.libraryReference?.canonicalName),
|
|
(u) => SymbolConstant(u.first, u.second?.reference),
|
|
Tuple2Serializer(DartString(), Optional(CanonicalNameSerializer())));
|
|
|
|
TextSerializer<StaticTearOffConstant> staticTearOffConstantSerializer =
|
|
Wrapped<CanonicalName, StaticTearOffConstant>(
|
|
(w) => w.targetReference.canonicalName!,
|
|
(u) => StaticTearOffConstant.byReference(u.reference),
|
|
CanonicalNameSerializer());
|
|
|
|
TextSerializer<ConstructorTearOffConstant>
|
|
constructorTearOffConstantSerializer =
|
|
Wrapped<CanonicalName, ConstructorTearOffConstant>(
|
|
(w) => w.targetReference.canonicalName!,
|
|
(u) => ConstructorTearOffConstant.byReference(u.reference),
|
|
CanonicalNameSerializer());
|
|
|
|
TextSerializer<RedirectingFactoryTearOffConstant>
|
|
redirectingFactoryTearOffConstantSerializer =
|
|
Wrapped<CanonicalName, RedirectingFactoryTearOffConstant>(
|
|
(w) => w.targetReference.canonicalName!,
|
|
(u) => RedirectingFactoryTearOffConstant.byReference(u.reference),
|
|
CanonicalNameSerializer());
|
|
|
|
final TextSerializer<TypedefTearOffConstant> typedefTearOffConstantSerializer =
|
|
new Wrapped<Tuple2<List<TypeParameter>, Tuple2<Constant, List<DartType>>>,
|
|
TypedefTearOffConstant>(
|
|
unwrapTypedefTearOffConstant,
|
|
wrapTypedefTearOffConstant,
|
|
Bind(
|
|
typeParametersSerializer,
|
|
Tuple2Serializer(
|
|
constantSerializer, ListSerializer(dartTypeSerializer))));
|
|
|
|
Tuple2<List<TypeParameter>, Tuple2<Constant, List<DartType>>>
|
|
unwrapTypedefTearOffConstant(TypedefTearOffConstant node) {
|
|
return new Tuple2(
|
|
node.parameters, new Tuple2(node.tearOffConstant, node.types));
|
|
}
|
|
|
|
TypedefTearOffConstant wrapTypedefTearOffConstant(
|
|
Tuple2<List<TypeParameter>, Tuple2<Constant, List<DartType>>> tuple) {
|
|
return new TypedefTearOffConstant(
|
|
tuple.first, tuple.second.first as TearOffConstant, tuple.second.second);
|
|
}
|
|
|
|
TextSerializer<TypeLiteralConstant> typeLiteralConstantSerializer =
|
|
Wrapped<DartType, TypeLiteralConstant>(
|
|
(w) => w.type, (u) => TypeLiteralConstant(u), dartTypeSerializer);
|
|
|
|
TextSerializer<UnevaluatedConstant> unevaluatedConstantSerializer =
|
|
Wrapped<Expression, UnevaluatedConstant>((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.reference, u.second,
|
|
Map.fromIterables(u.third.map((c) => c.reference), u.fourth)),
|
|
Tuple4Serializer(
|
|
CanonicalNameSerializer(),
|
|
ListSerializer(dartTypeSerializer),
|
|
ListSerializer(CanonicalNameSerializer()),
|
|
ListSerializer(constantSerializer)));
|
|
|
|
Case<Constant> constantSerializer = Case.uninitialized(ConstantTagger());
|
|
|
|
class InitializerTagger implements Tagger<Initializer> {
|
|
const InitializerTagger();
|
|
|
|
@override
|
|
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<Statement, AssertInitializer>((w) => w.statement,
|
|
(u) => AssertInitializer(u as AssertStatement), statementSerializer);
|
|
|
|
TextSerializer<FieldInitializer> fieldInitializerSerializer =
|
|
Wrapped<Tuple2<CanonicalName, Expression>, FieldInitializer>(
|
|
(w) => Tuple2(w.fieldReference.canonicalName!, w.value),
|
|
(u) => FieldInitializer.byReference(u.first.reference, u.second),
|
|
Tuple2Serializer(CanonicalNameSerializer(), expressionSerializer));
|
|
|
|
TextSerializer<InvalidInitializer> invalidInitializerSerializer =
|
|
Wrapped<void, InvalidInitializer>(
|
|
(_) => null, (_) => InvalidInitializer(), Nothing());
|
|
|
|
TextSerializer<LocalInitializer> localInitializerSerializer =
|
|
Wrapped<VariableDeclaration, LocalInitializer>((w) => w.variable,
|
|
(u) => LocalInitializer(u), variableDeclarationSerializer);
|
|
|
|
TextSerializer<RedirectingInitializer> redirectingInitializerSerializer =
|
|
Wrapped<Tuple2<CanonicalName, Arguments>, RedirectingInitializer>(
|
|
(w) => Tuple2(w.targetReference.canonicalName!, w.arguments),
|
|
(u) => RedirectingInitializer.byReference(u.first.reference, u.second),
|
|
Tuple2Serializer(CanonicalNameSerializer(), argumentsSerializer));
|
|
|
|
TextSerializer<SuperInitializer> superInitializerSerializer =
|
|
Wrapped<Tuple2<CanonicalName, Arguments>, SuperInitializer>(
|
|
(w) => Tuple2(w.targetReference.canonicalName!, w.arguments),
|
|
(u) => SuperInitializer.byReference(u.first.reference, u.second),
|
|
Tuple2Serializer(CanonicalNameSerializer(), argumentsSerializer));
|
|
|
|
Case<Initializer> initializerSerializer =
|
|
Case.uninitialized(InitializerTagger());
|
|
|
|
TextSerializer<Supertype> supertypeSerializer =
|
|
Wrapped<Tuple2<CanonicalName, List<DartType>>, Supertype>(
|
|
(w) => Tuple2(w.className.canonicalName!, w.typeArguments),
|
|
(u) => Supertype.byReference(u.first.reference, 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.FlagMacro: "macro",
|
|
};
|
|
|
|
class ClassFlagTagger implements Tagger<int> {
|
|
const ClassFlagTagger();
|
|
|
|
@override
|
|
String tag(int flag) {
|
|
return classFlagToName[flag] ??
|
|
(throw StateError("Unknown Class flag value: ${flag}."));
|
|
}
|
|
}
|
|
|
|
TextSerializer<int> classFlagsSerializer = Wrapped<List<int>, int>(
|
|
(w) => List.generate(30, (i) => w & (1 << i)).where((f) => f != 0).toList(),
|
|
(u) => u.fold(0, (fs, f) => fs |= f),
|
|
ListSerializer(Case(ClassFlagTagger(), convertFlagsMap(classFlagToName))));
|
|
|
|
TextSerializer<Class> classSerializer = Wrapped<
|
|
Tuple4<
|
|
String,
|
|
int,
|
|
Uri,
|
|
Tuple2<
|
|
List<TypeParameter>,
|
|
/* Comment added to guide formatting. */
|
|
Tuple4<Supertype?, Supertype?, List<Supertype>, List<Member>>>>,
|
|
Class>(
|
|
(w) => Tuple4(
|
|
w.name,
|
|
w.flags,
|
|
w.fileUri,
|
|
Tuple2(
|
|
w.typeParameters,
|
|
Tuple4(w.supertype, w.mixedInType, w.implementedTypes,
|
|
<Member>[...w.fields, ...w.constructors, ...w.procedures]))),
|
|
(u) => Class(
|
|
name: u.first,
|
|
typeParameters: u.fourth.first,
|
|
supertype: u.fourth.second.first,
|
|
mixedInType: u.fourth.second.second,
|
|
implementedTypes: u.fourth.second.third,
|
|
fields: u.fourth.second.fourth
|
|
.where((m) => m is Field)
|
|
.cast<Field>()
|
|
.toList(),
|
|
constructors: u.fourth.second.fourth
|
|
.where((m) => m is Constructor)
|
|
.cast<Constructor>()
|
|
.toList(),
|
|
procedures: u.fourth.second.fourth
|
|
.where((m) => m is Procedure)
|
|
.cast<Procedure>()
|
|
.toList(),
|
|
fileUri: u.third)
|
|
..flags = u.second,
|
|
Tuple4Serializer(
|
|
DartString(),
|
|
classFlagsSerializer,
|
|
UriSerializer(),
|
|
Bind(
|
|
typeParametersSerializer,
|
|
Tuple4Serializer(
|
|
Optional(supertypeSerializer),
|
|
Optional(supertypeSerializer),
|
|
ListSerializer(supertypeSerializer),
|
|
ListSerializer(memberSerializer)))));
|
|
|
|
TextSerializer<Typedef> typedefSerializer = Wrapped<
|
|
Tuple3<String, Tuple2<List<TypeParameter>, DartType>, Uri>, Typedef>(
|
|
(w) => Tuple3(w.name, Tuple2(w.typeParameters, w.type!), w.fileUri),
|
|
(u) => Typedef(u.first, u.second.second,
|
|
typeParameters: u.second.first, fileUri: u.third),
|
|
Tuple3Serializer(DartString(),
|
|
Bind(typeParametersSerializer, dartTypeSerializer), UriSerializer()));
|
|
|
|
const Map<int, String> extensionMemberDescriptorFlagToName = const {
|
|
ExtensionMemberDescriptor.FlagStatic: "static",
|
|
};
|
|
|
|
class ExtensionMemberDescriptorFlagTagger implements Tagger<int> {
|
|
const ExtensionMemberDescriptorFlagTagger();
|
|
|
|
@override
|
|
String tag(int flag) {
|
|
return extensionMemberDescriptorFlagToName[flag] ??
|
|
(throw StateError(
|
|
"Unknown ExtensionMemberDescriptor flag value: ${flag}."));
|
|
}
|
|
}
|
|
|
|
TextSerializer<int> extensionMemberDescriptorFlagsSerializer =
|
|
Wrapped<List<int>, int>(
|
|
(w) => List.generate(30, (i) => w & (1 << i))
|
|
.where((f) => f != 0)
|
|
.toList(),
|
|
(u) => u.fold(0, (fs, f) => fs |= f),
|
|
ListSerializer(Case(ExtensionMemberDescriptorFlagTagger(),
|
|
convertFlagsMap(extensionMemberDescriptorFlagToName))));
|
|
|
|
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();
|
|
|
|
@override
|
|
String tag(ExtensionMemberKind kind) {
|
|
return extensionMemberKindToName[kind] ??
|
|
(throw StateError("Unknown ExtensionMemberKind flag value: ${kind}."));
|
|
}
|
|
}
|
|
|
|
TextSerializer<ExtensionMemberKind> extensionMemberKindSerializer = Case(
|
|
ExtensionMemberKindTagger(), convertFlagsMap(extensionMemberKindToName));
|
|
|
|
TextSerializer<ExtensionMemberDescriptor> extensionMemberDescriptorSerializer =
|
|
Wrapped<Tuple4<Name, ExtensionMemberKind, int, CanonicalName>,
|
|
ExtensionMemberDescriptor>(
|
|
(w) => Tuple4(w.name, w.kind, w.flags, w.member.canonicalName!),
|
|
(u) => ExtensionMemberDescriptor(
|
|
name: u.first, kind: u.second, member: u.fourth.reference)
|
|
..flags = u.third,
|
|
Tuple4Serializer(
|
|
nameSerializer,
|
|
extensionMemberKindSerializer,
|
|
extensionMemberDescriptorFlagsSerializer,
|
|
CanonicalNameSerializer()));
|
|
|
|
TextSerializer<Extension> extensionSerializer = Wrapped<
|
|
Tuple4<String, Tuple2<List<TypeParameter>, DartType>,
|
|
List<ExtensionMemberDescriptor>, Uri>,
|
|
Extension>(
|
|
(w) => Tuple4(
|
|
w.name, Tuple2(w.typeParameters, w.onType), w.members, w.fileUri),
|
|
(u) => Extension(
|
|
name: u.first,
|
|
typeParameters: u.second.first,
|
|
onType: u.second.second,
|
|
members: u.third,
|
|
fileUri: u.fourth),
|
|
Tuple4Serializer(
|
|
DartString(),
|
|
Bind(typeParametersSerializer, dartTypeSerializer),
|
|
ListSerializer(extensionMemberDescriptorSerializer),
|
|
UriSerializer()));
|
|
|
|
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-instance": instanceGetSerializer,
|
|
"set-instance": instanceSetSerializer,
|
|
"get-dynamic": dynamicGetSerializer,
|
|
"set-dynamic": dynamicSetSerializer,
|
|
"tearoff-instance": instanceTearOffSerializer,
|
|
"tearoff-function": functionTearOffSerializer,
|
|
"get-super": superPropertyGetSerializer,
|
|
"set-super": superPropertySetSerializer,
|
|
"invoke-instance": instanceInvocationSerializer,
|
|
"invoke-instance-getter": instanceGetterInvocationSerializer,
|
|
"invoke-dynamic": dynamicInvocationSerializer,
|
|
"invoke-function": functionInvocationSerializer,
|
|
"invoke-local-function": localFunctionInvocationSerializer,
|
|
"equals-null": equalsNullSerializer,
|
|
"equals-call": equalsCallSerializer,
|
|
"invoke-super": superMethodInvocationSerializer,
|
|
"get-var": variableGetSerializer,
|
|
"set-var": variableSetSerializer,
|
|
"get-static": staticGetSerializer,
|
|
"set-static": staticSetSerializer,
|
|
"tearoff-static": staticTearOffSerializer,
|
|
"tearoff-constructor": constructorTearOffSerializer,
|
|
"tearoff-redirecting-factory": redirectingFactoryTearOffSerializer,
|
|
"tearoff-typedef": typedefTearOffSerializer,
|
|
"invoke-static": staticInvocationSerializer,
|
|
"invoke-const-static": constStaticInvocationSerializer,
|
|
"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,
|
|
"->": functionTypeSerializer,
|
|
"par": typeParameterTypeSerializer,
|
|
"interface": interfaceTypeSerializer,
|
|
"never": neverTypeSerializer,
|
|
"typedef": typedefTypeSerializer,
|
|
"futureor": futureOrTypeSerializer,
|
|
"null-type": nullTypeSerializer,
|
|
});
|
|
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({
|
|
"mutable-field": mutableFieldSerializer,
|
|
"immutable-field": immutableFieldSerializer,
|
|
"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": instantiationConstantSerializer,
|
|
"const-set": setConstantSerializer,
|
|
"const-string": stringConstantSerializer,
|
|
"const-symbol": symbolConstantSerializer,
|
|
"const-tearoff-static": staticTearOffConstantSerializer,
|
|
"const-tearoff-constructor": constructorTearOffConstantSerializer,
|
|
"const-tearoff-redirecting-factory":
|
|
redirectingFactoryTearOffConstantSerializer,
|
|
"const-tearoff-typedef": typedefTearOffConstantSerializer,
|
|
"const-type": typeLiteralConstantSerializer,
|
|
"const-expr": unevaluatedConstantSerializer,
|
|
"const-object": instanceConstantSerializer,
|
|
});
|
|
initializerSerializer.registerTags({
|
|
"assert": assertInitializerSerializer,
|
|
"field": fieldInitializerSerializer,
|
|
"invalid": invalidInitializerSerializer,
|
|
"local": localInitializerSerializer,
|
|
"redirecting": redirectingInitializerSerializer,
|
|
"super": superInitializerSerializer,
|
|
});
|
|
}
|
|
|
|
Map<String, Wrapped<void, T>> convertFlagsMap<T>(Map<T, String> map) {
|
|
return map.entries.toMap(
|
|
key: (e) => e.value,
|
|
value: (e) => Wrapped<void, T>((_) => null, (_) => e.key, Nothing()));
|
|
}
|
|
|
|
extension MapFromIterable<E> on Iterable<E> {
|
|
Map<K, V> toMap<K, V>(
|
|
{required K Function(E) key, required V Function(E) value}) {
|
|
return {for (E e in this) key(e): value(e)};
|
|
}
|
|
}
|