Skip to content

Commit 145d458

Browse files
Dmitry Stefantsovcommit-bot@chromium.org
Dmitry Stefantsov
authored andcommitted
[cfe] Add support for Fields to round-trip text serialization
The flags on the fields are serialized as lists of flag names, allowing for any combination of the flags in any order. Similar technique is used in this CL to serialize the flags on Procedures and VariableDeclarations. This is in the contrast with the previous approach for those nodes, when the flags were the part of the serialized name of the node (such as "static-method" for static Procedures or "final" for final VariableDeclarations). Change-Id: I02eb5ac92f6273542f08f269aee8e6519d3085e9 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/153766 Commit-Queue: Dmitry Stefantsov <[email protected]> Reviewed-by: Johnni Winther <[email protected]>
1 parent f75a982 commit 145d458

File tree

4 files changed

+172
-125
lines changed

4 files changed

+172
-125
lines changed

pkg/kernel/lib/text/text_serialization_verifier.dart

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,6 @@ class VerificationState {
333333
node is Component ||
334334
node is Constructor ||
335335
node is Extension ||
336-
node is Field ||
337336
node is FieldInitializer ||
338337
node is InvalidInitializer ||
339338
node is Library ||
@@ -474,8 +473,8 @@ class TextSerializationVerifier extends RecursiveVisitor<void> {
474473
makeRoundTrip<Arguments>(node, argumentsSerializer);
475474
} else if (node is FunctionNode) {
476475
makeRoundTrip<FunctionNode>(node, functionNodeSerializer);
477-
} else if (node is Procedure) {
478-
makeRoundTrip<Procedure>(node, procedureSerializer);
476+
} else if (node is Member) {
477+
makeRoundTrip<Member>(node, memberSerializer);
479478
} else if (node is TypeParameter) {
480479
makeRoundTrip<TypeParameter>(node, typeParameterSerializer);
481480
} else if (node is NamedType) {

pkg/kernel/lib/text/text_serializer.dart

Lines changed: 147 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -799,76 +799,53 @@ Arguments wrapArguments(
799799
return new Arguments(tuple.second, types: tuple.first, named: tuple.third);
800800
}
801801

802-
class VariableDeclarationTagger implements Tagger<VariableDeclaration> {
803-
const VariableDeclarationTagger();
804-
805-
String tag(VariableDeclaration decl) {
806-
String prefix = "";
807-
if (decl.isCovariant) {
808-
prefix = "${prefix}covariant-";
809-
if (decl.isFieldFormal) {
810-
// Field formals can only be used in constructors,
811-
// and "covariant" keyword doesn't make sense for them.
812-
throw StateError("Encountered covariant field formal.");
813-
}
814-
}
815-
if (decl.isFieldFormal) {
816-
prefix = "${prefix}fieldformal-";
817-
}
818-
819-
if (decl.isConst) {
820-
// It's not clear what invariants we assume about const/final. For now
821-
// throw if we have both.
822-
if (decl.isFinal) {
823-
throw UnimplementedError(
824-
"Encountered a variable that is both const and final.");
825-
}
826-
return "${prefix}const";
827-
}
828-
if (decl.isFinal) {
829-
return "${prefix}final";
830-
}
831-
return "${prefix}var";
802+
const Map<int, String> variableDeclarationFlagToName = const {
803+
VariableDeclaration.FlagFinal: "final",
804+
VariableDeclaration.FlagConst: "const",
805+
VariableDeclaration.FlagFieldFormal: "field-formal",
806+
VariableDeclaration.FlagCovariant: "covariant",
807+
VariableDeclaration.FlagInScope: "in-scope",
808+
VariableDeclaration.FlagGenericCovariantImpl: "generic-covariant-impl",
809+
VariableDeclaration.FlagLate: "late",
810+
VariableDeclaration.FlagRequired: "required",
811+
};
812+
813+
class VariableDeclarationFlagTagger implements Tagger<IntLiteral> {
814+
String tag(IntLiteral wrappedFlag) {
815+
int flag = wrappedFlag.value;
816+
return variableDeclarationFlagToName[flag] ??
817+
(throw StateError("Unknown VariableDeclaration flag value: ${flag}."));
832818
}
833819
}
834820

835-
TextSerializer<VariableDeclaration> makeVariableDeclarationSerializer(
836-
{bool isFinal = false,
837-
bool isConst = false,
838-
bool isCovariant = false,
839-
bool isFieldFormal = false}) =>
840-
new Wrapped(
841-
(w) => Tuple3(w.type, w.initializer, w.annotations),
842-
(u) => u.third.fold(
843-
VariableDeclaration(null,
844-
type: u.first,
845-
initializer: u.second,
846-
isFinal: isFinal,
847-
isConst: isConst,
848-
isCovariant: isCovariant,
849-
isFieldFormal: isFieldFormal),
850-
(v, a) => v..addAnnotation(a)),
851-
Tuple3Serializer(dartTypeSerializer, new Optional(expressionSerializer),
852-
new ListSerializer(expressionSerializer)));
821+
TextSerializer<int> variableDeclarationFlagsSerializer = Wrapped(
822+
(w) => List.generate(30, (i) => IntLiteral(w & (1 << i)))
823+
.where((f) => f.value != 0)
824+
.toList(),
825+
(u) => u.fold(0, (fs, f) => fs |= f.value),
826+
ListSerializer(Case(
827+
VariableDeclarationFlagTagger(),
828+
Map.fromIterable(variableDeclarationFlagToName.entries,
829+
key: (e) => e.value,
830+
value: (e) =>
831+
Wrapped((_) => null, (_) => IntLiteral(e.key), Nothing())))));
853832

854833
TextSerializer<VariableDeclaration> variableDeclarationSerializer = Wrapped(
855834
(v) => Tuple2(v.name, v),
856835
(t) => t.second..name = t.first,
857-
Binder(Case(VariableDeclarationTagger(), {
858-
"var": makeVariableDeclarationSerializer(),
859-
"final": makeVariableDeclarationSerializer(isFinal: true),
860-
"const": makeVariableDeclarationSerializer(isConst: true),
861-
"covariant-var": makeVariableDeclarationSerializer(isCovariant: true),
862-
"covariant-final":
863-
makeVariableDeclarationSerializer(isCovariant: true, isFinal: true),
864-
"covariant-const":
865-
makeVariableDeclarationSerializer(isCovariant: true, isConst: true),
866-
"fieldformal-var": makeVariableDeclarationSerializer(isFieldFormal: true),
867-
"fieldformal-final":
868-
makeVariableDeclarationSerializer(isFieldFormal: true, isFinal: true),
869-
"fieldformal-const":
870-
makeVariableDeclarationSerializer(isFieldFormal: true, isConst: true),
871-
})));
836+
Binder<VariableDeclaration>(
837+
new Wrapped(
838+
(w) => Tuple4(w.flags, w.type, w.initializer, w.annotations),
839+
(u) => u.fourth.fold(
840+
VariableDeclaration(null,
841+
flags: u.first, type: u.second, initializer: u.third),
842+
(v, a) => v..addAnnotation(a)),
843+
Tuple4Serializer(
844+
variableDeclarationFlagsSerializer,
845+
dartTypeSerializer,
846+
new Optional(expressionSerializer),
847+
new ListSerializer(expressionSerializer))),
848+
));
872849

873850
TextSerializer<TypeParameter> typeParameterSerializer = Wrapped(
874851
(p) => Tuple2(p.name, p),
@@ -1593,36 +1570,112 @@ FunctionNode wrapSyncYieldingFunctionNode(
15931570
Case<FunctionNode> functionNodeSerializer =
15941571
new Case.uninitialized(const FunctionNodeTagger());
15951572

1596-
class ProcedureTagger implements Tagger<Procedure> {
1597-
const ProcedureTagger();
1598-
1599-
String tag(Procedure node) {
1600-
String prefix = node.isStatic ? "static-" : "";
1601-
switch (node.kind) {
1602-
case ProcedureKind.Method:
1603-
return "${prefix}method";
1604-
default:
1605-
throw new UnsupportedError("${node.kind}");
1606-
}
1573+
const Map<int, String> procedureFlagToName = const {
1574+
Procedure.FlagStatic: "static",
1575+
Procedure.FlagAbstract: "abstract",
1576+
Procedure.FlagExternal: "external",
1577+
Procedure.FlagConst: "const",
1578+
Procedure.FlagForwardingStub: "forwarding-stub",
1579+
Procedure.FlagForwardingSemiStub: "forwarding-semi-stub",
1580+
Procedure.FlagRedirectingFactoryConstructor:
1581+
"redirecting-factory-constructor",
1582+
Procedure.FlagNoSuchMethodForwarder: "no-such-method-forwarder",
1583+
Procedure.FlagExtensionMember: "extension-member",
1584+
Procedure.FlagMemberSignature: "member-signature",
1585+
Procedure.FlagNonNullableByDefault: "non-nullable-by-default",
1586+
};
1587+
1588+
class ProcedureFlagTagger implements Tagger<IntLiteral> {
1589+
const ProcedureFlagTagger();
1590+
1591+
String tag(IntLiteral wrappedFlag) {
1592+
int flag = wrappedFlag.value;
1593+
return procedureFlagToName[flag] ??
1594+
(throw StateError("Unknown Procedure flag value: ${flag}."));
16071595
}
16081596
}
16091597

1610-
TextSerializer<Procedure> staticMethodSerializer = new Wrapped(
1611-
unwrapStaticMethod,
1612-
wrapStaticMethod,
1613-
new Tuple2Serializer(nameSerializer, functionNodeSerializer));
1614-
1615-
Tuple2<Name, FunctionNode> unwrapStaticMethod(Procedure procedure) {
1616-
return new Tuple2(procedure.name, procedure.function);
1598+
TextSerializer<int> procedureFlagsSerializer = Wrapped(
1599+
(w) => List.generate(30, (i) => IntLiteral(w & (1 << i)))
1600+
.where((f) => f.value != 0)
1601+
.toList(),
1602+
(u) => u.fold(0, (fs, f) => fs |= f.value),
1603+
ListSerializer(Case(
1604+
ProcedureFlagTagger(),
1605+
Map.fromIterable(procedureFlagToName.entries,
1606+
key: (e) => e.value,
1607+
value: (e) =>
1608+
Wrapped((_) => null, (_) => IntLiteral(e.key), Nothing())))));
1609+
1610+
const Map<int, String> fieldFlagToName = const {
1611+
Field.FlagFinal: "final",
1612+
Field.FlagConst: "const",
1613+
Field.FlagStatic: "static",
1614+
Field.FlagHasImplicitGetter: "has-implicit-getter",
1615+
Field.FlagHasImplicitSetter: "has-implicit-setter",
1616+
Field.FlagCovariant: "covariant",
1617+
Field.FlagGenericCovariantImpl: "generic-covariant-impl",
1618+
Field.FlagLate: "late",
1619+
Field.FlagExtensionMember: "extension-member",
1620+
Field.FlagNonNullableByDefault: "non-nullable-by-default",
1621+
Field.FlagInternalImplementation: "internal-implementation",
1622+
};
1623+
1624+
class FieldFlagTagger implements Tagger<IntLiteral> {
1625+
const FieldFlagTagger();
1626+
1627+
String tag(IntLiteral wrappedFlag) {
1628+
int flag = wrappedFlag.value;
1629+
return fieldFlagToName[flag] ??
1630+
(throw StateError("Unknown Field flag value: ${flag}."));
1631+
}
16171632
}
16181633

1619-
Procedure wrapStaticMethod(Tuple2<Name, FunctionNode> tuple) {
1620-
return new Procedure(tuple.first, ProcedureKind.Method, tuple.second,
1621-
isStatic: true);
1634+
TextSerializer<int> fieldFlagsSerializer = Wrapped(
1635+
(w) => List.generate(30, (i) => IntLiteral(w & (1 << i)))
1636+
.where((f) => f.value != 0)
1637+
.toList(),
1638+
(u) => u.fold(0, (fs, f) => fs |= f.value),
1639+
ListSerializer(Case(
1640+
FieldFlagTagger(),
1641+
Map.fromIterable(fieldFlagToName.entries,
1642+
key: (e) => e.value,
1643+
value: (e) =>
1644+
Wrapped((_) => null, (_) => IntLiteral(e.key), Nothing())))));
1645+
1646+
class MemberTagger implements Tagger<Member> {
1647+
const MemberTagger();
1648+
1649+
String tag(Member node) {
1650+
if (node is Field) {
1651+
return "field";
1652+
} else if (node is Procedure) {
1653+
switch (node.kind) {
1654+
case ProcedureKind.Method:
1655+
return "method";
1656+
default:
1657+
throw new UnsupportedError("${node.kind}");
1658+
}
1659+
} else {
1660+
throw UnimplementedError("MemberTagger.tag(${node.runtimeType})");
1661+
}
1662+
}
16221663
}
16231664

1624-
Case<Procedure> procedureSerializer =
1625-
new Case.uninitialized(const ProcedureTagger());
1665+
TextSerializer<Field> fieldSerializer = Wrapped(
1666+
(w) => Tuple4(w.name, w.flags, w.type, w.initializer),
1667+
(u) =>
1668+
Field(u.first, type: u.third, initializer: u.fourth)..flags = u.second,
1669+
Tuple4Serializer(nameSerializer, fieldFlagsSerializer, dartTypeSerializer,
1670+
Optional(expressionSerializer)));
1671+
1672+
TextSerializer<Procedure> methodSerializer = Wrapped(
1673+
(w) => Tuple3(w.name, w.flags, w.function),
1674+
(u) => Procedure(u.first, ProcedureKind.Method, u.third)..flags = u.second,
1675+
Tuple3Serializer(
1676+
nameSerializer, procedureFlagsSerializer, functionNodeSerializer));
1677+
1678+
Case<Member> memberSerializer = new Case.uninitialized(const MemberTagger());
16261679

16271680
class LibraryTagger implements Tagger<Library> {
16281681
const LibraryTagger();
@@ -1633,20 +1686,14 @@ class LibraryTagger implements Tagger<Library> {
16331686
}
16341687

16351688
TextSerializer<Library> libraryContentsSerializer = new Wrapped(
1636-
unwrapLibraryNode,
1637-
wrapLibraryNode,
1638-
new Tuple2Serializer(
1639-
const UriSerializer(), new ListSerializer(procedureSerializer)),
1689+
(w) => Tuple2(w.importUri, [...w.fields, ...w.procedures]),
1690+
(u) => Library(u.first,
1691+
fields: u.second.where((m) => m is Field).cast<Field>().toList(),
1692+
procedures:
1693+
u.second.where((m) => m is Procedure).cast<Procedure>().toList()),
1694+
new Tuple2Serializer(const UriSerializer(), ListSerializer(memberSerializer)),
16401695
);
16411696

1642-
Tuple2<Uri, List<Procedure>> unwrapLibraryNode(Library library) {
1643-
return new Tuple2(library.importUri, library.procedures);
1644-
}
1645-
1646-
Library wrapLibraryNode(Tuple2<Uri, List<Procedure>> tuple) {
1647-
return new Library(tuple.first, procedures: tuple.second);
1648-
}
1649-
16501697
Case<Library> librarySerializer = new Case.uninitialized(const LibraryTagger());
16511698

16521699
class ShowHideTagger implements Tagger<Combinator> {
@@ -1881,7 +1928,8 @@ void initializeSerializers() {
18811928
"async-star": asyncStarFunctionNodeSerializer,
18821929
"sync-yielding": syncYieldingStarFunctionNodeSerializer,
18831930
});
1884-
procedureSerializer.registerTags({"static-method": staticMethodSerializer});
1931+
memberSerializer
1932+
.registerTags({"field": fieldSerializer, "method": methodSerializer});
18851933
librarySerializer.registerTags({
18861934
"legacy": libraryContentsSerializer,
18871935
"null-safe": libraryContentsSerializer,

0 commit comments

Comments
 (0)