diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt index e61defdddde5..a0508a324ce9 100644 --- a/pkg/front_end/test/spell_checking_list_code.txt +++ b/pkg/front_end/test/spell_checking_list_code.txt @@ -406,6 +406,7 @@ field1 field1a field1b field2 +fieldformal file's filenames finv diff --git a/pkg/kernel/lib/text/text_serialization_verifier.dart b/pkg/kernel/lib/text/text_serialization_verifier.dart index ea087148af06..ee673a61b995 100644 --- a/pkg/kernel/lib/text/text_serialization_verifier.dart +++ b/pkg/kernel/lib/text/text_serialization_verifier.dart @@ -322,18 +322,9 @@ class VerificationState { } } - static bool isStatementSupported(Statement node) => - !isStatementNotSupported(node); - - static bool isStatementNotSupported(Statement node) => - node is VariableDeclaration && - (node.parent is! Block || node.name == null) || - node is FunctionDeclaration; - static bool isSupported(Node node) => !isNotSupported(node); static bool isNotSupported(Node node) => - node is Statement && isStatementNotSupported(node) || node is FunctionNode && node.body == null || node is Procedure && (!node.isStatic || node.kind != ProcedureKind.Method) || diff --git a/pkg/kernel/lib/text/text_serializer.dart b/pkg/kernel/lib/text/text_serializer.dart index fc7614b1a08d..00316f626da1 100644 --- a/pkg/kernel/lib/text/text_serializer.dart +++ b/pkg/kernel/lib/text/text_serializer.dart @@ -803,82 +803,71 @@ class VariableDeclarationTagger implements Tagger { const VariableDeclarationTagger(); String tag(VariableDeclaration decl) { - if (decl.isCovariant) throw UnimplementedError("Covariant declaration."); - if (decl.isFieldFormal) throw UnimplementedError("Initializing formal."); + String prefix = ""; + if (decl.isCovariant) { + prefix = "${prefix}covariant-"; + if (decl.isFieldFormal) { + // Field formals can only be used in constructors, + // and "covariant" keyword doesn't make sense for them. + throw StateError("Encountered covariant field formal."); + } + } + if (decl.isFieldFormal) { + prefix = "${prefix}fieldformal-"; + } + 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) { + throw UnimplementedError( + "Encountered a variable that is both const and final."); + } + return "${prefix}const"; } if (decl.isFinal) { - return "final"; + return "${prefix}final"; } - return "var"; - } -} - -TextSerializer varDeclarationSerializer = new Wrapped( - unwrapVariableDeclaration, - wrapVarDeclaration, - Tuple3Serializer(dartTypeSerializer, new Optional(expressionSerializer), - new ListSerializer(expressionSerializer))); - -Tuple3> unwrapVariableDeclaration( - VariableDeclaration declaration) { - return new Tuple3( - declaration.type, declaration.initializer, declaration.annotations); -} - -VariableDeclaration wrapVarDeclaration( - Tuple3> tuple) { - var result = new VariableDeclaration(null, - initializer: tuple.second, type: tuple.first); - for (int i = 0; i < tuple.third.length; ++i) { - result.addAnnotation(tuple.third[i]); - } - return result; -} - -TextSerializer finalDeclarationSerializer = new Wrapped( - unwrapVariableDeclaration, - wrapFinalDeclaration, - Tuple3Serializer(dartTypeSerializer, new Optional(expressionSerializer), - new ListSerializer(expressionSerializer))); - -VariableDeclaration wrapFinalDeclaration( - Tuple3> tuple) { - var result = new VariableDeclaration(null, - initializer: tuple.second, type: tuple.first, isFinal: true); - for (int i = 0; i < tuple.third.length; ++i) { - result.addAnnotation(tuple.third[i]); + return "${prefix}var"; } - return result; } -TextSerializer constDeclarationSerializer = new Wrapped( - unwrapVariableDeclaration, - wrapConstDeclaration, - Tuple3Serializer(dartTypeSerializer, new Optional(expressionSerializer), - new ListSerializer(expressionSerializer))); - -VariableDeclaration wrapConstDeclaration( - Tuple3> tuple) { - var result = new VariableDeclaration(null, - initializer: tuple.second, type: tuple.first, isConst: true); - for (int i = 0; i < tuple.third.length; ++i) { - result.addAnnotation(tuple.third[i]); - } - return result; -} +TextSerializer makeVariableDeclarationSerializer( + {bool isFinal = false, + bool isConst = false, + bool isCovariant = false, + bool isFieldFormal = false}) => + new Wrapped( + (w) => Tuple3(w.type, w.initializer, w.annotations), + (u) => u.third.fold( + VariableDeclaration(null, + type: u.first, + initializer: u.second, + isFinal: isFinal, + isConst: isConst, + isCovariant: isCovariant, + isFieldFormal: isFieldFormal), + (v, a) => v..addAnnotation(a)), + Tuple3Serializer(dartTypeSerializer, new Optional(expressionSerializer), + new ListSerializer(expressionSerializer))); TextSerializer variableDeclarationSerializer = Wrapped( (v) => Tuple2(v.name, v), (t) => t.second..name = t.first, Binder(Case(VariableDeclarationTagger(), { - "var": varDeclarationSerializer, - "final": finalDeclarationSerializer, - "const": constDeclarationSerializer, + "var": makeVariableDeclarationSerializer(), + "final": makeVariableDeclarationSerializer(isFinal: true), + "const": makeVariableDeclarationSerializer(isConst: true), + "covariant-var": makeVariableDeclarationSerializer(isCovariant: true), + "covariant-final": + makeVariableDeclarationSerializer(isCovariant: true, isFinal: true), + "covariant-const": + makeVariableDeclarationSerializer(isCovariant: true, isConst: true), + "fieldformal-var": makeVariableDeclarationSerializer(isFieldFormal: true), + "fieldformal-final": + makeVariableDeclarationSerializer(isFieldFormal: true, isFinal: true), + "fieldformal-const": + makeVariableDeclarationSerializer(isFieldFormal: true, isConst: true), }))); TextSerializer typeParameterSerializer = Wrapped( @@ -1108,6 +1097,7 @@ class StatementTagger extends StatementVisitor String visitSwitchStatement(SwitchStatement node) => "switch"; String visitContinueSwitchStatement(ContinueSwitchStatement node) => "continue"; + String visitFunctionDeclaration(FunctionDeclaration node) => "local-fun"; } TextSerializer expressionStatementSerializer = new Wrapped( @@ -1282,28 +1272,14 @@ DoStatement wrapDoStatement(Tuple2 tuple) { } TextSerializer forStatementSerializer = new Wrapped( - unwrapForStatement, - wrapForStatement, + (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(expressionSerializer, + new Tuple3Serializer(Optional(expressionSerializer), new ListSerializer(expressionSerializer), statementSerializer))); -Tuple2, - Tuple3, Statement>> - unwrapForStatement(ForStatement node) { - return new Tuple2( - node.variables, new Tuple3(node.condition, node.updates, node.body)); -} - -ForStatement wrapForStatement( - Tuple2, - Tuple3, Statement>> - tuple) { - return new ForStatement( - tuple.first, tuple.second.first, tuple.second.second, tuple.second.third); -} - TextSerializer forInStatementSerializer = new Wrapped( unwrapForInStatement, wrapForInStatement, @@ -1370,13 +1346,15 @@ TextSerializer tryCatchSerializer = Wrapped( Tuple2Serializer(statementSerializer, ListSerializer(catchSerializer))); TextSerializer catchSerializer = Wrapped( - (w) => Tuple4(w.guard, w.exception, w.stackTrace, w.body), - (u) => Catch(u.second, u.fourth, stackTrace: u.third, guard: u.first), - Tuple4Serializer( + (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, - Optional(variableDeclarationSerializer), - Optional(variableDeclarationSerializer), - statementSerializer)); + Bind( + Tuple2Serializer(Optional(variableDeclarationSerializer), + Optional(variableDeclarationSerializer)), + statementSerializer))); TextSerializer switchStatementSerializer = Wrapped( (w) => Tuple2(w.expression, w.cases), @@ -1417,6 +1395,11 @@ TextSerializer switchCaseSerializer = Case(SwitchCaseTagger(), { TextSerializer continueSwitchStatementSerializer = Wrapped((w) => w.target, (u) => ContinueSwitchStatement(u), ScopedUse()); +TextSerializer functionDeclarationSerializer = Wrapped( + (w) => Tuple2(w.variable, w.function), + (u) => FunctionDeclaration(u.first, u.second), + Bind(variableDeclarationSerializer, functionNodeSerializer)); + Case statementSerializer = new Case.uninitialized(const StatementTagger()); @@ -1889,6 +1872,7 @@ void initializeSerializers() { "try-catch": tryCatchSerializer, "switch": switchStatementSerializer, "continue": continueSwitchStatementSerializer, + "local-fun": functionDeclarationSerializer, }); functionNodeSerializer.registerTags({ "sync": syncFunctionNodeSerializer,