Skip to content

Commit

Permalink
Add type inference for while and do loops.
Browse files Browse the repository at this point in the history
Analyzer does not type infer these constructs correctly (it uses an
empty context for the loop condition, instead of bool), so the tests
are in inference_new.

R=scheglov@google.com

Review-Url: https://codereview.chromium.org/2954253002 .
  • Loading branch information
stereotype441 committed Jun 26, 2017
1 parent 7553b2e commit 213c208
Show file tree
Hide file tree
Showing 13 changed files with 149 additions and 3 deletions.
4 changes: 2 additions & 2 deletions pkg/front_end/lib/src/fasta/kernel/body_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2493,7 +2493,7 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
body = new KernelLabeledStatement(body);
continueTarget.resolveContinues(body);
}
Statement result = new DoStatement(body, condition);
Statement result = new KernelDoStatement(body, condition);
if (breakTarget.hasUsers) {
result = new KernelLabeledStatement(result);
breakTarget.resolveBreaks(result);
Expand Down Expand Up @@ -2639,7 +2639,7 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
body = new KernelLabeledStatement(body);
continueTarget.resolveContinues(body);
}
Statement result = new WhileStatement(condition, body);
Statement result = new KernelWhileStatement(condition, body);
if (breakTarget.hasUsers) {
result = new KernelLabeledStatement(result);
breakTarget.resolveBreaks(result);
Expand Down
30 changes: 30 additions & 0 deletions pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,21 @@ class KernelDirectPropertyGet extends DirectPropertyGet
}
}

/// Concrete shadow object representing a do loop in kernel form.
class KernelDoStatement extends DoStatement implements KernelStatement {
KernelDoStatement(Statement body, Expression condition)
: super(body, condition);

@override
void _inferStatement(KernelTypeInferrer inferrer) {
inferrer.listener.doStatementEnter(this);
inferrer.inferStatement(body);
inferrer.inferExpression(
condition, inferrer.coreTypes.boolClass.rawType, false);
inferrer.listener.doStatementExit(this);
}
}

/// Concrete shadow object representing a double literal in kernel form.
class KernelDoubleLiteral extends DoubleLiteral implements KernelExpression {
KernelDoubleLiteral(double value) : super(value);
Expand Down Expand Up @@ -2236,6 +2251,21 @@ class KernelVariableGet extends VariableGet implements KernelExpression {
}
}

/// Concrete shadow object representing a while loop in kernel form.
class KernelWhileStatement extends WhileStatement implements KernelStatement {
KernelWhileStatement(Expression condition, Statement body)
: super(condition, body);

@override
void _inferStatement(KernelTypeInferrer inferrer) {
inferrer.listener.whileStatementEnter(this);
inferrer.inferExpression(
condition, inferrer.coreTypes.boolClass.rawType, false);
inferrer.inferStatement(body);
inferrer.listener.whileStatementExit(this);
}
}

/// Concrete shadow object representing a yield statement in kernel form.
class KernelYieldStatement extends YieldStatement implements KernelStatement {
KernelYieldStatement(Expression expression, {bool isYieldStar: false})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,12 @@ class TypeInferenceListener
InvocationExpression expression, DartType inferredType) =>
debugExpressionExit("constructorInvocation", expression, inferredType);

void doStatementEnter(DoStatement statement) =>
debugStatementEnter("doStatement", statement);

void doStatementExit(DoStatement statement) =>
debugStatementExit("doStatement", statement);

bool doubleLiteralEnter(DoubleLiteral expression, DartType typeContext) =>
debugExpressionEnter("doubleLiteral", expression, typeContext);

Expand Down Expand Up @@ -370,6 +376,12 @@ class TypeInferenceListener
void variableSetExit(VariableSet expression, DartType inferredType) =>
debugExpressionExit("variableSet", expression, inferredType);

void whileStatementEnter(WhileStatement statement) =>
debugStatementEnter("whileStatement", statement);

void whileStatementExit(WhileStatement statement) =>
debugStatementExit("whileStatement", statement);

void yieldStatementEnter(YieldStatement statement) =>
debugStatementEnter('yieldStatement', statement);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class ImplicitScopeTest extends core::Object {
dynamic a = "bar";
dynamic b = "baz";
}
while ("black".==("white"))
while ("black".{core::String::==}("white"))
exp::Expect::equals("foo", a);
exp::Expect::equals(null, b);
}
Expand Down
16 changes: 16 additions & 0 deletions pkg/front_end/testcases/inference_new/do_loop.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

/*@testedFeatures=inference*/
library test;

T f<T>() => null;

void test() {
do {
var /*@type=int*/ x = 0;
} while (/*@typeArgs=bool*/ f());
}

main() {}
13 changes: 13 additions & 0 deletions pkg/front_end/testcases/inference_new/do_loop.dart.direct.expect
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
library test;
import self as self;
import "dart:core" as core;

static method f<T extends core::Object>() → self::f::T
return null;
static method test() → void {
do {
dynamic x = 0;
}
while (self::f<dynamic>())
}
static method main() → dynamic {}
10 changes: 10 additions & 0 deletions pkg/front_end/testcases/inference_new/do_loop.dart.outline.expect
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
library test;
import self as self;
import "dart:core" as core;

static method f<T extends core::Object>() → self::f::T
;
static method test() → void
;
static method main() → dynamic
;
13 changes: 13 additions & 0 deletions pkg/front_end/testcases/inference_new/do_loop.dart.strong.expect
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
library test;
import self as self;
import "dart:core" as core;

static method f<T extends core::Object>() → self::f::T
return null;
static method test() → void {
do {
core::int x = 0;
}
while (self::f<core::bool>())
}
static method main() → dynamic {}
16 changes: 16 additions & 0 deletions pkg/front_end/testcases/inference_new/while_loop.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

/*@testedFeatures=inference*/
library test;

T f<T>() => null;

void test() {
while (/*@typeArgs=bool*/ f()) {
var /*@type=int*/ x = 0;
}
}

main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
library test;
import self as self;
import "dart:core" as core;

static method f<T extends core::Object>() → self::f::T
return null;
static method test() → void {
while (self::f<dynamic>()) {
dynamic x = 0;
}
}
static method main() → dynamic {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
library test;
import self as self;
import "dart:core" as core;

static method f<T extends core::Object>() → self::f::T
;
static method test() → void
;
static method main() → dynamic
;
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
library test;
import self as self;
import "dart:core" as core;

static method f<T extends core::Object>() → self::f::T
return null;
static method test() → void {
while (self::f<core::bool>()) {
core::int x = 0;
}
}
static method main() → dynamic {}
2 changes: 2 additions & 0 deletions pkg/front_end/testcases/kompile.status
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@ inference/unsafe_block_closure_inference_method_call_no_type_param: Crash
inference/void_return_type_subtypes_dynamic: Crash
inference_new/dependency_only_if_generic_method: Crash
inference_new/dependency_only_if_overloaded: Crash
inference_new/do_loop: VerificationError
inference_new/downwards_inference_inside_top_level: Crash
inference_new/downwards_inference_inside_top_level_2: Crash
inference_new/field_inference_circularity: Crash
Expand All @@ -415,6 +416,7 @@ inference_new/switch: Crash
inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2: Crash
inference_new/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2: Crash
inference_new/void_return_type_subtypes_dynamic: Crash
inference_new/while_loop: VerificationError

rasta/abstract_constructor: Fail
rasta/bad_constructor_redirection: Crash
Expand Down

0 comments on commit 213c208

Please sign in to comment.