[Kernel] Add BlockExpression to the Kernel language
This is not yet used or tested.
Change-Id: Id050802926ad6452df3c39ace12ea5dd56d4faaa
Reviewed-on: https://dart-review.googlesource.com/c/87970
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Aske Simon Christensen <askesc@google.com>
Commit-Queue: Kevin Millikin <kmillikin@google.com>
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index a56cbc2..7df0400 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -5028,6 +5028,11 @@
}
@override
+ visitBlockExpression(BlockExpression node) {
+ throw UnimplementedError('ProgramCompiler.visitBlockExpression');
+ }
+
+ @override
visitInstantiation(Instantiation node) {
return runtimeCall('gbind(#, #)', [
_visitExpression(node.expression),
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index 8ea99dc..5071104 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -137,7 +137,7 @@
type ComponentFile {
UInt32 magic = 0x90ABCDEF;
- UInt32 formatVersion = 18;
+ UInt32 formatVersion = 19;
List<String> problemsAsJson; // Described in problems.md.
Library[] libraries;
UriSource sourceMap;
@@ -845,6 +845,12 @@
Expression body;
}
+type BlockExpression extends Expression {
+ Byte tag = 82;
+ List<Statement> body;
+ Expression value;
+}
+
type Instantiation extends Expression {
Byte tag = 54;
Expression expression;
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 2da3cd5..a5132fc 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -3644,6 +3644,39 @@
}
}
+class BlockExpression extends Expression {
+ final List<Statement> statements;
+ Expression value;
+
+ BlockExpression(this.statements, this.value) {
+ // Ensure statements is mutable.
+ assert((statements
+ ..add(null)
+ ..removeLast()) !=
+ null);
+ setParents(statements, this);
+ value?.parent = this;
+ }
+
+ DartType getStaticType(TypeEnvironment types) => value.getStaticType(types);
+
+ accept(ExpressionVisitor v) => v.visitBlockExpression(this);
+ accept1(ExpressionVisitor1 v, arg) => v.visitBlockExpression(this, arg);
+
+ visitChildren(Visitor v) {
+ visitList(statements, v);
+ value?.accept(v);
+ }
+
+ transformChildren(Transformer v) {
+ transformList(statements, v, this);
+ if (value != null) {
+ value = value.accept(v);
+ value?.parent = this;
+ }
+ }
+}
+
/// Attempt to load the library referred to by a deferred import.
///
/// This instruction is concerned with:
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index cc11d87..98c5d46 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -1593,6 +1593,12 @@
var body = readExpression();
variableStack.length = stackHeight;
return new Let(variable, body);
+ case Tag.BlockExpression:
+ int stackHeight = variableStack.length;
+ var statements = readStatementList();
+ var value = readExpression();
+ variableStack.length = stackHeight;
+ return new BlockExpression(statements, value);
case Tag.Instantiation:
var expression = readExpression();
var typeArguments = readDartTypeList();
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index 1b945ba..bce361f 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -1614,6 +1614,16 @@
}
@override
+ void visitBlockExpression(BlockExpression node) {
+ writeByte(Tag.BlockExpression);
+ _variableIndexer ??= new VariableIndexer();
+ _variableIndexer.pushScope();
+ writeNodeList(node.statements);
+ writeNode(node.value);
+ _variableIndexer.popScope();
+ }
+
+ @override
void visitInstantiation(Instantiation node) {
writeByte(Tag.Instantiation);
writeNode(node.expression);
diff --git a/pkg/kernel/lib/binary/tag.dart b/pkg/kernel/lib/binary/tag.dart
index 280454f..b4bf895 100644
--- a/pkg/kernel/lib/binary/tag.dart
+++ b/pkg/kernel/lib/binary/tag.dart
@@ -67,6 +67,7 @@
static const int AwaitExpression = 51;
static const int FunctionExpression = 52;
static const int Let = 53;
+ static const int BlockExpression = 82;
static const int Instantiation = 54;
static const int PositiveIntLiteral = 55;
static const int NegativeIntLiteral = 56;
@@ -98,6 +99,7 @@
static const int FunctionDeclaration = 79;
static const int AsyncForInStatement = 80;
static const int AssertBlock = 81;
+ // 82 is occupied by [BlockExpression] (expression).
// Types
static const int TypedefType = 87;
@@ -137,7 +139,7 @@
/// Internal version of kernel binary format.
/// Bump it when making incompatible changes in kernel binaries.
/// Keep in sync with runtime/vm/kernel_binary.h, pkg/kernel/binary.md.
- static const int BinaryFormatVersion = 18;
+ static const int BinaryFormatVersion = 19;
}
abstract class ConstantTag {
diff --git a/pkg/kernel/lib/clone.dart b/pkg/kernel/lib/clone.dart
index 17ade68..05fd20f 100644
--- a/pkg/kernel/lib/clone.dart
+++ b/pkg/kernel/lib/clone.dart
@@ -277,6 +277,11 @@
return new Let(newVariable, clone(node.body));
}
+ visitBlockExpression(BlockExpression node) {
+ return new BlockExpression(
+ node.statements.map(clone).toList(), clone(node.value));
+ }
+
visitExpressionStatement(ExpressionStatement node) {
return new ExpressionStatement(clone(node.expression));
}
diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart
index dc0a65e..c110f74 100644
--- a/pkg/kernel/lib/text/ast_to_text.dart
+++ b/pkg/kernel/lib/text/ast_to_text.dart
@@ -1392,6 +1392,21 @@
writeExpression(node.body);
}
+ visitBlockExpression(BlockExpression node) {
+ writeSpaced('block');
+ if (node.statements.isEmpty) {
+ writeSymbol('{');
+ } else {
+ endLine('{');
+ }
+ ++indentation;
+ node.statements.forEach(writeNode);
+ --indentation;
+ writeIndentation();
+ writeSymbol('} =>');
+ writeExpression(node.value);
+ }
+
visitInstantiation(Instantiation node) {
writeExpression(node.expression);
writeSymbol('<');
diff --git a/pkg/kernel/lib/text/text_serialization_verifier.dart b/pkg/kernel/lib/text/text_serialization_verifier.dart
index e666451..02ce55f 100644
--- a/pkg/kernel/lib/text/text_serialization_verifier.dart
+++ b/pkg/kernel/lib/text/text_serialization_verifier.dart
@@ -756,6 +756,12 @@
}
@override
+ void visitBlockExpression(BlockExpression node) {
+ storeLastSeenUriAndOffset(node);
+ makeExpressionRoundTrip(node);
+ }
+
+ @override
void visitNullLiteral(NullLiteral node) {
storeLastSeenUriAndOffset(node);
makeExpressionRoundTrip(node);
diff --git a/pkg/kernel/lib/type_checker.dart b/pkg/kernel/lib/type_checker.dart
index 11503d0..d41de601 100644
--- a/pkg/kernel/lib/type_checker.dart
+++ b/pkg/kernel/lib/type_checker.dart
@@ -489,6 +489,12 @@
}
@override
+ DartType visitBlockExpression(BlockExpression node) {
+ node.statements.forEach(visitStatement);
+ return visitExpression(node.value);
+ }
+
+ @override
DartType visitInstantiation(Instantiation node) {
DartType type = visitExpression(node.expression);
if (type is! FunctionType) {
diff --git a/pkg/kernel/lib/verifier.dart b/pkg/kernel/lib/verifier.dart
index 85a8177..fc09f57 100644
--- a/pkg/kernel/lib/verifier.dart
+++ b/pkg/kernel/lib/verifier.dart
@@ -338,6 +338,10 @@
visitWithLocalScope(node);
}
+ visitBlockExpression(BlockExpression node) {
+ visitWithLocalScope(node);
+ }
+
visitCatch(Catch node) {
bool savedInCatchBlock = inCatchBlock;
inCatchBlock = true;
diff --git a/pkg/kernel/lib/visitor.dart b/pkg/kernel/lib/visitor.dart
index a83374b..4d2b2bb 100644
--- a/pkg/kernel/lib/visitor.dart
+++ b/pkg/kernel/lib/visitor.dart
@@ -57,6 +57,7 @@
R visitBoolLiteral(BoolLiteral node) => defaultBasicLiteral(node);
R visitNullLiteral(NullLiteral node) => defaultBasicLiteral(node);
R visitLet(Let node) => defaultExpression(node);
+ R visitBlockExpression(BlockExpression node) => defaultExpression(node);
R visitInstantiation(Instantiation node) => defaultExpression(node);
R visitLoadLibrary(LoadLibrary node) => defaultExpression(node);
R visitCheckLibraryIsLoaded(CheckLibraryIsLoaded node) =>
@@ -179,6 +180,7 @@
R visitBoolLiteral(BoolLiteral node) => defaultBasicLiteral(node);
R visitNullLiteral(NullLiteral node) => defaultBasicLiteral(node);
R visitLet(Let node) => defaultExpression(node);
+ R visitBlockExpression(BlockExpression node) => defaultExpression(node);
R visitInstantiation(Instantiation node) => defaultExpression(node);
R visitLoadLibrary(LoadLibrary node) => defaultExpression(node);
R visitCheckLibraryIsLoaded(CheckLibraryIsLoaded node) =>
@@ -516,6 +518,8 @@
R visitBoolLiteral(BoolLiteral node, T arg) => defaultBasicLiteral(node, arg);
R visitNullLiteral(NullLiteral node, T arg) => defaultBasicLiteral(node, arg);
R visitLet(Let node, T arg) => defaultExpression(node, arg);
+ R visitBlockExpression(BlockExpression node, T arg) =>
+ defaultExpression(node, arg);
R visitInstantiation(Instantiation node, T arg) =>
defaultExpression(node, arg);
R visitLoadLibrary(LoadLibrary node, T arg) => defaultExpression(node, arg);
diff --git a/runtime/vm/compiler/frontend/constant_evaluator.cc b/runtime/vm/compiler/frontend/constant_evaluator.cc
index 9c9b8ec..a16e229 100644
--- a/runtime/vm/compiler/frontend/constant_evaluator.cc
+++ b/runtime/vm/compiler/frontend/constant_evaluator.cc
@@ -117,6 +117,10 @@
case kLet:
EvaluateLet();
break;
+ case kBlockExpression: {
+ UNIMPLEMENTED();
+ break;
+ }
case kInstantiation:
EvaluatePartialTearoffInstantiation();
break;
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 10659cb..948a0d7 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -2126,6 +2126,10 @@
return BuildFunctionExpression();
case kLet:
return BuildLet(position);
+ case kBlockExpression: {
+ UNIMPLEMENTED();
+ break;
+ }
case kBigIntLiteral:
return BuildBigIntLiteral(position);
case kStringLiteral:
diff --git a/runtime/vm/compiler/frontend/kernel_fingerprints.cc b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
index 03a4e59..58675d6 100644
--- a/runtime/vm/compiler/frontend/kernel_fingerprints.cc
+++ b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
@@ -505,6 +505,10 @@
CalculateVariableDeclarationFingerprint(); // read variable declaration.
CalculateExpressionFingerprint(); // read expression.
return;
+ case kBlockExpression: {
+ UNIMPLEMENTED();
+ return;
+ }
case kInstantiation:
CalculateExpressionFingerprint(); // read expression.
CalculateListOfDartTypesFingerprint(); // read type arguments.
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index 62f2c00..90ff779 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -2255,6 +2255,10 @@
SkipVariableDeclaration(); // read variable declaration.
SkipExpression(); // read expression.
return;
+ case kBlockExpression: {
+ UNIMPLEMENTED();
+ return;
+ }
case kInstantiation:
SkipExpression(); // read expression.
SkipListOfDartTypes(); // read type arguments.
diff --git a/runtime/vm/compiler/frontend/scope_builder.cc b/runtime/vm/compiler/frontend/scope_builder.cc
index d585002..71c2e61 100644
--- a/runtime/vm/compiler/frontend/scope_builder.cc
+++ b/runtime/vm/compiler/frontend/scope_builder.cc
@@ -832,6 +832,10 @@
ExitScope(helper_.reader_.min_position(), helper_.reader_.max_position());
return;
}
+ case kBlockExpression: {
+ UNIMPLEMENTED();
+ return;
+ }
case kBigIntLiteral:
helper_.SkipStringReference(); // read string reference.
return;
diff --git a/runtime/vm/kernel_binary.cc b/runtime/vm/kernel_binary.cc
index 2dd239e..0824578 100644
--- a/runtime/vm/kernel_binary.cc
+++ b/runtime/vm/kernel_binary.cc
@@ -68,7 +68,8 @@
}
uint32_t formatVersion = reader->ReadUInt32();
- if (formatVersion != kBinaryFormatVersion) {
+ if ((formatVersion < kMinSupportedKernelFormatVersion) ||
+ (formatVersion > kMaxSupportedKernelFormatVersion)) {
if (error != nullptr) {
*error = kKernelInvalidBinaryFormatVersion;
}
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index 85ed239..0cc7f0e 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -17,7 +17,10 @@
// package:kernel/binary.md.
static const uint32_t kMagicProgramFile = 0x90ABCDEFu;
-static const uint32_t kBinaryFormatVersion = 18;
+
+// Both version numbers are inclusive.
+static const uint32_t kMinSupportedKernelFormatVersion = 18;
+static const uint32_t kMaxSupportedKernelFormatVersion = 19;
// Keep in sync with package:kernel/lib/binary/tag.dart
#define KERNEL_TAG_LIST(V) \
@@ -77,6 +80,7 @@
V(AwaitExpression, 51) \
V(FunctionExpression, 52) \
V(Let, 53) \
+ V(BlockExpression, 82) \
V(Instantiation, 54) \
V(PositiveIntLiteral, 55) \
V(NegativeIntLiteral, 56) \