Skip to content

Commit da87123

Browse files
Dmitry Stefantsovcommit-bot@chromium.org
Dmitry Stefantsov
authored andcommitted
[cfe] Support LabeledStatement and Break in text serialization
In addition to supporting the nodes, the notion of Binder is reworked. It doesn't store the computed local distinct name on the node itself now, as it's not always possible (which is the case of LabeledStatement), but keep it in a map. Change-Id: I04c08875cbcac3a547d62afbe5b17f023e6f1035 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/153342 Reviewed-by: Johnni Winther <[email protected]>
1 parent 1ed7581 commit da87123

5 files changed

+242
-206
lines changed

pkg/kernel/lib/text/serializer_combinators.dart

Lines changed: 79 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -17,25 +17,30 @@ class DeserializationEnvironment<T extends Node> {
1717

1818
final Map<String, T> binders = <String, T>{};
1919

20-
final Set<String> usedNames;
20+
final Map<T, String> distinctNames = new Map<T, String>.identity();
2121

22-
DeserializationEnvironment(this.parent)
23-
: usedNames = parent?.usedNames?.toSet() ?? new Set<String>();
22+
DeserializationEnvironment(this.parent);
2423

2524
T lookup(String name) => locals[name] ?? parent?.lookup(name);
2625

27-
T addBinder(String name, T node) {
28-
if (usedNames.contains(name)) {
29-
throw StateError("Name '${name}' is already declared in this scope.");
26+
T addBinder(T node, String distinctName) {
27+
if (lookupDistinctName(node) != null) {
28+
throw StateError(
29+
"Name '${distinctName}' is already declared in this scope.");
3030
}
31-
usedNames.add(name);
32-
return binders[name] = node;
31+
distinctNames[node] = distinctName;
32+
return binders[distinctName] = node;
3333
}
3434

35-
void close() {
35+
// TODO(dmitryas): Consider combining with [addBinder] into a single method.
36+
void extend() {
3637
locals.addAll(binders);
3738
binders.clear();
3839
}
40+
41+
String lookupDistinctName(T object) {
42+
return distinctNames[object] ?? parent?.lookupDistinctName(object);
43+
}
3944
}
4045

4146
class SerializationEnvironment<T extends Node> {
@@ -47,33 +52,55 @@ class SerializationEnvironment<T extends Node> {
4752

4853
int nameCount;
4954

55+
Map<T, String> distinctNames = new Map<T, String>.identity();
56+
5057
SerializationEnvironment(this.parent) : nameCount = parent?.nameCount ?? 0;
5158

5259
String lookup(T node) => locals[node] ?? parent?.lookup(node);
5360

54-
String addBinder(T node, String name) {
61+
String addBinder(T node, {String nameClue}) {
5562
final String separator = "^";
5663
final int codeOfZero = "0".codeUnitAt(0);
5764
final int codeOfNine = "9".codeUnitAt(0);
5865

59-
int prefixLength = name.length - 1;
60-
bool isOnlyDigits = true;
61-
while (prefixLength >= 0 && name[prefixLength] != separator) {
62-
int code = name.codeUnitAt(prefixLength);
63-
isOnlyDigits = isOnlyDigits && (codeOfZero <= code && code <= codeOfNine);
64-
--prefixLength;
65-
}
66-
if (prefixLength < 0 || !isOnlyDigits) {
67-
prefixLength = name.length;
66+
String prefix;
67+
if (nameClue != null) {
68+
int prefixLength = nameClue.length - 1;
69+
bool isOnlyDigits = true;
70+
while (prefixLength >= 0 && nameClue[prefixLength] != separator) {
71+
int code = nameClue.codeUnitAt(prefixLength);
72+
isOnlyDigits =
73+
isOnlyDigits && (codeOfZero <= code && code <= codeOfNine);
74+
--prefixLength;
75+
}
76+
if (prefixLength < 0 || !isOnlyDigits) {
77+
prefixLength = nameClue.length;
78+
}
79+
prefix = nameClue.substring(0, prefixLength);
80+
} else {
81+
prefix = "ID";
6882
}
69-
String prefix = name.substring(0, prefixLength);
70-
return binders[node] = "$prefix$separator${nameCount++}";
71-
}
72-
73-
void close() {
83+
String distinctName = "$prefix$separator${nameCount++}";
84+
// The following checks for an internal error, not an error caused by the user.
85+
// So, an assert is used instead of an exception.
86+
assert(
87+
lookupDistinctName(node) == null,
88+
"Can't assign distinct name '${distinctName}' "
89+
"to an object of kind '${node.runtimeType}': "
90+
"it's already known by name '${lookupDistinctName(node)}'.");
91+
distinctNames[node] = distinctName;
92+
return binders[node] = distinctName;
93+
}
94+
95+
// TODO(dmitryas): Consider combining with [addBinder] into a single method.
96+
void extend() {
7497
locals.addAll(binders);
7598
binders.clear();
7699
}
100+
101+
String lookupDistinctName(T object) {
102+
return distinctNames[object] ?? parent?.lookupDistinctName(object);
103+
}
77104
}
78105

79106
class DeserializationState {
@@ -312,7 +339,7 @@ class Tuple2Serializer<T1, T2> extends TextSerializer<Tuple2<T1, T2>> {
312339
void writeTo(
313340
StringBuffer buffer, Tuple2<T1, T2> object, SerializationState state) {
314341
first.writeTo(buffer, object.first, state);
315-
buffer.write(' ');
342+
if (!second.isEmpty) buffer.write(' ');
316343
second.writeTo(buffer, object.second, state);
317344
}
318345
}
@@ -340,9 +367,9 @@ class Tuple3Serializer<T1, T2, T3> extends TextSerializer<Tuple3<T1, T2, T3>> {
340367
void writeTo(StringBuffer buffer, Tuple3<T1, T2, T3> object,
341368
SerializationState state) {
342369
first.writeTo(buffer, object.first, state);
343-
buffer.write(' ');
370+
if (!second.isEmpty) buffer.write(' ');
344371
second.writeTo(buffer, object.second, state);
345-
buffer.write(' ');
372+
if (!third.isEmpty) buffer.write(' ');
346373
third.writeTo(buffer, object.third, state);
347374
}
348375
}
@@ -376,11 +403,11 @@ class Tuple4Serializer<T1, T2, T3, T4>
376403
void writeTo(StringBuffer buffer, Tuple4<T1, T2, T3, T4> object,
377404
SerializationState state) {
378405
first.writeTo(buffer, object.first, state);
379-
buffer.write(' ');
406+
if (!second.isEmpty) buffer.write(' ');
380407
second.writeTo(buffer, object.second, state);
381-
buffer.write(' ');
408+
if (!third.isEmpty) buffer.write(' ');
382409
third.writeTo(buffer, object.third, state);
383-
buffer.write(' ');
410+
if (!fourth.isEmpty) buffer.write(' ');
384411
fourth.writeTo(buffer, object.fourth, state);
385412
}
386413
}
@@ -451,25 +478,28 @@ class Optional<T> extends TextSerializer<T> {
451478
/// Serializes an object and uses it as a binder for the name that is retrieved
452479
/// from the object using [nameGetter] and (temporarily) modified using
453480
/// [nameSetter]. The binder is added to the enclosing environment.
454-
class Binder<T extends Node> extends TextSerializer<T> {
455-
final TextSerializer<T> contents;
456-
final String Function(T) nameGetter;
457-
final void Function(T, String) nameSetter;
481+
class Binder<T extends Node> extends TextSerializer<Tuple2<String, T>> {
482+
final Tuple2Serializer<String, T> namedContents;
458483

459-
const Binder(this.contents, this.nameGetter, this.nameSetter);
484+
Binder(TextSerializer<T> contents)
485+
: namedContents = new Tuple2Serializer(const DartString(), contents);
460486

461-
T readFrom(Iterator<Object> stream, DeserializationState state) {
462-
T object = contents.readFrom(stream, state);
463-
state.environment.addBinder(nameGetter(object), object);
464-
return object;
487+
Tuple2<String, T> readFrom(
488+
Iterator<Object> stream, DeserializationState state) {
489+
Tuple2<String, T> namedObject = namedContents.readFrom(stream, state);
490+
String name = namedObject.first;
491+
T object = namedObject.second;
492+
state.environment.addBinder(object, name);
493+
return new Tuple2(name, object);
465494
}
466495

467-
void writeTo(StringBuffer buffer, T object, SerializationState state) {
468-
String oldName = nameGetter(object);
469-
String newName = state.environment.addBinder(object, oldName);
470-
nameSetter(object, newName);
471-
contents.writeTo(buffer, object, state);
472-
nameSetter(object, oldName);
496+
void writeTo(StringBuffer buffer, Tuple2<String, T> namedObject,
497+
SerializationState state) {
498+
String nameClue = namedObject.first;
499+
T object = namedObject.second;
500+
String distinctName =
501+
state.environment.addBinder(object, nameClue: nameClue);
502+
namedContents.writeTo(buffer, new Tuple2(distinctName, object), state);
473503
}
474504
}
475505

@@ -488,7 +518,7 @@ class Bind<P, T> extends TextSerializer<Tuple2<P, T>> {
488518
var bindingState = new DeserializationState(
489519
new DeserializationEnvironment(state.environment), state.nameRoot);
490520
P first = pattern.readFrom(stream, bindingState);
491-
bindingState.environment.close();
521+
bindingState.environment.extend();
492522
T second = term.readFrom(stream, bindingState);
493523
return new Tuple2(first, second);
494524
}
@@ -498,7 +528,7 @@ class Bind<P, T> extends TextSerializer<Tuple2<P, T>> {
498528
var bindingState =
499529
new SerializationState(new SerializationEnvironment(state.environment));
500530
pattern.writeTo(buffer, tuple.first, bindingState);
501-
bindingState.environment.close();
531+
bindingState.environment.extend();
502532
buffer.write(' ');
503533
term.writeTo(buffer, tuple.second, bindingState);
504534
}
@@ -520,7 +550,7 @@ class Rebind<P, T> extends TextSerializer<Tuple2<P, T>> {
520550
var closedState = new DeserializationState(
521551
new DeserializationEnvironment(state.environment)
522552
..binders.addAll(state.environment.binders)
523-
..close(),
553+
..extend(),
524554
state.nameRoot);
525555
T second = pattern2.readFrom(stream, closedState);
526556
state.environment.binders.addAll(closedState.environment.binders);
@@ -533,7 +563,7 @@ class Rebind<P, T> extends TextSerializer<Tuple2<P, T>> {
533563
var closedState =
534564
new SerializationState(new SerializationEnvironment(state.environment)
535565
..binders.addAll(state.environment.binders)
536-
..close());
566+
..extend());
537567
buffer.write(' ');
538568
pattern2.writeTo(buffer, tuple.second, closedState);
539569
state.environment.binders.addAll(closedState.environment.binders);

pkg/kernel/lib/text/text_serialization_verifier.dart

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -344,12 +344,10 @@ class VerificationState {
344344
!isStatementNotSupported(node);
345345

346346
static bool isStatementNotSupported(Statement node) =>
347-
node is BreakStatement ||
348347
node is VariableDeclaration &&
349348
(node.parent is! Block || node.name == null) ||
350349
node is SwitchStatement ||
351350
node is TryFinally ||
352-
node is LabeledStatement ||
353351
node is TryCatch ||
354352
node is FunctionDeclaration ||
355353
node is ContinueSwitchStatement;

0 commit comments

Comments
 (0)