blob: aa5f087d35f4f9533423cee48468e00addc577c4 [file] [log] [blame]
// 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.
import "package:expect/expect.dart";
// Tests function statements and expressions.
class Bug4089219 {
int x;
var f;
Bug4089219(int i) : this.x = i {
f = () => x;
}
}
class Bug4342163 {
final m;
Bug4342163(int a) : this.m = (() => a) {}
}
class StaticFunctionDef {
static const int one = 1;
static var fn1;
static var fn2;
static var fn3;
static init() {
fn1 = () {
return one;
};
fn2 = () {
return (() {
return one;
})();
};
fn3 = () {
final local = 1;
return (() {
return local;
})();
};
}
}
class A {
var ma;
A(a) {
ma = a;
}
}
class B1 extends A {
final mfn;
B1(int a)
: this.mfn = (() {
return a;
}),
super(a);
}
class B2 extends A {
final mfn;
B2(int a)
: this.mfn = (() {
return a;
}),
super(2);
}
class B3 extends A {
final mfn;
B3(int a)
: this.mfn = (() {
return a;
}),
super(() {
return a;
});
}
typedef void Fisk();
class FunctionTest {
FunctionTest() {}
static void testMain() {
var test = new FunctionTest();
test.testForEach();
test.testVarOrder1();
test.testVarOrder2();
test.testLexicalClosureRef1();
test.testLexicalClosureRef2();
test.testLexicalClosureRef3();
test.testLexicalClosureRef4();
test.testLexicalClosureRef5();
test.testDefaultParametersOrder();
test.testParametersOrder();
test.testFunctionDefaults1();
test.testFunctionDefaults2();
test.testEscapingFunctions();
test.testThisBinding();
test.testFnBindingInStatics();
test.testFnBindingInInitLists();
test.testSubclassConstructorScopeAlias();
}
void testSubclassConstructorScopeAlias() {
var b1 = new B1(10);
Expect.equals(10, (b1.mfn)());
Expect.equals(10, b1.ma);
var b2 = new B2(11);
Expect.equals(11, (b2.mfn)());
Expect.equals(2, b2.ma);
var b3 = new B3(12);
Expect.equals(12, (b3.mfn)());
Expect.equals(12, (b3.ma)());
}
void testFnBindingInInitLists() {
Expect.equals(1, (new Bug4342163(1).m)());
}
void testFnBindingInStatics() {
StaticFunctionDef.init();
Expect.equals(1, ((StaticFunctionDef.fn1)()));
Expect.equals(1, ((StaticFunctionDef.fn2)()));
Expect.equals(1, ((StaticFunctionDef.fn3)()));
}
Fisk testReturnVoidFunction() {
void f() {}
Fisk x = f;
return f;
}
void testVarOrder1() {
var a = 0, b = a++, c = a++;
Expect.equals(a, 2);
Expect.equals(b, 0);
Expect.equals(c, 1);
}
void testVarOrder2() {
var a = 0;
f() {
return a++;
}
;
var b = f(), c = f();
Expect.equals(a, 2);
Expect.equals(b, 0);
Expect.equals(c, 1);
}
void testLexicalClosureRef1() {
var a = 1;
var f, g;
{
var b = 2;
f = () {
return b - a;
};
}
{
var b = 3;
g = () {
return b - a;
};
}
Expect.equals(1, f());
Expect.equals(2, g());
}
void testLexicalClosureRef2() {
var a = 1;
var f, g;
{
var b = 2;
f = () {
return (() {
return b - a;
})();
};
}
{
var b = 3;
g = () {
return (() {
return b - a;
})();
};
}
Expect.equals(1, f());
Expect.equals(2, g());
}
void testLexicalClosureRef3() {
var a = new List();
for (int i = 0; i < 10; i++) {
var x = i;
a.add(() {
return x;
});
}
var sum = 0;
for (int i = 0; i < a.length; i++) {
sum += (a[i])();
}
Expect.equals(45, sum);
}
void testLexicalClosureRef5() {
{
var a;
Expect.equals(null, a);
a = 1;
Expect.equals(1, a);
}
{
var a;
Expect.equals(null, a);
a = 1;
Expect.equals(1, a);
}
}
// Make sure labels are preserved, and a second 'i' does influence the first.
void testLexicalClosureRef4() {
var a = new List();
x:
for (int i = 0; i < 10; i++) {
a.add(() {
return i;
});
continue x;
}
var sum = 0;
for (int i = 0; i < a.length; i++) {
sum += (a[i])();
}
Expect.equals(45, sum);
}
int tempField;
void testForEach() {
List<int> vals = [1, 2, 3];
int total = 0;
vals.forEach((int v) {
total += v;
});
Expect.equals(6, total);
}
void testDefaultParametersOrder() {
f([a = 1, b = 3]) {
return a - b;
}
Expect.equals(-2, f());
}
void testParametersOrder() {
f(a, b) {
return a - b;
}
Expect.equals(-2, f(1, 3));
}
void testFunctionDefaults1() {
// TODO(jimhug): This return null shouldn't be necessary.
f() {
return null;
}
;
(([a = 10]) {
Expect.equals(10, a);
})();
((a, [b = 10]) {
Expect.equals(10, b);
})(1);
(([a = 10]) {
Expect.equals(null, a);
})(f());
// FAILS: (([a = 10]) { Expect.equals(null ,a); })( f() );
}
void testFunctionDefaults2() {
Expect.equals(10, helperFunctionDefaults2());
Expect.equals(1, helperFunctionDefaults2(1));
}
num helperFunctionDefaults2([a = 10]) {
return (() {
return a;
})();
}
void testEscapingFunctions() {
f() {
return 42;
}
;
(() {
Expect.equals(42, f());
})();
var o = new Bug4089219(42);
Expect.equals(42, (o.f)());
}
void testThisBinding() {
Expect.equals(this, () {
return this;
}());
}
}
typedef void Foo<A, B>(A a, B b);
class Bar<A, B> {
Foo<A, B> field;
Bar(A a, B b) : this.field = ((A a1, B b2) {}) {
field(a, b);
}
}
typedef UntypedFunction(arg);
typedef UntypedFunction2(arg);
class UseFunctionTypes {
void test() {
Function f = null;
UntypedFunction uf = null;
UntypedFunction2 uf2 = null;
Foo foo = null;
Foo<int, String> fooIntString = null;
Foo<Object, Object> fooObjectObject = null;
f = uf;
f = uf2;
f = foo;
f = fooIntString;
uf = f;
uf2 = f;
foo = f;
fooIntString = f;
fooIntString = foo;
foo = fooObjectObject;
fooObjectObject = foo;
uf = uf2;
uf2 = uf;
}
}
main() {
FunctionTest.testMain();
}