Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(69)

Unified Diff: pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart

Issue 2903243002: Add type inference logic for cascade expressions. (Closed)
Patch Set: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
index de95a4dc9864c1e7f78665e11976f27ef9eaa73d..6d7a19bc6f123b5dfea073d9da8e4d40833fe590 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
@@ -25,6 +25,7 @@ import 'package:front_end/src/fasta/type_inference/type_promotion.dart';
import 'package:front_end/src/fasta/type_inference/type_schema.dart';
import 'package:front_end/src/fasta/type_inference/type_schema_elimination.dart';
import 'package:kernel/ast.dart';
+import 'package:kernel/frontend/accessors.dart';
import 'package:kernel/type_algebra.dart';
List<DartType> getExplicitTypeArguments(Arguments arguments) {
@@ -113,6 +114,80 @@ class KernelBoolLiteral extends BoolLiteral implements KernelExpression {
}
}
+/// Concrete shadow object representing a cascade expression.
+///
+/// A cascade expression of the form `a..b()..c()` is represented as the kernel
+/// expression:
+///
+/// let v = a in
+/// let _ = v.b() in
+/// let _ = v.c() in
+/// v
+///
+/// In the documentation that follows, `v` is referred to as the "cascade
+/// variable"--this is the variable that remembers the value of the expression
+/// preceding the first `..` while the cascades are being evaluated.
+///
+/// After constructing a [KernelCascadeExpression], the caller should
+/// call [finalize] with an expression representing the expression after the
+/// `..`. If a further `..` follows that expression, the caller should call
+/// [extend] followed by [finalize] for each subsequent cascade.
+class KernelCascadeExpression extends Let implements KernelExpression {
+ /// Pointer to the last "let" expression in the cascade.
+ Let nextCascade;
+
+ /// Creates a [KernelCascadeExpression] using [variable] as the cascade
+ /// variable. Caller is responsible for ensuring that [variable]'s
+ /// initializer is the expression preceding the first `..` of the cascade
+ /// expression.
+ KernelCascadeExpression(KernelVariableDeclaration variable)
+ : super(
+ variable,
+ makeLet(new VariableDeclaration.forValue(new InvalidExpression()),
+ new VariableGet(variable))) {
+ nextCascade = body;
+ }
+
+ /// Adds a new unfinalized section to the end of the cascade. Should be
+ /// called after the previous cascade section has been finalized.
+ void extend() {
+ assert(nextCascade.variable.initializer is! InvalidExpression);
+ Let newCascade = makeLet(
+ new VariableDeclaration.forValue(new InvalidExpression()),
+ nextCascade.body);
+ nextCascade.body = newCascade;
+ newCascade.parent = nextCascade;
+ nextCascade = newCascade;
+ }
+
+ /// Finalizes the last cascade section with the given [expression].
+ void finalize(Expression expression) {
+ assert(nextCascade.variable.initializer is InvalidExpression);
+ nextCascade.variable.initializer = expression;
+ expression.parent = nextCascade.variable;
+ }
+
+ @override
+ DartType _inferExpression(
+ KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) {
+ typeNeeded = inferrer.listener.cascadeExpressionEnter(this, typeContext) ||
+ typeNeeded;
+ var lhsType = inferrer.inferExpression(
+ variable.initializer, typeContext, typeNeeded || inferrer.strongMode);
+ if (inferrer.strongMode) {
+ variable.type = lhsType;
+ }
+ Let section = body;
+ while (true) {
+ inferrer.inferExpression(section.variable.initializer, null, false);
+ if (section.body is! Let) break;
+ section = section.body;
+ }
+ inferrer.listener.cascadeExpressionExit(this, lhsType);
+ return lhsType;
+ }
+}
+
/// Concrete shadow object representing a conditional expression in kernel form.
/// Shadow object for [ConditionalExpression].
class KernelConditionalExpression extends ConditionalExpression
@@ -1230,6 +1305,12 @@ class KernelVariableDeclaration extends VariableDeclaration
isFinal: isFinal,
isConst: isConst);
+ KernelVariableDeclaration.forValue(
+ Expression initializer, this._functionNestingLevel)
+ : _implicitlyTyped = true,
+ _isLocalFunction = false,
+ super.forValue(initializer);
+
@override
void _inferStatement(KernelTypeInferrer inferrer) {
inferrer.listener.variableDeclarationEnter(this);

Powered by Google App Engine
This is Rietveld 408576698