e4cc3c98e5
TEST=ci Bug: Contributes to https://github.com/dart-lang/sdk/issues/49529 Change-Id: Ic129ef2d89f625d9ec6a7a1c301cffddd60b2ff7 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/258920 Reviewed-by: Lasse Nielsen <lrn@google.com> Commit-Queue: Michael Thomsen <mit@google.com> Reviewed-by: Slava Egorov <vegorov@google.com>
230 lines
4.9 KiB
Dart
230 lines
4.9 KiB
Dart
// Copyright (c) 2011, 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.
|
|
// Dart test program testing closures.
|
|
|
|
// @dart = 2.9
|
|
|
|
import "package:expect/expect.dart";
|
|
|
|
class LocalFunctionTest {
|
|
LocalFunctionTest()
|
|
: field1 = 100,
|
|
field2_ = 200 {}
|
|
static int f(int n) {
|
|
int a = 0;
|
|
g(int m) {
|
|
a = 3 * n + m + 1; // Capture parameter n and local a.
|
|
return a;
|
|
}
|
|
|
|
var b = g(n);
|
|
return a + b;
|
|
}
|
|
|
|
static int h(int n) {
|
|
k(int n) {
|
|
var a = new List<dynamic>.filled(n, null);
|
|
var b = new List<dynamic>.filled(n, null);
|
|
int i;
|
|
for (i = 0; i < n; i++) {
|
|
var j = i;
|
|
a[i] = () => i; // Captured i is always n.
|
|
b[i] = () => j; // Captured j varies from 0 to n-1.
|
|
}
|
|
var a_sum = 0;
|
|
var b_sum = 0;
|
|
for (int i = 0; i < n; i++) {
|
|
a_sum += a[i]();
|
|
b_sum += b[i]();
|
|
}
|
|
return a_sum + b_sum;
|
|
}
|
|
|
|
return k(n);
|
|
}
|
|
|
|
static int h2(int n) {
|
|
k(int n) {
|
|
var a = new List<dynamic>.filled(n, null);
|
|
var b = new List<dynamic>.filled(n, null);
|
|
for (int i = 0; i < n; i++) {
|
|
var j = i;
|
|
a[i] = () => i; // Captured i varies from 0 to n-1.
|
|
b[i] = () => j; // Captured j varies from 0 to n-1.
|
|
}
|
|
var a_sum = 0;
|
|
var b_sum = 0;
|
|
for (int i = 0; i < n; i++) {
|
|
a_sum += a[i]();
|
|
b_sum += b[i]();
|
|
}
|
|
return a_sum + b_sum;
|
|
}
|
|
|
|
return k(n);
|
|
}
|
|
|
|
int field1;
|
|
int field2_;
|
|
int get field2 {
|
|
return field2_;
|
|
}
|
|
|
|
void set field2(int value) {
|
|
field2_ = value;
|
|
}
|
|
|
|
int method(int n) {
|
|
incField1() {
|
|
field1++;
|
|
}
|
|
|
|
incField2() {
|
|
field2++;
|
|
}
|
|
|
|
for (int i = 0; i < n; i++) {
|
|
incField1();
|
|
incField2();
|
|
}
|
|
return field1 + field2;
|
|
}
|
|
|
|
int execute(int times, apply(int x)) {
|
|
for (int i = 0; i < times; i++) {
|
|
apply(i);
|
|
}
|
|
return field1;
|
|
}
|
|
|
|
int testExecute(int n) {
|
|
execute(n, (int x) {
|
|
field1 += x;
|
|
});
|
|
return field1;
|
|
}
|
|
|
|
static int foo(int n) {
|
|
return -100; // Wrong foo.
|
|
}
|
|
|
|
static testSelfReference1(int n) {
|
|
int foo(int n) {
|
|
if (n == 0) {
|
|
return 0;
|
|
} else {
|
|
return 1 + foo(n - 1); // Local foo, not static foo.
|
|
}
|
|
}
|
|
|
|
;
|
|
return foo(n); // Local foo, not static foo.
|
|
}
|
|
|
|
static void hep(Function f) {
|
|
f();
|
|
}
|
|
|
|
static testNesting(int n) {
|
|
var a = new List<dynamic>.filled(n * n, null);
|
|
f0() {
|
|
for (int i = 0; i < n; i++) {
|
|
int vi = i;
|
|
f1() {
|
|
for (int j = 0; j < n; j++) {
|
|
int vj = j;
|
|
a[i * n + j] = () => vi * n + vj;
|
|
}
|
|
}
|
|
|
|
f1();
|
|
}
|
|
}
|
|
|
|
f0();
|
|
int result = 0;
|
|
for (int k = 0; k < n * n; k++) {
|
|
Expect.equals(k, a[k]());
|
|
result += a[k]();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
static var field5;
|
|
static var set_field5_func;
|
|
static testClosureCallStatement(int x) {
|
|
LocalFunctionTest.set_field5_func = (int n) {
|
|
field5 = n * n;
|
|
};
|
|
(LocalFunctionTest.set_field5_func)(x);
|
|
Expect.equals(x * x, LocalFunctionTest.field5);
|
|
return true;
|
|
}
|
|
|
|
static testExceptions() {
|
|
dynamic f = (int n) => n + 1;
|
|
Expect.equals(2, f(1));
|
|
Expect.equals(true, f is Function);
|
|
Expect.equals(true, f is Object);
|
|
Expect.equals(true, f.toString().startsWith("Closure"));
|
|
bool exception_caught = false;
|
|
try {
|
|
f(1, 2);
|
|
} on NoSuchMethodError catch (e) {
|
|
exception_caught = true;
|
|
}
|
|
Expect.equals(true, exception_caught);
|
|
exception_caught = false;
|
|
try {
|
|
f();
|
|
} on NoSuchMethodError catch (e) {
|
|
exception_caught = true;
|
|
}
|
|
Expect.equals(true, exception_caught);
|
|
exception_caught = false;
|
|
try {
|
|
f.xyz(0);
|
|
} on NoSuchMethodError catch (e) {
|
|
exception_caught = true;
|
|
}
|
|
Expect.equals(true, exception_caught);
|
|
|
|
// Overwrite closure value.
|
|
f = 3;
|
|
exception_caught = false;
|
|
try {
|
|
f(1);
|
|
} on NoSuchMethodError catch (e) {
|
|
exception_caught = true;
|
|
}
|
|
Expect.equals(true, exception_caught);
|
|
|
|
// Do not expect any exceptions to be thrown.
|
|
var g = ([int n = 1]) => n + 1;
|
|
Expect.equals(2, g());
|
|
Expect.equals(3, g(2));
|
|
}
|
|
|
|
static int doThis(int n, int f(int n)) {
|
|
return f(n);
|
|
}
|
|
|
|
static testMain() {
|
|
Expect.equals(2 * (3 * 2 + 2 + 1), f(2));
|
|
Expect.equals(10 * 10 + 10 * 9 / 2, h(10));
|
|
Expect.equals(90, h2(10));
|
|
Expect.equals(320, new LocalFunctionTest().method(10));
|
|
Expect.equals(145, new LocalFunctionTest().testExecute(10));
|
|
Expect.equals(5, testSelfReference1(5));
|
|
Expect.equals(24 * 25 / 2, testNesting(5));
|
|
Expect.equals(true, testClosureCallStatement(7));
|
|
Expect.equals(99, doThis(10, (n) => n * n - 1));
|
|
testExceptions();
|
|
}
|
|
}
|
|
|
|
main() {
|
|
LocalFunctionTest.testMain();
|
|
}
|