| 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 c4dcf4da2c4373108dd20f6f8fcb23f2c2b6b579..ffe96b4795fae15b7a22e64c830215b2ab565621 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
|
| @@ -935,6 +935,56 @@ class KernelFunctionExpression extends FunctionExpression
|
| }
|
| }
|
|
|
| +/// Concrete shadow object representing an if-null expression.
|
| +///
|
| +/// An if-null expression of the form `a ?? b` is represented as the kernel
|
| +/// expression:
|
| +///
|
| +/// let v = a in v == null ? b : v
|
| +class KernelIfNullExpression extends Let implements KernelExpression {
|
| + KernelIfNullExpression(VariableDeclaration variable, Expression body)
|
| + : super(variable, body);
|
| +
|
| + @override
|
| + ConditionalExpression get body => super.body;
|
| +
|
| + /// Returns the expression to the left of `??`.
|
| + Expression get _lhs => variable.initializer;
|
| +
|
| + /// Returns the expression to the right of `??`.
|
| + Expression get _rhs => body.then;
|
| +
|
| + @override
|
| + void _collectDependencies(KernelDependencyCollector collector) {
|
| + // If-null expressions are not immediately evident expressions.
|
| + collector.recordNotImmediatelyEvident(fileOffset);
|
| + }
|
| +
|
| + @override
|
| + DartType _inferExpression(
|
| + KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) {
|
| + typeNeeded = inferrer.listener.ifNullEnter(this, typeContext) || typeNeeded;
|
| + // To infer `e0 ?? e1` in context K:
|
| + // - Infer e0 in context K to get T0
|
| + var lhsType = inferrer.inferExpression(_lhs, typeContext, true);
|
| + variable.type = lhsType;
|
| + // - Let J = T0 if K is `_` else K.
|
| + var rhsContext = typeContext ?? lhsType;
|
| + // - Infer e1 in context J to get T1
|
| + var rhsType =
|
| + inferrer.inferExpression(_rhs, rhsContext, typeContext == null);
|
| + // - Let T = greatest closure of K with respect to `?` if K is not `_`, else
|
| + // UP(t0, t1)
|
| + // - Then the inferred type is T.
|
| + var inferredType = typeContext == null
|
| + ? inferrer.typeSchemaEnvironment.getLeastUpperBound(lhsType, rhsType)
|
| + : greatestClosure(inferrer.coreTypes, typeContext);
|
| + body.staticType = inferredType;
|
| + inferrer.listener.ifNullExit(this, inferredType);
|
| + return inferredType;
|
| + }
|
| +}
|
| +
|
| /// Concrete shadow object representing an if statement in kernel form.
|
| class KernelIfStatement extends IfStatement implements KernelStatement {
|
| KernelIfStatement(Expression condition, Statement then, Statement otherwise)
|
|
|