// 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 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 a, B b); class Bar { Foo 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 fooIntString = null; Foo 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(); }