mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 23:29:47 +00:00
[cfe] Do-while statements for const functions.
Change-Id: I881fb535ef76e564ab76c5fc661d3adbbe5aed0f Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/192401 Commit-Queue: Kallen Tu <kallentu@google.com> Reviewed-by: Jake Macdonald <jakemac@google.com> Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
This commit is contained in:
parent
86c5085565
commit
9e5a6c1568
|
@ -3362,6 +3362,29 @@ class StatementConstantEvaluator extends StatementVisitor<ExecutionStatus> {
|
|||
ExecutionStatus visitBreakStatement(BreakStatement node) =>
|
||||
new BreakStatus(node.target);
|
||||
|
||||
@override
|
||||
ExecutionStatus visitDoStatement(DoStatement node) {
|
||||
Constant condition;
|
||||
do {
|
||||
ExecutionStatus status = node.body.accept(this);
|
||||
if (status is! ProceedStatus) return status;
|
||||
condition = evaluate(node.condition);
|
||||
} while (condition is BoolConstant && condition.value);
|
||||
|
||||
if (condition is AbortConstant) {
|
||||
return new AbortStatus(condition);
|
||||
} else if (condition is! BoolConstant) {
|
||||
return new AbortStatus(exprEvaluator.createErrorConstant(
|
||||
node.condition,
|
||||
templateConstEvalInvalidType.withArguments(
|
||||
condition,
|
||||
exprEvaluator.typeEnvironment.coreTypes.boolLegacyRawType,
|
||||
condition.getType(exprEvaluator._staticTypeContext),
|
||||
exprEvaluator.isNonNullableByDefault)));
|
||||
}
|
||||
return const ProceedStatus();
|
||||
}
|
||||
|
||||
@override
|
||||
ExecutionStatus visitIfStatement(IfStatement node) {
|
||||
Constant condition = evaluate(node.condition);
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
// Copyright (c) 2021, 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.
|
||||
|
||||
// Tests do-while statements for const functions.
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
const var1 = fn();
|
||||
int fn() {
|
||||
int x = 0;
|
||||
do {
|
||||
x++;
|
||||
} while (x < 2);
|
||||
return x;
|
||||
}
|
||||
|
||||
const var2 = fn2(2);
|
||||
const var3 = fn2(10);
|
||||
int fn2(int a) {
|
||||
int x = 0, b = 0;
|
||||
do {
|
||||
if (x > 5) break;
|
||||
x += a;
|
||||
b++;
|
||||
} while (b < 2);
|
||||
return x;
|
||||
}
|
||||
|
||||
const var4 = fn3();
|
||||
int fn3() {
|
||||
int x = 0, b = 0;
|
||||
do {
|
||||
x += 1;
|
||||
if (x % 2 == 1) continue;
|
||||
b += x;
|
||||
} while (x < 5);
|
||||
return b;
|
||||
}
|
||||
|
||||
void main() {
|
||||
Expect.equals(var1, 2);
|
||||
Expect.equals(var2, 4);
|
||||
Expect.equals(var3, 10);
|
||||
Expect.equals(var4, 6);
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
import "package:expect/expect.dart" as exp;
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
static const field core::int var1 = #C1;
|
||||
static const field core::int var2 = #C2;
|
||||
static const field core::int var3 = #C3;
|
||||
static const field core::int var4 = #C4;
|
||||
static method fn() → core::int {
|
||||
core::int x = 0;
|
||||
do {
|
||||
x = x.{core::num::+}(1);
|
||||
}
|
||||
while (x.{core::num::<}(2))
|
||||
return x;
|
||||
}
|
||||
static method fn2(core::int a) → core::int {
|
||||
core::int x = 0;
|
||||
core::int b = 0;
|
||||
#L1:
|
||||
do {
|
||||
if(x.{core::num::>}(5))
|
||||
break #L1;
|
||||
x = x.{core::num::+}(a);
|
||||
b = b.{core::num::+}(1);
|
||||
}
|
||||
while (b.{core::num::<}(2))
|
||||
return x;
|
||||
}
|
||||
static method fn3() → core::int {
|
||||
core::int x = 0;
|
||||
core::int b = 0;
|
||||
do
|
||||
#L2:
|
||||
{
|
||||
x = x.{core::num::+}(1);
|
||||
if(x.{core::num::%}(2).{core::num::==}(1))
|
||||
break #L2;
|
||||
b = b.{core::num::+}(x);
|
||||
}
|
||||
while (x.{core::num::<}(5))
|
||||
return b;
|
||||
}
|
||||
static method main() → void {
|
||||
exp::Expect::equals(#C1, 2);
|
||||
exp::Expect::equals(#C2, 4);
|
||||
exp::Expect::equals(#C3, 10);
|
||||
exp::Expect::equals(#C4, 6);
|
||||
}
|
||||
|
||||
constants {
|
||||
#C1 = 2
|
||||
#C2 = 4
|
||||
#C3 = 10
|
||||
#C4 = 6
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
import "package:expect/expect.dart" as exp;
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
static const field core::int var1 = #C1;
|
||||
static const field core::int var2 = #C2;
|
||||
static const field core::int var3 = #C3;
|
||||
static const field core::int var4 = #C4;
|
||||
static method fn() → core::int {
|
||||
core::int x = 0;
|
||||
do {
|
||||
x = x.{core::num::+}(1);
|
||||
}
|
||||
while (x.{core::num::<}(2))
|
||||
return x;
|
||||
}
|
||||
static method fn2(core::int a) → core::int {
|
||||
core::int x = 0;
|
||||
core::int b = 0;
|
||||
#L1:
|
||||
do {
|
||||
if(x.{core::num::>}(5))
|
||||
break #L1;
|
||||
x = x.{core::num::+}(a);
|
||||
b = b.{core::num::+}(1);
|
||||
}
|
||||
while (b.{core::num::<}(2))
|
||||
return x;
|
||||
}
|
||||
static method fn3() → core::int {
|
||||
core::int x = 0;
|
||||
core::int b = 0;
|
||||
do
|
||||
#L2:
|
||||
{
|
||||
x = x.{core::num::+}(1);
|
||||
if(x.{core::num::%}(2).{core::num::==}(1))
|
||||
break #L2;
|
||||
b = b.{core::num::+}(x);
|
||||
}
|
||||
while (x.{core::num::<}(5))
|
||||
return b;
|
||||
}
|
||||
static method main() → void {
|
||||
exp::Expect::equals(#C1, 2);
|
||||
exp::Expect::equals(#C2, 4);
|
||||
exp::Expect::equals(#C3, 10);
|
||||
exp::Expect::equals(#C4, 6);
|
||||
}
|
||||
|
||||
constants {
|
||||
#C1 = 2
|
||||
#C2 = 4
|
||||
#C3 = 10
|
||||
#C4 = 6
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
import "package:expect/expect.dart";
|
||||
|
||||
const var1 = fn();
|
||||
int fn() {}
|
||||
const var2 = fn2(2);
|
||||
const var3 = fn2(10);
|
||||
int fn2(int a) {}
|
||||
const var4 = fn3();
|
||||
int fn3() {}
|
||||
void main() {}
|
|
@ -0,0 +1,10 @@
|
|||
import "package:expect/expect.dart";
|
||||
|
||||
const var1 = fn();
|
||||
const var2 = fn2(2);
|
||||
const var3 = fn2(10);
|
||||
const var4 = fn3();
|
||||
int fn() {}
|
||||
int fn2(int a) {}
|
||||
int fn3() {}
|
||||
void main() {}
|
|
@ -0,0 +1,59 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
import "package:expect/expect.dart" as exp;
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
static const field core::int var1 = #C1;
|
||||
static const field core::int var2 = #C2;
|
||||
static const field core::int var3 = #C3;
|
||||
static const field core::int var4 = #C4;
|
||||
static method fn() → core::int {
|
||||
core::int x = 0;
|
||||
do {
|
||||
x = x.{core::num::+}(1);
|
||||
}
|
||||
while (x.{core::num::<}(2))
|
||||
return x;
|
||||
}
|
||||
static method fn2(core::int a) → core::int {
|
||||
core::int x = 0;
|
||||
core::int b = 0;
|
||||
#L1:
|
||||
do {
|
||||
if(x.{core::num::>}(5))
|
||||
break #L1;
|
||||
x = x.{core::num::+}(a);
|
||||
b = b.{core::num::+}(1);
|
||||
}
|
||||
while (b.{core::num::<}(2))
|
||||
return x;
|
||||
}
|
||||
static method fn3() → core::int {
|
||||
core::int x = 0;
|
||||
core::int b = 0;
|
||||
do
|
||||
#L2:
|
||||
{
|
||||
x = x.{core::num::+}(1);
|
||||
if(x.{core::num::%}(2).{core::num::==}(1))
|
||||
break #L2;
|
||||
b = b.{core::num::+}(x);
|
||||
}
|
||||
while (x.{core::num::<}(5))
|
||||
return b;
|
||||
}
|
||||
static method main() → void {
|
||||
exp::Expect::equals(#C1, 2);
|
||||
exp::Expect::equals(#C2, 4);
|
||||
exp::Expect::equals(#C3, 10);
|
||||
exp::Expect::equals(#C4, 6);
|
||||
}
|
||||
|
||||
constants {
|
||||
#C1 = 2
|
||||
#C2 = 4
|
||||
#C3 = 10
|
||||
#C4 = 6
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
static const field core::int var1 = self::fn();
|
||||
static const field core::int var2 = self::fn2(2);
|
||||
static const field core::int var3 = self::fn2(10);
|
||||
static const field core::int var4 = self::fn3();
|
||||
static method fn() → core::int
|
||||
;
|
||||
static method fn2(core::int a) → core::int
|
||||
;
|
||||
static method fn3() → core::int
|
||||
;
|
||||
static method main() → void
|
||||
;
|
|
@ -0,0 +1,59 @@
|
|||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
import "package:expect/expect.dart" as exp;
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
static const field core::int var1 = #C1;
|
||||
static const field core::int var2 = #C2;
|
||||
static const field core::int var3 = #C3;
|
||||
static const field core::int var4 = #C4;
|
||||
static method fn() → core::int {
|
||||
core::int x = 0;
|
||||
do {
|
||||
x = x.{core::num::+}(1);
|
||||
}
|
||||
while (x.{core::num::<}(2))
|
||||
return x;
|
||||
}
|
||||
static method fn2(core::int a) → core::int {
|
||||
core::int x = 0;
|
||||
core::int b = 0;
|
||||
#L1:
|
||||
do {
|
||||
if(x.{core::num::>}(5))
|
||||
break #L1;
|
||||
x = x.{core::num::+}(a);
|
||||
b = b.{core::num::+}(1);
|
||||
}
|
||||
while (b.{core::num::<}(2))
|
||||
return x;
|
||||
}
|
||||
static method fn3() → core::int {
|
||||
core::int x = 0;
|
||||
core::int b = 0;
|
||||
do
|
||||
#L2:
|
||||
{
|
||||
x = x.{core::num::+}(1);
|
||||
if(x.{core::num::%}(2).{core::num::==}(1))
|
||||
break #L2;
|
||||
b = b.{core::num::+}(x);
|
||||
}
|
||||
while (x.{core::num::<}(5))
|
||||
return b;
|
||||
}
|
||||
static method main() → void {
|
||||
exp::Expect::equals(#C1, 2);
|
||||
exp::Expect::equals(#C2, 4);
|
||||
exp::Expect::equals(#C3, 10);
|
||||
exp::Expect::equals(#C4, 6);
|
||||
}
|
||||
|
||||
constants {
|
||||
#C1 = 2
|
||||
#C2 = 4
|
||||
#C3 = 10
|
||||
#C4 = 6
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
// Copyright (c) 2021, 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.
|
||||
|
||||
// Tests erroneous do-while statements for const functions.
|
||||
|
||||
// SharedOptions=--enable-experiment=const-functions
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
const var1 = fn();
|
||||
// ^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
|
||||
int fn() {
|
||||
int x = 0;
|
||||
do {
|
||||
x++;
|
||||
} while (x);
|
||||
// ^
|
||||
// [analyzer] COMPILE_TIME_ERROR.NON_BOOL_CONDITION
|
||||
// [cfe] A value of type 'int' can't be assigned to a variable of type 'bool'.
|
||||
return 2;
|
||||
}
|
||||
|
||||
const var2 = fn2();
|
||||
// ^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
|
||||
// [cfe] Constant evaluation error:
|
||||
int fn2() {
|
||||
int x = 0;
|
||||
do {
|
||||
x++;
|
||||
} while (x as dynamic);
|
||||
return 2;
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
// Copyright (c) 2021, 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.
|
||||
|
||||
// Tests do-while statements for const functions.
|
||||
|
||||
// SharedOptions=--enable-experiment=const-functions
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
const var1 = fn();
|
||||
// ^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
|
||||
int fn() {
|
||||
int x = 0;
|
||||
do {
|
||||
x++;
|
||||
} while (x < 2);
|
||||
return x;
|
||||
}
|
||||
|
||||
const var2 = fn2(2);
|
||||
// ^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
|
||||
const var3 = fn2(10);
|
||||
// ^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
|
||||
int fn2(int a) {
|
||||
int x = 0, b = 0;
|
||||
do {
|
||||
if (x > 5) break;
|
||||
x += a;
|
||||
b++;
|
||||
} while (b < 2);
|
||||
return x;
|
||||
}
|
||||
|
||||
const var4 = fn3();
|
||||
// ^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
|
||||
int fn3() {
|
||||
int x = 0, b = 0;
|
||||
do {
|
||||
x += 1;
|
||||
if (x % 2 == 1) continue;
|
||||
b += x;
|
||||
} while (x < 5);
|
||||
return b;
|
||||
}
|
||||
|
||||
void main() {
|
||||
Expect.equals(var1, 2);
|
||||
Expect.equals(var2, 4);
|
||||
Expect.equals(var3, 10);
|
||||
Expect.equals(var4, 6);
|
||||
}
|
Loading…
Reference in a new issue