OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 // Tests function statements and expressions. | |
6 | |
7 class Bug4089219 { | |
8 int x; | |
9 var f; | |
10 | |
11 Bug4089219(int i) : this.x = i { | |
12 f = () => x; | |
13 } | |
14 } | |
15 | |
16 class Bug4342163 { | |
17 final m; | |
18 Bug4342163(int a) : this.m = (() => a) {} | |
19 } | |
20 | |
21 class StaticFunctionDef { | |
22 static final int one = 1; | |
23 static var fn1; | |
24 static var fn2; | |
25 static var fn3; | |
26 | |
27 static init() { | |
28 fn1 = () { return one; }; | |
29 fn2 = () { return (() { return one; })(); }; | |
30 fn3 = () { | |
31 final local = 1; | |
32 return (() { return local; })(); | |
33 }; | |
34 } | |
35 } | |
36 | |
37 class A { | |
38 var ma; | |
39 A(a) {ma = a;} | |
40 } | |
41 | |
42 class B1 extends A { | |
43 final mfn; | |
44 B1(int a) : super(a), this.mfn = (() {return a;}) { | |
45 } | |
46 } | |
47 | |
48 class B2 extends A { | |
49 final mfn; | |
50 B2(int a) : super(2), this.mfn = (() {return a;}) { | |
51 } | |
52 } | |
53 | |
54 class B3 extends A { | |
55 final mfn; | |
56 B3(int a) : super(() {return a;}), this.mfn = (() {return a;}) { | |
57 } | |
58 } | |
59 | |
60 typedef void Fisk(); | |
61 | |
62 class FunctionTest { | |
63 | |
64 FunctionTest() {} | |
65 | |
66 static void testMain() { | |
67 var test = new FunctionTest(); | |
68 test.testRecursiveClosureRef(); | |
69 test.testForEach(); | |
70 test.testVarOrder1(); | |
71 test.testVarOrder2(); | |
72 test.testLexicalClosureRef1(); | |
73 test.testLexicalClosureRef2(); | |
74 test.testLexicalClosureRef3(); | |
75 test.testLexicalClosureRef4(); | |
76 test.testLexicalClosureRef5(); | |
77 test.testFunctionScopes(); | |
78 test.testDefaultParametersOrder(); | |
79 test.testParametersOrder(); | |
80 test.testFunctionDefaults1(); | |
81 test.testFunctionDefaults2(); | |
82 test.testEscapingFunctions(); | |
83 test.testThisBinding(); | |
84 test.testFnBindingInStatics(); | |
85 test.testFnBindingInInitLists(); | |
86 test.testSubclassConstructorScopeAlias(); | |
87 } | |
88 | |
89 void testSubclassConstructorScopeAlias() { | |
90 var b1 = new B1(10); | |
91 Expect.equals(10, (b1.mfn)()); | |
92 Expect.equals(10, b1.ma); | |
93 | |
94 var b2 = new B2(11); | |
95 Expect.equals(11, (b2.mfn)()); | |
96 Expect.equals(2, b2.ma); | |
97 | |
98 var b3 = new B3(12); | |
99 Expect.equals(12, (b3.mfn)()); | |
100 Expect.equals(12, (b3.ma)()); | |
101 } | |
102 | |
103 void testFnBindingInInitLists() { | |
104 Expect.equals(1, (new Bug4342163(1).m)()); | |
105 } | |
106 | |
107 void testFnBindingInStatics() { | |
108 StaticFunctionDef.init(); | |
109 Expect.equals(1, ((StaticFunctionDef.fn1)())); | |
110 Expect.equals(1, ((StaticFunctionDef.fn2)())); | |
111 Expect.equals(1, ((StaticFunctionDef.fn3)())); | |
112 } | |
113 | |
114 Fisk testReturnVoidFunction() { | |
115 void f() {} | |
116 Fisk x = f; | |
117 return f; | |
118 } | |
119 | |
120 void testVarOrder1() { | |
121 var a = 0, b = a++, c = a++; | |
122 | |
123 Expect.equals(a, 2); | |
124 Expect.equals(b, 0); | |
125 Expect.equals(c, 1); | |
126 } | |
127 | |
128 void testVarOrder2() { | |
129 var a = 0; | |
130 f() {return a++;}; | |
131 var b = f(), c = f(); | |
132 | |
133 Expect.equals(a, 2); | |
134 Expect.equals(b, 0); | |
135 Expect.equals(c, 1); | |
136 } | |
137 | |
138 void testLexicalClosureRef1() { | |
139 var a = 1; | |
140 var f, g; | |
141 { | |
142 var b = 2; | |
143 f = () {return b - a;}; | |
144 } | |
145 | |
146 { | |
147 var b = 3; | |
148 g = () {return b - a;}; | |
149 } | |
150 Expect.equals(1, f()); | |
151 Expect.equals(2, g()); | |
152 } | |
153 | |
154 void testLexicalClosureRef2() { | |
155 var a = 1; | |
156 var f, g; | |
157 { | |
158 var b = 2; | |
159 f = () {return ((){return b - a;})();}; | |
160 } | |
161 | |
162 { | |
163 var b = 3; | |
164 g = () {return ((){return b - a;})();}; | |
165 } | |
166 Expect.equals(1, f()); | |
167 Expect.equals(2, g()); | |
168 } | |
169 | |
170 void testLexicalClosureRef3() { | |
171 var a = new List(); | |
172 for (int i = 0; i < 10; i++) { | |
173 var x = i; | |
174 a.add(() {return x;}); | |
175 } | |
176 | |
177 var sum = 0; | |
178 for (int i = 0; i < a.length; i++) { | |
179 sum += (a[i])(); | |
180 } | |
181 | |
182 Expect.equals(45, sum); | |
183 } | |
184 | |
185 void testLexicalClosureRef5() { | |
186 { | |
187 var a; | |
188 Expect.equals(null, a); | |
189 a = 1; | |
190 Expect.equals(1, a); | |
191 } | |
192 | |
193 { | |
194 var a; | |
195 Expect.equals(null, a); | |
196 a = 1; | |
197 Expect.equals(1, a); | |
198 } | |
199 } | |
200 | |
201 // Make sure labels are preserved, and a second 'i' does influence the first. | |
202 void testLexicalClosureRef4() { | |
203 var a = new List(); | |
204 x:for (int i = 0; i < 10; i++) { | |
205 a.add(() {return i;}); | |
206 continue x; | |
207 } | |
208 | |
209 var sum = 0; | |
210 for (int i = 0; i < a.length; i++) { | |
211 sum += (a[i])(); | |
212 } | |
213 | |
214 Expect.equals(45, sum); | |
215 } | |
216 | |
217 int tempField; | |
218 | |
219 // Validate that a closure that calls the private name of a function (for | |
220 // for recursion) calls the version of function with the bound names. | |
221 void testRecursiveClosureRef() { | |
222 tempField = 2; | |
223 var x = 3; | |
224 var g = f(a) { | |
225 tempField++; | |
226 x++; | |
227 if (a > 0) { | |
228 f(--a); | |
229 } | |
230 }; | |
231 g(2); | |
232 | |
233 | |
234 Expect.equals(5, tempField); | |
235 Expect.equals(6, x); | |
236 } | |
237 | |
238 void testForEach() { | |
239 List<int> vals = [1,2,3]; | |
240 int total = 0; | |
241 vals.forEach((int v) { | |
242 total += v; | |
243 }); | |
244 Expect.equals(6, total); | |
245 } | |
246 | |
247 void testFunctionScopes() { | |
248 // Function expression. 'recurse' is only defined within the function body. | |
249 // FAILS: | |
250 // var factorial0 = function recurse(int x) { | |
251 // return (x == 1) ? 1 : (x * recurse(x - 1)); | |
252 // }; | |
253 // TEMP: | |
254 var factorial0; | |
255 factorial0 = recurse(int x) { | |
256 return (x == 1) ? 1 : (x * factorial0(x - 1)); | |
257 }; | |
258 // END TEMP | |
259 | |
260 | |
261 // Function statement. 'factorial1' is defined in the outer scope. | |
262 int factorial1(int x) { | |
263 return (x == 1) ? 1 : (x * factorial1(x - 1)); | |
264 } | |
265 | |
266 // This would fail to compile if 'recurse' were defined in the outer scope. | |
267 // Which it shouldn't be. | |
268 int recurse = 42; | |
269 | |
270 Expect.equals(6, factorial0(3)); | |
271 Expect.equals(24, factorial0(4)); | |
272 } | |
273 | |
274 void testDefaultParametersOrder() { | |
275 f([a = 1, b = 3]) { | |
276 return a - b; | |
277 } | |
278 Expect.equals(-2, f()); | |
279 } | |
280 | |
281 void testParametersOrder() { | |
282 f(a, b) { | |
283 return a - b; | |
284 } | |
285 Expect.equals(-2, f(1,3)); | |
286 } | |
287 | |
288 void testFunctionDefaults1() { | |
289 // TODO(jimhug): This return null shouldn't be necessary. | |
290 f() { return null; }; | |
291 (([a = 10]) { Expect.equals(10, a); })(); | |
292 ((a, [b = 10]) { Expect.equals(10, b); })(1); | |
293 (([a = 10]) { Expect.equals(null, a); })( f() ); | |
294 // FAILS: (([a = 10]) { Expect.equals(null ,a); })( f() ); | |
295 } | |
296 | |
297 void testFunctionDefaults2() { | |
298 Expect.equals(10, helperFunctionDefaults2()); | |
299 Expect.equals(1, helperFunctionDefaults2(1)); | |
300 } | |
301 | |
302 num helperFunctionDefaults2([a = 10]) { | |
303 return ((){return a;})(); | |
304 } | |
305 | |
306 void testEscapingFunctions() { | |
307 f() { return 42; }; | |
308 (() { Expect.equals(42, f()); })(); | |
309 var o = new Bug4089219(42); | |
310 Expect.equals(42, (o.f)()); | |
311 } | |
312 | |
313 void testThisBinding() { | |
314 Expect.equals(this, () { return this; }()); | |
315 } | |
316 } | |
317 | |
318 typedef void Foo<A, B>(A a, B b); | |
319 | |
320 class Bar<A, B> { | |
321 Foo<A, B> field; | |
322 Bar(A a, B b) : this.field = ((A a1, B b2){}) { | |
323 field(a, b); | |
324 } | |
325 } | |
326 | |
327 typedef UntypedFunction(arg); | |
328 typedef UntypedFunction2(arg); | |
329 | |
330 class UseFunctionTypes { | |
331 void test() { | |
332 Function f = null; | |
333 UntypedFunction uf = null; | |
334 UntypedFunction2 uf2 = null; | |
335 Foo foo = null; | |
336 Foo<int, String> fooIntString = null; | |
337 | |
338 f = uf; | |
339 f = uf2; | |
340 f = foo; | |
341 f = fooIntString; | |
342 | |
343 uf = f; | |
344 uf2 = f; | |
345 foo = f; | |
346 fooIntString = f; | |
347 | |
348 foo = fooIntString; | |
349 fooIntString = foo; | |
350 | |
351 uf = uf2; | |
352 uf2 = uf; | |
353 } | |
354 } | |
355 | |
356 main() { | |
357 FunctionTest.testMain(); | |
358 } | |
OLD | NEW |