// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. library kernel.text_serializer; import '../ast.dart'; import 'serializer_combinators.dart'; import '../visitor.dart' show ExpressionVisitor; abstract class Tagger { String tag(T node); } class NameTagger implements Tagger { const NameTagger(); String tag(Name name) => name.isPrivate ? "private" : "public"; } TextSerializer publicName = new Wrapped(unwrapPublicName, wrapPublicName, const DartString()); String unwrapPublicName(Name name) => name.name; Name wrapPublicName(String name) => new Name(name); TextSerializer privateName = new Wrapped(unwrapPrivateName, wrapPrivateName, Tuple2Serializer(const DartString(), const DartString())); Tuple2 unwrapPrivateName(Name name) { return new Tuple2(name.library.importUri.toString(), name.name); } Name wrapPrivateName(Tuple2 tuple) { // We need a map from import URI to libraries. More generally, we will need // a way to map any 'named' node to the node's reference. throw UnimplementedError('deserialization of private names'); } TextSerializer nameSerializer = new Case(const NameTagger(), [ "public", "private", ], [ publicName, privateName ]); class ExpressionTagger extends ExpressionVisitor implements Tagger { const ExpressionTagger(); String tag(Expression expression) => expression.accept(this); String visitStringLiteral(StringLiteral _) => "string"; String visitIntLiteral(IntLiteral _) => "int"; String visitDoubleLiteral(DoubleLiteral _) => "double"; String visitBoolLiteral(BoolLiteral _) => "bool"; String visitNullLiteral(NullLiteral _) => "null"; String visitInvalidExpression(InvalidExpression _) => "invalid"; String visitNot(Not _) => "not"; String visitLogicalExpression(LogicalExpression expression) { return expression.operator; } String visitStringConcatenation(StringConcatenation _) => "concat"; String visitSymbolLiteral(SymbolLiteral _) => "symbol"; String visitThisExpression(ThisExpression _) => "this"; String visitRethrow(Rethrow _) => "rethrow"; String visitThrow(Throw _) => "throw"; String visitAwaitExpression(AwaitExpression _) => "await"; String visitConditionalExpression(ConditionalExpression _) => "cond"; String visitIsExpression(IsExpression _) => "is"; String visitAsExpression(AsExpression _) => "as"; String visitTypeLiteral(TypeLiteral _) => "type"; String visitListLiteral(ListLiteral expression) { return expression.isConst ? "const-list" : "list"; } String visitSetLiteral(SetLiteral expression) { return expression.isConst ? "const-set" : "set"; } String visitMapLiteral(MapLiteral expression) { return expression.isConst ? "const-map" : "map"; } String visitLet(Let _) => "let"; String visitPropertyGet(PropertyGet _) => "get-prop"; String visitPropertySet(PropertySet _) => "set-prop"; String visitSuperPropertyGet(SuperPropertyGet _) => "get-super"; String visitSuperPropertySet(SuperPropertySet _) => "set-super"; String visitMethodInvocation(MethodInvocation _) => "invoke-method"; String visitSuperMethodInvocation(SuperMethodInvocation _) => "invoke-super"; String visitVariableGet(VariableGet _) => "get-var"; String visitVariableSet(VariableSet _) => "set-var"; String visitStaticGet(StaticGet _) => "get-static"; String visitStaticSet(StaticSet _) => "set-static"; String visitDirectPropertyGet(DirectPropertyGet _) => "get-direct-prop"; String visitDirectPropertySet(DirectPropertySet _) => "set-direct-prop"; String visitStaticInvocation(StaticInvocation expression) { return expression.isConst ? "invoke-const-static" : "invoke-static"; } String visitDirectMethodInvocation(DirectMethodInvocation _) { return "invoke-direct-method"; } String visitConstructorInvocation(ConstructorInvocation expression) { return expression.isConst ? "invoke-const-constructor" : "invoke-constructor"; } } TextSerializer invalidExpressionSerializer = new Wrapped( unwrapInvalidExpression, wrapInvalidExpression, const DartString()); String unwrapInvalidExpression(InvalidExpression expression) { return expression.message; } InvalidExpression wrapInvalidExpression(String message) { return new InvalidExpression(message); } TextSerializer notSerializer = new Wrapped(unwrapNot, wrapNot, expressionSerializer); Expression unwrapNot(Not expression) => expression.operand; Not wrapNot(Expression operand) => new Not(operand); TextSerializer logicalAndSerializer = new Wrapped( unwrapLogicalExpression, wrapLogicalAnd, new Tuple2Serializer(expressionSerializer, expressionSerializer)); Tuple2 unwrapLogicalExpression( LogicalExpression expression) { return new Tuple2(expression.left, expression.right); } LogicalExpression wrapLogicalAnd(Tuple2 tuple) { return new LogicalExpression(tuple.first, '&&', tuple.second); } TextSerializer logicalOrSerializer = new Wrapped( unwrapLogicalExpression, wrapLogicalOr, new Tuple2Serializer(expressionSerializer, expressionSerializer)); LogicalExpression wrapLogicalOr(Tuple2 tuple) { return new LogicalExpression(tuple.first, '||', tuple.second); } TextSerializer stringConcatenationSerializer = new Wrapped( unwrapStringConcatenation, wrapStringConcatenation, new ListSerializer(expressionSerializer)); List unwrapStringConcatenation(StringConcatenation expression) { return expression.expressions; } StringConcatenation wrapStringConcatenation(List expressions) { return new StringConcatenation(expressions); } TextSerializer stringLiteralSerializer = new Wrapped(unwrapStringLiteral, wrapStringLiteral, const DartString()); String unwrapStringLiteral(StringLiteral literal) => literal.value; StringLiteral wrapStringLiteral(String value) => new StringLiteral(value); TextSerializer intLiteralSerializer = new Wrapped(unwrapIntLiteral, wrapIntLiteral, const DartInt()); int unwrapIntLiteral(IntLiteral literal) => literal.value; IntLiteral wrapIntLiteral(int value) => new IntLiteral(value); TextSerializer doubleLiteralSerializer = new Wrapped(unwrapDoubleLiteral, wrapDoubleLiteral, const DartDouble()); double unwrapDoubleLiteral(DoubleLiteral literal) => literal.value; DoubleLiteral wrapDoubleLiteral(double value) => new DoubleLiteral(value); TextSerializer boolLiteralSerializer = new Wrapped(unwrapBoolLiteral, wrapBoolLiteral, const DartBool()); bool unwrapBoolLiteral(BoolLiteral literal) => literal.value; BoolLiteral wrapBoolLiteral(bool value) => new BoolLiteral(value); TextSerializer nullLiteralSerializer = new Wrapped(unwrapNullLiteral, wrapNullLiteral, const Nothing()); void unwrapNullLiteral(NullLiteral literal) {} NullLiteral wrapNullLiteral(void ignored) => new NullLiteral(); TextSerializer symbolLiteralSerializer = new Wrapped(unwrapSymbolLiteral, wrapSymbolLiteral, const DartString()); String unwrapSymbolLiteral(SymbolLiteral expression) => expression.value; SymbolLiteral wrapSymbolLiteral(String value) => new SymbolLiteral(value); TextSerializer thisExpressionSerializer = new Wrapped(unwrapThisExpression, wrapThisExpression, const Nothing()); void unwrapThisExpression(ThisExpression expression) {} ThisExpression wrapThisExpression(void ignored) => new ThisExpression(); TextSerializer rethrowSerializer = new Wrapped(unwrapRethrow, wrapRethrow, const Nothing()); void unwrapRethrow(Rethrow expression) {} Rethrow wrapRethrow(void ignored) => new Rethrow(); TextSerializer throwSerializer = new Wrapped(unwrapThrow, wrapThrow, expressionSerializer); Expression unwrapThrow(Throw expression) => expression.expression; Throw wrapThrow(Expression expression) => new Throw(expression); TextSerializer awaitExpressionSerializer = new Wrapped( unwrapAwaitExpression, wrapAwaitExpression, expressionSerializer); Expression unwrapAwaitExpression(AwaitExpression expression) => expression.operand; AwaitExpression wrapAwaitExpression(Expression operand) => new AwaitExpression(operand); TextSerializer conditionalExpressionSerializer = new Wrapped( unwrapConditionalExpression, wrapConditionalExpression, new Tuple4Serializer(expressionSerializer, dartTypeSerializer, expressionSerializer, expressionSerializer)); Tuple4 unwrapConditionalExpression(ConditionalExpression expression) { return new Tuple4(expression.condition, expression.staticType, expression.then, expression.otherwise); } ConditionalExpression wrapConditionalExpression( Tuple4 tuple) { return new ConditionalExpression( tuple.first, tuple.third, tuple.fourth, tuple.second); } TextSerializer isExpressionSerializer = new Wrapped( unwrapIsExpression, wrapIsExpression, new Tuple2Serializer(expressionSerializer, dartTypeSerializer)); Tuple2 unwrapIsExpression(IsExpression expression) { return new Tuple2(expression.operand, expression.type); } IsExpression wrapIsExpression(Tuple2 tuple) { return new IsExpression(tuple.first, tuple.second); } TextSerializer asExpressionSerializer = new Wrapped( unwrapAsExpression, wrapAsExpression, new Tuple2Serializer(expressionSerializer, dartTypeSerializer)); Tuple2 unwrapAsExpression(AsExpression expression) { return new Tuple2(expression.operand, expression.type); } AsExpression wrapAsExpression(Tuple2 tuple) { return new AsExpression(tuple.first, tuple.second); } TextSerializer typeLiteralSerializer = new Wrapped(unwrapTypeLiteral, wrapTypeLiteral, dartTypeSerializer); DartType unwrapTypeLiteral(TypeLiteral expression) => expression.type; TypeLiteral wrapTypeLiteral(DartType type) => new TypeLiteral(type); TextSerializer listLiteralSerializer = new Wrapped( unwrapListLiteral, wrapListLiteral, new Tuple2Serializer( dartTypeSerializer, new ListSerializer(expressionSerializer))); Tuple2> unwrapListLiteral(ListLiteral expression) { return new Tuple2(expression.typeArgument, expression.expressions); } ListLiteral wrapListLiteral(Tuple2> tuple) { return new ListLiteral(tuple.second, typeArgument: tuple.first, isConst: false); } TextSerializer constListLiteralSerializer = new Wrapped( unwrapListLiteral, wrapConstListLiteral, new Tuple2Serializer( dartTypeSerializer, new ListSerializer(expressionSerializer))); ListLiteral wrapConstListLiteral(Tuple2> tuple) { return new ListLiteral(tuple.second, typeArgument: tuple.first, isConst: true); } TextSerializer setLiteralSerializer = new Wrapped( unwrapSetLiteral, wrapSetLiteral, new Tuple2Serializer( dartTypeSerializer, new ListSerializer(expressionSerializer))); Tuple2> unwrapSetLiteral(SetLiteral expression) { return new Tuple2(expression.typeArgument, expression.expressions); } SetLiteral wrapSetLiteral(Tuple2> tuple) { return new SetLiteral(tuple.second, typeArgument: tuple.first, isConst: false); } TextSerializer constSetLiteralSerializer = new Wrapped( unwrapSetLiteral, wrapConstSetLiteral, new Tuple2Serializer( dartTypeSerializer, new ListSerializer(expressionSerializer))); SetLiteral wrapConstSetLiteral(Tuple2> tuple) { return new SetLiteral(tuple.second, typeArgument: tuple.first, isConst: true); } TextSerializer mapLiteralSerializer = new Wrapped( unwrapMapLiteral, wrapMapLiteral, new Tuple3Serializer(dartTypeSerializer, dartTypeSerializer, new ListSerializer(expressionSerializer))); Tuple3> unwrapMapLiteral( MapLiteral expression) { List entries = new List(2 * expression.entries.length); for (int from = 0, to = 0; from < expression.entries.length; ++from) { MapEntry entry = expression.entries[from]; entries[to++] = entry.key; entries[to++] = entry.value; } return new Tuple3(expression.keyType, expression.valueType, entries); } MapLiteral wrapMapLiteral(Tuple3> tuple) { List entries = new List(tuple.third.length ~/ 2); for (int from = 0, to = 0; to < entries.length; ++to) { entries[to] = new MapEntry(tuple.third[from++], tuple.third[from++]); } return new MapLiteral(entries, keyType: tuple.first, valueType: tuple.second, isConst: false); } TextSerializer constMapLiteralSerializer = new Wrapped( unwrapMapLiteral, wrapConstMapLiteral, new Tuple3Serializer(dartTypeSerializer, dartTypeSerializer, new ListSerializer(expressionSerializer))); MapLiteral wrapConstMapLiteral( Tuple3> tuple) { List entries = new List(tuple.third.length ~/ 2); for (int from = 0, to = 0; to < entries.length; ++to) { entries[to] = new MapEntry(tuple.third[from++], tuple.third[from++]); } return new MapLiteral(entries, keyType: tuple.first, valueType: tuple.second, isConst: true); } TextSerializer letSerializer = new Wrapped( unwrapLet, wrapLet, new Bind( new Binder(variableDeclarationSerializer, getVariableDeclarationName, setVariableDeclarationName), expressionSerializer)); Tuple2 unwrapLet(Let expression) { return new Tuple2(expression.variable, expression.body); } Let wrapLet(Tuple2 tuple) { return new Let(tuple.first, tuple.second); } String getVariableDeclarationName(VariableDeclaration node) => node.name; void setVariableDeclarationName(VariableDeclaration node, String name) { node.name = name; } TextSerializer propertyGetSerializer = new Wrapped( unwrapPropertyGet, wrapPropertyGet, new Tuple2Serializer(expressionSerializer, nameSerializer)); Tuple2 unwrapPropertyGet(PropertyGet expression) { return new Tuple2(expression.receiver, expression.name); } PropertyGet wrapPropertyGet(Tuple2 tuple) { return new PropertyGet(tuple.first, tuple.second); } TextSerializer propertySetSerializer = new Wrapped( unwrapPropertySet, wrapPropertySet, new Tuple3Serializer( expressionSerializer, nameSerializer, expressionSerializer)); Tuple3 unwrapPropertySet(PropertySet expression) { return new Tuple3(expression.receiver, expression.name, expression.value); } PropertySet wrapPropertySet(Tuple3 tuple) { return new PropertySet(tuple.first, tuple.second, tuple.third); } TextSerializer superPropertyGetSerializer = new Wrapped(unwrapSuperPropertyGet, wrapSuperPropertyGet, nameSerializer); Name unwrapSuperPropertyGet(SuperPropertyGet expression) { return expression.name; } SuperPropertyGet wrapSuperPropertyGet(Name name) { return new SuperPropertyGet(name); } TextSerializer superPropertySetSerializer = new Wrapped( unwrapSuperPropertySet, wrapSuperPropertySet, new Tuple2Serializer(nameSerializer, expressionSerializer)); Tuple2 unwrapSuperPropertySet(SuperPropertySet expression) { return new Tuple2(expression.name, expression.value); } SuperPropertySet wrapSuperPropertySet(Tuple2 tuple) { return new SuperPropertySet(tuple.first, tuple.second, null); } TextSerializer methodInvocationSerializer = new Wrapped( unwrapMethodInvocation, wrapMethodInvocation, new Tuple3Serializer( expressionSerializer, nameSerializer, argumentsSerializer)); Tuple3 unwrapMethodInvocation( MethodInvocation expression) { return new Tuple3(expression.receiver, expression.name, expression.arguments); } MethodInvocation wrapMethodInvocation( Tuple3 tuple) { return new MethodInvocation(tuple.first, tuple.second, tuple.third); } TextSerializer superMethodInvocationSerializer = new Wrapped(unwrapSuperMethodInvocation, wrapSuperMethodInvocation, new Tuple2Serializer(nameSerializer, argumentsSerializer)); Tuple2 unwrapSuperMethodInvocation( SuperMethodInvocation expression) { return new Tuple2(expression.name, expression.arguments); } SuperMethodInvocation wrapSuperMethodInvocation(Tuple2 tuple) { return new SuperMethodInvocation(tuple.first, tuple.second); } TextSerializer variableGetSerializer = new Wrapped( unwrapVariableGet, wrapVariableGet, new Tuple2Serializer(const ScopedUse(), new Optional(dartTypeSerializer))); Tuple2 unwrapVariableGet(VariableGet node) { return new Tuple2( node.variable, node.promotedType); } VariableGet wrapVariableGet(Tuple2 tuple) { return new VariableGet(tuple.first, tuple.second); } TextSerializer variableSetSerializer = new Wrapped( unwrapVariableSet, wrapVariableSet, new Tuple2Serializer( const ScopedUse(), expressionSerializer)); Tuple2 unwrapVariableSet(VariableSet node) { return new Tuple2(node.variable, node.value); } VariableSet wrapVariableSet(Tuple2 tuple) { return new VariableSet(tuple.first, tuple.second); } class CanonicalNameSerializer extends TextSerializer { static const String delimiter = "::"; const CanonicalNameSerializer(); static void writeName(CanonicalName name, StringBuffer buffer) { if (!name.isRoot) { if (!name.parent.isRoot) { writeName(name.parent, buffer); buffer.write(delimiter); } buffer.write(name.name); } } CanonicalName readFrom(Iterator stream, DeserializationState state) { String string = const DartString().readFrom(stream, state); CanonicalName name = state.nameRoot; for (String s in string.split(delimiter)) { name = name.getChild(s); } return name; } void writeTo( StringBuffer buffer, CanonicalName name, SerializationState state) { StringBuffer sb = new StringBuffer(); writeName(name, sb); const DartString().writeTo(buffer, sb.toString(), state); } } TextSerializer staticGetSerializer = new Wrapped(unwrapStaticGet, wrapStaticGet, new CanonicalNameSerializer()); CanonicalName unwrapStaticGet(StaticGet expression) { return expression.targetReference.canonicalName; } StaticGet wrapStaticGet(CanonicalName name) { return new StaticGet.byReference(name.getReference()); } TextSerializer staticSetSerializer = new Wrapped( unwrapStaticSet, wrapStaticSet, new Tuple2Serializer( const CanonicalNameSerializer(), expressionSerializer)); Tuple2 unwrapStaticSet(StaticSet expression) { return new Tuple2(expression.targetReference.canonicalName, expression.value); } StaticSet wrapStaticSet(Tuple2 tuple) { return new StaticSet.byReference(tuple.first.getReference(), tuple.second); } TextSerializer directPropertyGetSerializer = new Wrapped( unwrapDirectPropertyGet, wrapDirectPropertyGet, new Tuple2Serializer( expressionSerializer, const CanonicalNameSerializer())); Tuple2 unwrapDirectPropertyGet( DirectPropertyGet expression) { return new Tuple2( expression.receiver, expression.targetReference.canonicalName); } DirectPropertyGet wrapDirectPropertyGet( Tuple2 tuple) { return new DirectPropertyGet.byReference( tuple.first, tuple.second.getReference()); } TextSerializer directPropertySetSerializer = new Wrapped( unwrapDirectPropertySet, wrapDirectPropertySet, new Tuple3Serializer(expressionSerializer, const CanonicalNameSerializer(), expressionSerializer)); Tuple3 unwrapDirectPropertySet( DirectPropertySet expression) { return new Tuple3(expression.receiver, expression.targetReference.canonicalName, expression.value); } DirectPropertySet wrapDirectPropertySet( Tuple3 tuple) { return new DirectPropertySet.byReference( tuple.first, tuple.second.getReference(), tuple.third); } TextSerializer staticInvocationSerializer = new Wrapped( unwrapStaticInvocation, wrapStaticInvocation, new Tuple2Serializer(const CanonicalNameSerializer(), argumentsSerializer)); Tuple2 unwrapStaticInvocation( StaticInvocation expression) { return new Tuple2( expression.targetReference.canonicalName, expression.arguments); } StaticInvocation wrapStaticInvocation(Tuple2 tuple) { return new StaticInvocation.byReference( tuple.first.getReference(), tuple.second, isConst: false); } TextSerializer constStaticInvocationSerializer = new Wrapped( unwrapStaticInvocation, wrapConstStaticInvocation, new Tuple2Serializer(const CanonicalNameSerializer(), argumentsSerializer)); StaticInvocation wrapConstStaticInvocation( Tuple2 tuple) { return new StaticInvocation.byReference( tuple.first.getReference(), tuple.second, isConst: true); } TextSerializer directMethodInvocationSerializer = new Wrapped( unwrapDirectMethodInvocation, wrapDirectMethodInvocation, new Tuple3Serializer(expressionSerializer, const CanonicalNameSerializer(), argumentsSerializer)); Tuple3 unwrapDirectMethodInvocation( DirectMethodInvocation expression) { return new Tuple3(expression.receiver, expression.targetReference.canonicalName, expression.arguments); } DirectMethodInvocation wrapDirectMethodInvocation( Tuple3 tuple) { return new DirectMethodInvocation.byReference( tuple.first, tuple.second.getReference(), tuple.third); } TextSerializer constructorInvocationSerializer = new Wrapped( unwrapConstructorInvocation, wrapConstructorInvocation, new Tuple2Serializer( const CanonicalNameSerializer(), argumentsSerializer)); Tuple2 unwrapConstructorInvocation( ConstructorInvocation expression) { return new Tuple2( expression.targetReference.canonicalName, expression.arguments); } ConstructorInvocation wrapConstructorInvocation( Tuple2 tuple) { return new ConstructorInvocation.byReference( tuple.first.getReference(), tuple.second, isConst: false); } TextSerializer constConstructorInvocationSerializer = new Wrapped(unwrapConstructorInvocation, wrapConstConstructorInvocation, Tuple2Serializer(const CanonicalNameSerializer(), argumentsSerializer)); ConstructorInvocation wrapConstConstructorInvocation( Tuple2 tuple) { return new ConstructorInvocation.byReference( tuple.first.getReference(), tuple.second, isConst: true); } Case expressionSerializer = new Case.uninitialized(const ExpressionTagger()); TextSerializer namedExpressionSerializer = new Wrapped( unwrapNamedExpression, wrapNamedExpression, new Tuple2Serializer(const DartString(), expressionSerializer)); Tuple2 unwrapNamedExpression(NamedExpression expression) { return new Tuple2(expression.name, expression.value); } NamedExpression wrapNamedExpression(Tuple2 tuple) { return new NamedExpression(tuple.first, tuple.second); } TextSerializer argumentsSerializer = new Wrapped( unwrapArguments, wrapArguments, Tuple3Serializer( new ListSerializer(dartTypeSerializer), new ListSerializer(expressionSerializer), new ListSerializer(namedExpressionSerializer))); Tuple3, List, List> unwrapArguments( Arguments arguments) { return new Tuple3(arguments.types, arguments.positional, arguments.named); } Arguments wrapArguments( Tuple3, List, List> tuple) { return new Arguments(tuple.second, types: tuple.first, named: tuple.third); } class VariableDeclarationTagger implements Tagger { const VariableDeclarationTagger(); String tag(VariableDeclaration decl) { if (decl.isCovariant) throw UnimplementedError("covariant declaration"); if (decl.isFieldFormal) throw UnimplementedError("initializing formal"); if (decl.isConst) { // It's not clear what invariants we assume about const/final. For now // throw if we have both. if (decl.isFinal) throw UnimplementedError("const and final"); return "const"; } if (decl.isFinal) { return "final"; } return "var"; } } TextSerializer varDeclarationSerializer = new Wrapped( unwrapVariableDeclaration, wrapVarDeclaration, Tuple4Serializer( const DartString(), dartTypeSerializer, new Optional(expressionSerializer), new ListSerializer(expressionSerializer))); Tuple4> unwrapVariableDeclaration(VariableDeclaration declaration) { return new Tuple4(declaration.name ?? "", declaration.type, declaration.initializer, declaration.annotations); } VariableDeclaration wrapVarDeclaration( Tuple4> tuple) { var result = new VariableDeclaration(tuple.first.isEmpty ? null : tuple.first, initializer: tuple.third, type: tuple.second); for (int i = 0; i < tuple.fourth.length; ++i) { result.addAnnotation(tuple.fourth[i]); } return result; } TextSerializer finalDeclarationSerializer = new Wrapped( unwrapVariableDeclaration, wrapFinalDeclaration, Tuple4Serializer( const DartString(), dartTypeSerializer, new Optional(expressionSerializer), new ListSerializer(expressionSerializer))); VariableDeclaration wrapFinalDeclaration( Tuple4> tuple) { var result = new VariableDeclaration(tuple.first.isEmpty ? null : tuple.first, initializer: tuple.third, type: tuple.second, isFinal: true); for (int i = 0; i < tuple.fourth.length; ++i) { result.addAnnotation(tuple.fourth[i]); } return result; } TextSerializer constDeclarationSerializer = new Wrapped( unwrapVariableDeclaration, wrapConstDeclaration, Tuple4Serializer( const DartString(), dartTypeSerializer, new Optional(expressionSerializer), new ListSerializer(expressionSerializer))); VariableDeclaration wrapConstDeclaration( Tuple4> tuple) { var result = new VariableDeclaration(tuple.first.isEmpty ? null : tuple.first, initializer: tuple.third, type: tuple.second, isConst: true); for (int i = 0; i < tuple.fourth.length; ++i) { result.addAnnotation(tuple.fourth[i]); } return result; } TextSerializer variableDeclarationSerializer = new Case(const VariableDeclarationTagger(), [ "var", "final", "const", ], [ varDeclarationSerializer, finalDeclarationSerializer, constDeclarationSerializer, ]); TextSerializer typeParameterSerializer = new Wrapped(unwrapTypeParameter, wrapTypeParameter, const DartString()); String unwrapTypeParameter(TypeParameter node) => node.name; TypeParameter wrapTypeParameter(String name) => new TypeParameter(name); TextSerializer> typeParametersSerializer = new Zip( new Rebind( new Zip( new Rebind( new ListSerializer(new Binder(typeParameterSerializer, getTypeParameterName, setTypeParameterName)), new ListSerializer(dartTypeSerializer)), zipTypeParameterBound, unzipTypeParameterBound), new ListSerializer(dartTypeSerializer)), zipTypeParameterDefaultType, unzipTypeParameterDefaultType); String getTypeParameterName(TypeParameter node) => node.name; void setTypeParameterName(TypeParameter node, String name) { node.name = name; } TypeParameter zipTypeParameterBound(TypeParameter node, DartType bound) { return node..bound = bound; } Tuple2 unzipTypeParameterBound(TypeParameter node) { return new Tuple2(node, node.bound); } TypeParameter zipTypeParameterDefaultType( TypeParameter node, DartType defaultType) { return node..defaultType = defaultType; } Tuple2 unzipTypeParameterDefaultType( TypeParameter node) { return new Tuple2(node, node.defaultType); } class DartTypeTagger extends DartTypeVisitor implements Tagger { const DartTypeTagger(); String tag(DartType type) => type.accept(this); String visitInvalidType(InvalidType _) => "invalid"; String visitDynamicType(DynamicType _) => "dynamic"; String visitVoidType(VoidType _) => "void"; String visitBottomType(BottomType _) => "bottom"; String visitFunctionType(FunctionType _) => "->"; String visitTypeParameterType(TypeParameterType _) => "par"; } TextSerializer invalidTypeSerializer = new Wrapped(unwrapInvalidType, wrapInvalidType, const Nothing()); void unwrapInvalidType(InvalidType type) {} InvalidType wrapInvalidType(void ignored) => const InvalidType(); TextSerializer dynamicTypeSerializer = new Wrapped(unwrapDynamicType, wrapDynamicType, const Nothing()); void unwrapDynamicType(DynamicType type) {} DynamicType wrapDynamicType(void ignored) => const DynamicType(); TextSerializer voidTypeSerializer = new Wrapped(unwrapVoidType, wrapVoidType, const Nothing()); void unwrapVoidType(VoidType type) {} VoidType wrapVoidType(void ignored) => const VoidType(); TextSerializer bottomTypeSerializer = new Wrapped(unwrapBottomType, wrapBottomType, const Nothing()); void unwrapBottomType(BottomType type) {} BottomType wrapBottomType(void ignored) => const BottomType(); // TODO(dmitryas): Also handle nameParameters, and typedefType. TextSerializer functionTypeSerializer = new Wrapped( unwrapFunctionType, wrapFunctionType, new Bind( typeParametersSerializer, new Tuple4Serializer( new ListSerializer(dartTypeSerializer), new ListSerializer(dartTypeSerializer), new ListSerializer(namedTypeSerializer), dartTypeSerializer))); Tuple2, Tuple4, List, List, 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, Tuple4, List, List, DartType>> tuple) { return new FunctionType( tuple.second.first + tuple.second.second, tuple.second.fourth, requiredParameterCount: tuple.second.first.length, typeParameters: tuple.first, namedParameters: tuple.second.third); } TextSerializer namedTypeSerializer = new Wrapped(unwrapNamedType, wrapNamedType, Tuple2Serializer(const DartString(), dartTypeSerializer)); Tuple2 unwrapNamedType(NamedType namedType) { return new Tuple2(namedType.name, namedType.type); } NamedType wrapNamedType(Tuple2 tuple) { return new NamedType(tuple.first, tuple.second); } TextSerializer typeParameterTypeSerializer = new Wrapped( unwrapTypeParameterType, wrapTypeParameterType, Tuple2Serializer( new ScopedUse(), new Optional(dartTypeSerializer))); Tuple2 unwrapTypeParameterType( TypeParameterType node) { return new Tuple2(node.parameter, node.promotedBound); } TypeParameterType wrapTypeParameterType(Tuple2 tuple) { return new TypeParameterType(tuple.first, tuple.second); } Case dartTypeSerializer = new Case.uninitialized(const DartTypeTagger()); class StatementTagger extends StatementVisitor implements Tagger { const StatementTagger(); String tag(Statement statement) => statement.accept(this); String visitExpressionStatement(ExpressionStatement _) => "expr"; } TextSerializer expressionStatementSerializer = new Wrapped( unwrapExpressionStatement, wrapExpressionStatement, expressionSerializer); Expression unwrapExpressionStatement(ExpressionStatement statement) { return statement.expression; } ExpressionStatement wrapExpressionStatement(Expression expression) { return new ExpressionStatement(expression); } Case statementSerializer = new Case.uninitialized(const StatementTagger()); void initializeSerializers() { expressionSerializer.tags.addAll([ "string", "int", "double", "bool", "null", "invalid", "not", "&&", "||", "concat", "symbol", "this", "rethrow", "throw", "await", "cond", "is", "as", "type", "list", "const-list", "set", "const-set", "map", "const-map", "let", "get-prop", "set-prop", "get-super", "set-super", "invoke-method", "invoke-super", "get-var", "set-var", "get-static", "set-static", "get-direct-prop", "set-direct-prop", "invoke-static", "invoke-const-static", "invoke-direct-method", "invoke-constructor", "invoke-const-constructor", ]); expressionSerializer.serializers.addAll([ stringLiteralSerializer, intLiteralSerializer, doubleLiteralSerializer, boolLiteralSerializer, nullLiteralSerializer, invalidExpressionSerializer, notSerializer, logicalAndSerializer, logicalOrSerializer, stringConcatenationSerializer, symbolLiteralSerializer, thisExpressionSerializer, rethrowSerializer, throwSerializer, awaitExpressionSerializer, conditionalExpressionSerializer, isExpressionSerializer, asExpressionSerializer, typeLiteralSerializer, listLiteralSerializer, constListLiteralSerializer, setLiteralSerializer, constSetLiteralSerializer, mapLiteralSerializer, constMapLiteralSerializer, letSerializer, propertyGetSerializer, propertySetSerializer, superPropertyGetSerializer, superPropertySetSerializer, methodInvocationSerializer, superMethodInvocationSerializer, variableGetSerializer, variableSetSerializer, staticGetSerializer, staticSetSerializer, directPropertyGetSerializer, directPropertySetSerializer, staticInvocationSerializer, constStaticInvocationSerializer, directMethodInvocationSerializer, constructorInvocationSerializer, constConstructorInvocationSerializer, ]); dartTypeSerializer.tags.addAll([ "invalid", "dynamic", "void", "bottom", "->", "par", ]); dartTypeSerializer.serializers.addAll([ invalidTypeSerializer, dynamicTypeSerializer, voidTypeSerializer, bottomTypeSerializer, functionTypeSerializer, typeParameterTypeSerializer, ]); statementSerializer.tags.addAll([ "expr", ]); statementSerializer.serializers.addAll([ expressionStatementSerializer, ]); }