IntLiteral should prefer int32 during overload resolution
[WebKit-https.git] / Tools / WebGPUShadingLanguageRI / Test.js
1 /*
2  * Copyright (C) 2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25 "use strict";
26
27 if (this.window) {
28     this.print = (text) => {
29         var span = document.createElement("span");
30         document.getElementById("messages").appendChild(span);
31         span.innerHTML = text.replace(/ /g, "&nbsp;").replace(/\n/g, "<br>") + "<br>";
32     };
33     this.preciseTime = () => performance.now() / 1000;
34 } else
35     load("All.js");
36
37 function doPrep(code)
38 {
39     return prepare("/internal/test", 0, code);
40 }
41
42 function doLex(code)
43 {
44     let lexer = new Lexer("/internal/test", "native", 0, code);
45     var result = [];
46     for (;;) {
47         let next = lexer.next();
48         if (!next)
49             return result;
50         result.push(next);
51     }
52     return result;
53 }
54
55 function makeInt(program, value)
56 {
57     return TypedValue.box(program.intrinsics.int32, value);
58 }
59
60 function checkNumber(program, result, expected)
61 {
62     if (!result.type.isNumber)
63         throw new Error("Wrong result type; result: " + result);
64     if (result.value != expected)
65         throw new Error("Wrong result: " + result + " (expected " + expected + ")");
66 }
67
68 function makeUInt(program, value)
69 {
70     return TypedValue.box(program.intrinsics.uint32, value);
71 }
72
73 function makeBool(program, value)
74 {
75     return TypedValue.box(program.intrinsics.bool, value);
76 }
77
78 function checkInt(program, result, expected)
79 {
80     if (!result.type.equals(program.intrinsics.int32))
81         throw new Error("Wrong result type; result: " + result);
82     checkNumber(program, result, expected);
83 }
84
85 function checkUInt(program, result, expected)
86 {
87     if (!result.type.equals(program.intrinsics.uint32))
88         throw new Error("Wrong result type: " + result.type);
89     if (result.value != expected)
90         throw new Error("Wrong result: " + result.value + " (expected " + expected + ")");
91 }
92
93 function checkBool(program, result, expected)
94 {
95     if (!result.type.equals(program.intrinsics.bool))
96         throw new Error("Wrong result type: " + result.type);
97     if (result.value != expected)
98         throw new Error("Wrong result: " + result.value + " (expected " + expected + ")");
99 }
100
101 function checkLexerToken(result, expectedIndex, expectedKind, expectedText)
102 {
103     if (result._index != expectedIndex)
104         throw new Error("Wrong lexer index; result: " + result._index + " (expected " + expectedIndex + ")");
105     if (result._kind != expectedKind)
106         throw new Error("Wrong lexer kind; result: " + result._kind + " (expected " + expectedKind + ")");
107     if (result._text != expectedText)
108         throw new Error("Wrong lexer text; result: " + result._text + " (expected " + expectedText + ")");
109 }
110
111 function checkFail(callback, predicate)
112 {
113     try {
114         callback();
115         throw new Error("Did not throw exception");
116     } catch (e) {
117         if (predicate(e)) {
118             print("    Caught: " + e);
119             return;
120         }
121         throw e;
122     }
123 }
124
125 function TEST_literalBool() {
126     let program = doPrep("bool foo() { return true; }");
127     checkBool(program, callFunction(program, "foo", [], []), true);
128 }
129
130 function TEST_identityBool() {
131     let program = doPrep("bool foo(bool x) { return x; }");
132     checkBool(program, callFunction(program, "foo", [], [makeBool(program, true)]), true);
133     checkBool(program, callFunction(program, "foo", [], [makeBool(program, false)]), false);
134 }
135
136 function TEST_intSimpleMath() {
137     let program = doPrep("int foo(int x, int y) { return x + y; }");
138     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 7), makeInt(program, 5)]), 12);
139     program = doPrep("int foo(int x, int y) { return x - y; }");
140     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 7), makeInt(program, 5)]), 2);
141     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 5), makeInt(program, 7)]), -2);
142     program = doPrep("int foo(int x, int y) { return x * y; }");
143     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 7), makeInt(program, 5)]), 35);
144     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 7), makeInt(program, -5)]), -35);
145     program = doPrep("int foo(int x, int y) { return x / y; }");
146     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 7), makeInt(program, 2)]), 3);
147     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 7), makeInt(program, -2)]), -3);
148 }
149
150 function TEST_uintSimpleMath() {
151     let program = doPrep("uint foo(uint x, uint y) { return x + y; }");
152     checkUInt(program, callFunction(program, "foo", [], [makeUInt(program, 7), makeUInt(program, 5)]), 12);
153     program = doPrep("uint foo(uint x, uint y) { return x - y; }");
154     checkUInt(program, callFunction(program, "foo", [], [makeUInt(program, 7), makeUInt(program, 5)]), 2);
155     checkUInt(program, callFunction(program, "foo", [], [makeUInt(program, 5), makeUInt(program, 7)]), 4294967294);
156     program = doPrep("uint foo(uint x, uint y) { return x * y; }");
157     checkUInt(program, callFunction(program, "foo", [], [makeUInt(program, 7), makeUInt(program, 5)]), 35);
158     program = doPrep("uint foo(uint x, uint y) { return x / y; }");
159     checkUInt(program, callFunction(program, "foo", [], [makeUInt(program, 7), makeUInt(program, 2)]), 3);
160 }
161
162 function TEST_equality() {
163     let program = doPrep("bool foo(uint x, uint y) { return x == y; }");
164     checkBool(program, callFunction(program, "foo", [], [makeUInt(program, 7), makeUInt(program, 5)]), false);
165     checkBool(program, callFunction(program, "foo", [], [makeUInt(program, 7), makeUInt(program, 7)]), true);
166     program = doPrep("bool foo(int x, int y) { return x == y; }");
167     checkBool(program, callFunction(program, "foo", [], [makeInt(program, 7), makeInt(program, 5)]), false);
168     checkBool(program, callFunction(program, "foo", [], [makeInt(program, 7), makeInt(program, 7)]), true);
169     program = doPrep("bool foo(bool x, bool y) { return x == y; }");
170     checkBool(program, callFunction(program, "foo", [], [makeBool(program, false), makeBool(program, true)]), false);
171     checkBool(program, callFunction(program, "foo", [], [makeBool(program, true), makeBool(program, false)]), false);
172     checkBool(program, callFunction(program, "foo", [], [makeBool(program, false), makeBool(program, false)]), true);
173     checkBool(program, callFunction(program, "foo", [], [makeBool(program, true), makeBool(program, true)]), true);
174 }
175
176 function TEST_logicalNegation()
177 {
178     let program = doPrep("bool foo(bool x) { return !x; }");
179     checkBool(program, callFunction(program, "foo", [], [makeBool(program, true)]), false);
180     checkBool(program, callFunction(program, "foo", [], [makeBool(program, false)]), true);
181 }
182
183 function TEST_notEquality() {
184     let program = doPrep("bool foo(uint x, uint y) { return x != y; }");
185     checkBool(program, callFunction(program, "foo", [], [makeUInt(program, 7), makeUInt(program, 5)]), true);
186     checkBool(program, callFunction(program, "foo", [], [makeUInt(program, 7), makeUInt(program, 7)]), false);
187     program = doPrep("bool foo(int x, int y) { return x != y; }");
188     checkBool(program, callFunction(program, "foo", [], [makeInt(program, 7), makeInt(program, 5)]), true);
189     checkBool(program, callFunction(program, "foo", [], [makeInt(program, 7), makeInt(program, 7)]), false);
190     program = doPrep("bool foo(bool x, bool y) { return x != y; }");
191     checkBool(program, callFunction(program, "foo", [], [makeBool(program, false), makeBool(program, true)]), true);
192     checkBool(program, callFunction(program, "foo", [], [makeBool(program, true), makeBool(program, false)]), true);
193     checkBool(program, callFunction(program, "foo", [], [makeBool(program, false), makeBool(program, false)]), false);
194     checkBool(program, callFunction(program, "foo", [], [makeBool(program, true), makeBool(program, true)]), false);
195 }
196
197 function TEST_equalityTypeFailure()
198 {
199     checkFail(
200         () => doPrep("bool foo(int x, uint y) { return x == y; }"),
201         (e) => e instanceof WTypeError && e.message.indexOf("/internal/test:1") != -1);
202 }
203
204 function TEST_generalNegation()
205 {
206     let program = doPrep("bool foo(int x) { return !x; }");
207     checkBool(program, callFunction(program, "foo", [], [makeInt(program, 7)]), false);
208     checkBool(program, callFunction(program, "foo", [], [makeInt(program, 0)]), true);
209 }
210
211 function TEST_add1() {
212     let program = doPrep("int foo(int x) { return x + 1; }");
213     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 42)]), 43);
214 }
215
216 function TEST_simpleGeneric() {
217     let program = doPrep(`
218         T id<T>(T x) { return x; }
219         int foo(int x) { return id(x) + 1; }
220     `);
221     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 42)]), 43);
222 }
223
224 function TEST_nameResolutionFailure()
225 {
226     checkFail(
227         () => doPrep("int foo(int x) { return x + y; }"),
228         (e) => e instanceof WTypeError && e.message.indexOf("/internal/test:1") != -1);
229 }
230
231 function TEST_simpleVariable()
232 {
233     let program = doPrep(`
234         int foo(int p)
235         {
236             int result = p;
237             return result;
238         }
239     `);
240     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 42)]), 42);
241 }
242
243 function TEST_simpleAssignment()
244 {
245     let program = doPrep(`
246         int foo(int p)
247         {
248             int result;
249             result = p;
250             return result;
251         }
252     `);
253     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 42)]), 42);
254 }
255
256 function TEST_simpleDefault()
257 {
258     let program = doPrep(`
259         int foo()
260         {
261             int result;
262             return result;
263         }
264     `);
265     checkInt(program, callFunction(program, "foo", [], []), 0);
266 }
267
268 function TEST_simpleDereference()
269 {
270     let program = doPrep(`
271         int foo(device int^ p)
272         {
273             return ^p;
274         }
275     `);
276     let buffer = new EBuffer(1);
277     buffer.set(0, 13);
278     checkInt(program, callFunction(program, "foo", [], [TypedValue.box(new PtrType(null, "device", program.intrinsics.int32), new EPtr(buffer, 0))]), 13);
279 }
280
281 function TEST_dereferenceStore()
282 {
283     let program = doPrep(`
284         void foo(device int^ p)
285         {
286             ^p = 52;
287         }
288     `);
289     let buffer = new EBuffer(1);
290     buffer.set(0, 13);
291     callFunction(program, "foo", [], [TypedValue.box(new PtrType(null, "device", program.intrinsics.int32), new EPtr(buffer, 0))]);
292     if (buffer.get(0) != 52)
293         throw new Error("Expected buffer to contain 52 but it contains: " + buffer.get(0));
294 }
295
296 function TEST_simpleMakePtr()
297 {
298     let program = doPrep(`
299         thread int^ foo()
300         {
301             int x = 42;
302             return &x;
303         }
304     `);
305     let result = callFunction(program, "foo", [], []);
306     if (!result.type.isPtr)
307         throw new Error("Return type is not a pointer: " + result.type);
308     if (!result.type.elementType.equals(program.intrinsics.int32))
309         throw new Error("Return type is not a pointer to an int: " + result.type);
310     if (!(result.value instanceof EPtr))
311         throw new Error("Return value is not an EPtr: " + result.value);
312     let value = result.value.loadValue();
313     if (value != 42)
314         throw new Error("Expected 42 but got: " + value);
315 }
316
317 function TEST_threadArrayLoad()
318 {
319     let program = doPrep(`
320         int foo(thread int[] array)
321         {
322             return array[0u];
323         }
324     `);
325     let buffer = new EBuffer(1);
326     buffer.set(0, 89);
327     let result = callFunction(program, "foo", [], [TypedValue.box(new ArrayRefType(null, "thread", program.intrinsics.int32), new EArrayRef(new EPtr(buffer, 0), 1))]);
328     checkInt(program, result, 89);
329 }
330
331 function TEST_threadArrayLoadIntLiteral()
332 {
333     let program = doPrep(`
334         int foo(thread int[] array)
335         {
336             return array[0];
337         }
338     `);
339     let buffer = new EBuffer(1);
340     buffer.set(0, 89);
341     let result = callFunction(program, "foo", [], [TypedValue.box(new ArrayRefType(null, "thread", program.intrinsics.int32), new EArrayRef(new EPtr(buffer, 0), 1))]);
342     checkInt(program, result, 89);
343 }
344
345 function TEST_deviceArrayLoad()
346 {
347     let program = doPrep(`
348         int foo(device int[] array)
349         {
350             return array[0u];
351         }
352     `);
353     let buffer = new EBuffer(1);
354     buffer.set(0, 89);
355     let result = callFunction(program, "foo", [], [TypedValue.box(new ArrayRefType(null, "device", program.intrinsics.int32), new EArrayRef(new EPtr(buffer, 0), 1))]);
356     checkInt(program, result, 89);
357 }
358
359 function TEST_threadArrayStore()
360 {
361     let program = doPrep(`
362         void foo(thread int[] array, int value)
363         {
364             array[0u] = value;
365         }
366     `);
367     let buffer = new EBuffer(1);
368     buffer.set(0, 15);
369     let arrayRef = TypedValue.box(
370         new ArrayRefType(null, "thread", program.intrinsics.int32),
371         new EArrayRef(new EPtr(buffer, 0), 1));
372     callFunction(program, "foo", [], [arrayRef, makeInt(program, 65)]);
373     if (buffer.get(0) != 65)
374         throw new Error("Bad value stored into buffer (expected 65): " + buffer.get(0));
375     callFunction(program, "foo", [], [arrayRef, makeInt(program, -111)]);
376     if (buffer.get(0) != -111)
377         throw new Error("Bad value stored into buffer (expected -111): " + buffer.get(0));
378 }
379
380 function TEST_deviceArrayStore()
381 {
382     let program = doPrep(`
383         void foo(device int[] array, int value)
384         {
385             array[0u] = value;
386         }
387     `);
388     let buffer = new EBuffer(1);
389     buffer.set(0, 15);
390     let arrayRef = TypedValue.box(
391         new ArrayRefType(null, "device", program.intrinsics.int32),
392         new EArrayRef(new EPtr(buffer, 0), 1));
393     callFunction(program, "foo", [], [arrayRef, makeInt(program, 65)]);
394     if (buffer.get(0) != 65)
395         throw new Error("Bad value stored into buffer (expected 65): " + buffer.get(0));
396     callFunction(program, "foo", [], [arrayRef, makeInt(program, -111)]);
397     if (buffer.get(0) != -111)
398         throw new Error("Bad value stored into buffer (expected -111): " + buffer.get(0));
399 }
400
401 function TEST_deviceArrayStoreIntLiteral()
402 {
403     let program = doPrep(`
404         void foo(device int[] array, int value)
405         {
406             array[0] = value;
407         }
408     `);
409     let buffer = new EBuffer(1);
410     buffer.set(0, 15);
411     let arrayRef = TypedValue.box(
412         new ArrayRefType(null, "device", program.intrinsics.int32),
413         new EArrayRef(new EPtr(buffer, 0), 1));
414     callFunction(program, "foo", [], [arrayRef, makeInt(program, 65)]);
415     if (buffer.get(0) != 65)
416         throw new Error("Bad value stored into buffer (expected 65): " + buffer.get(0));
417     callFunction(program, "foo", [], [arrayRef, makeInt(program, -111)]);
418     if (buffer.get(0) != -111)
419         throw new Error("Bad value stored into buffer (expected -111): " + buffer.get(0));
420 }
421
422 function TEST_simpleProtocol()
423 {
424     let program = doPrep(`
425         protocol Addable {
426             Addable operator+(Addable, Addable);
427         }
428         T add<T:Addable>(T a, T b)
429         {
430             return a + b;
431         }
432         int foo(int x)
433         {
434             return add(x, 73);
435         }
436     `);
437     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 45)]), 45 + 73);
438 }
439
440 function TEST_typeMismatchReturn()
441 {
442     checkFail(
443         () => doPrep(`
444             int foo()
445             {
446                 return 0u;
447             }
448         `),
449         (e) => e instanceof WTypeError);
450 }
451
452 function TEST_typeMismatchVariableDecl()
453 {
454     checkFail(
455         () => doPrep(`
456             void foo(uint x)
457             {
458                 int y = x;
459             }
460         `),
461         (e) => e instanceof WTypeError);
462 }
463
464 function TEST_typeMismatchAssignment()
465 {
466     checkFail(
467         () => doPrep(`
468             void foo(uint x)
469             {
470                 int y;
471                 y = x;
472             }
473         `),
474         (e) => e instanceof WTypeError);
475 }
476
477 function TEST_typeMismatchReturnParam()
478 {
479     checkFail(
480         () => doPrep(`
481             int foo(uint x)
482             {
483                 return x;
484             }
485         `),
486         (e) => e instanceof WTypeError);
487 }
488
489 function TEST_badAdd()
490 {
491     checkFail(
492         () => doPrep(`
493             void bar<T>(T) { }
494             void foo(int x, uint y)
495             {
496                 bar(x + y);
497             }
498         `),
499         (e) => e instanceof WTypeError && e.message.indexOf("native int32 operator+<>(int32,int32)") != -1);
500 }
501
502 function TEST_lexerKeyword()
503 {
504     let result = doLex("ident for while 123 123u { } {asd asd{ 1a3");
505     if (result.length != 13)
506         throw new Error("Lexer emitted an incorrect number of tokens (expected 12): " + result.length);
507     checkLexerToken(result[0],  0,  "identifier", "ident");
508     checkLexerToken(result[1],  6,  "keyword",     "for");
509     checkLexerToken(result[2],  10, "keyword",     "while");
510     checkLexerToken(result[3],  16, "intLiteral",  "123");
511     checkLexerToken(result[4],  20, "uintLiteral", "123u");
512     checkLexerToken(result[5],  25, "punctuation", "{");
513     checkLexerToken(result[6],  27, "punctuation", "}");
514     checkLexerToken(result[7],  29, "punctuation", "{");
515     checkLexerToken(result[8],  30, "identifier",  "asd");
516     checkLexerToken(result[9],  34, "identifier",  "asd");
517     checkLexerToken(result[10], 37, "punctuation", "{");
518     checkLexerToken(result[11], 39, "intLiteral",  "1");
519     checkLexerToken(result[12], 40, "identifier",  "a3");
520 }
521
522 function TEST_simpleNoReturn()
523 {
524     checkFail(
525         () => doPrep("int foo() { }"),
526         (e) => e instanceof WTypeError);
527 }
528
529 function TEST_simpleUnreachableCode()
530 {
531     checkFail(
532         () => doPrep(`
533             void foo()
534             {
535                 return;
536                 int x;
537             }
538         `),
539         (e) => e instanceof WTypeError);
540 }
541
542 function TEST_simpleStruct()
543 {
544     let program = doPrep(`
545         struct Foo {
546             int x;
547             int y;
548         }
549         Foo foo(Foo foo)
550         {
551             Foo result;
552             result.x = foo.y;
553             result.y = foo.x;
554             return result;
555         }
556     `);
557     let structType = program.types.get("Foo");
558     if (!structType)
559         throw new Error("Did not find Foo type");
560     let buffer = new EBuffer(2);
561     buffer.set(0, 62);
562     buffer.set(1, 24);
563     let result = callFunction(program, "foo", [], [new TypedValue(structType, new EPtr(buffer, 0))]);
564     if (!result.type.equals(structType))
565         throw new Error("Wrong result type: " + result.type);
566     let x = result.ePtr.get(0);
567     let y = result.ePtr.get(1);
568     if (x != 24)
569         throw new Error("Wrong result for x: " + x + " (y = " + y + ")");
570     if (y != 62)
571         throw new Error("Wrong result for y: " + y + " (x + " + x + ")");
572 }
573
574 function TEST_genericStructInstance()
575 {
576     let program = doPrep(`
577         struct Foo<T> {
578             T x;
579             T y;
580         }
581         Foo<int> foo(Foo<int> foo)
582         {
583             Foo<int> result;
584             result.x = foo.y;
585             result.y = foo.x;
586             return result;
587         }
588     `);
589     let structType = TypeRef.instantiate(program.types.get("Foo"), [program.intrinsics.int32]);
590     let buffer = new EBuffer(2);
591     buffer.set(0, 62);
592     buffer.set(1, 24);
593     let result = callFunction(program, "foo", [], [new TypedValue(structType, new EPtr(buffer, 0))]);
594     let x = result.ePtr.get(0);
595     let y = result.ePtr.get(1);
596     if (x != 24)
597         throw new Error("Wrong result for x: " + x + " (y = " + y + ")");
598     if (y != 62)
599         throw new Error("Wrong result for y: " + y + " (x + " + x + ")");
600 }
601
602 function TEST_doubleGenericCallsDoubleGeneric()
603 {
604     doPrep(`
605         void foo<T, U>(T, U) { }
606         void bar<V, W>(V x, W y) { foo(x, y); }
607     `);
608 }
609
610 function TEST_doubleGenericCallsSingleGeneric()
611 {
612     checkFail(
613         () => doPrep(`
614             void foo<T>(T, T) { }
615             void bar<V, W>(V x, W y) { foo(x, y); }
616         `),
617         (e) => e instanceof WTypeError);
618 }
619
620 function TEST_loadNull()
621 {
622     checkFail(
623         () => doPrep(`
624             void sink<T>(T) { }
625             void foo() { sink(^null); }
626         `),
627         (e) => e instanceof WTypeError && e.message.indexOf("Type passed to dereference is not a pointer: null") != -1);
628 }
629
630 function TEST_storeNull()
631 {
632     checkFail(
633         () => doPrep(`
634             void foo() { ^null = 42; }
635         `),
636         (e) => e instanceof WTypeError && e.message.indexOf("Type passed to dereference is not a pointer: null") != -1);
637 }
638
639 function TEST_returnNull()
640 {
641     let program = doPrep(`
642         thread int^ foo() { return null; }
643     `);
644     let result = callFunction(program, "foo", [], []);
645     if (!result.type.isPtr)
646         throw new Error("Return type is not a pointer: " + result.type);
647     if (!result.type.elementType.equals(program.intrinsics.int32))
648         throw new Error("Return type is not a pointer to an int: " + result.type);
649     if (result.value != null)
650         throw new Error("Return value is not null: " + result.value);
651 }
652
653 function TEST_dereferenceDefaultNull()
654 {
655     let program = doPrep(`
656         int foo()
657         {
658             thread int^ p;
659             return ^p;
660         }
661     `);
662     checkFail(
663         () => callFunction(program, "foo", [], []),
664         (e) => e instanceof WTrapError);
665 }
666
667 function TEST_defaultInitializedNull()
668 {
669     let program = doPrep(`
670         int foo()
671         {
672             thread int^ p = null;;
673             return ^p;
674         }
675     `);
676     checkFail(
677         () => callFunction(program, "foo", [], []),
678         (e) => e instanceof WTrapError);
679 }
680
681 function TEST_passNullToPtrMonomorphic()
682 {
683     let program = doPrep(`
684         int foo(thread int^ ptr)
685         {
686             return ^ptr;
687         }
688         int bar()
689         {
690             return foo(null);
691         }
692     `);
693     checkFail(
694         () => callFunction(program, "bar", [], []),
695         (e) => e instanceof WTrapError);
696 }
697
698 function TEST_passNullToPtrPolymorphic()
699 {
700     checkFail(
701         () => doPrep(`
702             T foo<T>(thread T^ ptr)
703             {
704                 return ^ptr;
705             }
706             int bar()
707             {
708                 return foo(null);
709             }
710         `),
711         (e) => e instanceof WTypeError);
712 }
713
714 function TEST_passNullToPolymorphic()
715 {
716     checkFail(
717         () => doPrep(`
718             T foo<T>(T ptr)
719             {
720                 return ptr;
721             }
722             int bar()
723             {
724                 return foo(null);
725             }
726         `),
727         (e) => e instanceof WTypeError);
728 }
729
730 function TEST_loadNullArrayRef()
731 {
732     checkFail(
733         () => doPrep(`
734             void sink<T>(T) { }
735             void foo() { sink(null[0u]); }
736         `),
737         (e) => e instanceof WTypeError && e.message.indexOf("Did not find function for call") != -1);
738 }
739
740 function TEST_storeNullArrayRef()
741 {
742     checkFail(
743         () => doPrep(`
744             void foo() { null[0u] = 42; }
745         `),
746         (e) => e instanceof WTypeError && e.message.indexOf("Did not find function for call") != -1);
747 }
748
749 function TEST_returnNullArrayRef()
750 {
751     let program = doPrep(`
752         thread int[] foo() { return null; }
753     `);
754     let result = callFunction(program, "foo", [], []);
755     if (!result.type.isArrayRef)
756         throw new Error("Return type is not an array reference: " + result.type);
757     if (!result.type.elementType.equals(program.intrinsics.int32))
758         throw new Error("Return type is not an int array reference: " + result.type);
759     if (result.value != null)
760         throw new Error("Return value is not null: " + result.value);
761 }
762
763 function TEST_dereferenceDefaultNullArrayRef()
764 {
765     let program = doPrep(`
766         int foo()
767         {
768             thread int[] p;
769             return p[0u];
770         }
771     `);
772     checkFail(
773         () => callFunction(program, "foo", [], []),
774         (e) => e instanceof WTrapError);
775 }
776
777 function TEST_defaultInitializedNullArrayRef()
778 {
779     let program = doPrep(`
780         int foo()
781         {
782             thread int[] p = null;
783             return p[0u];
784         }
785     `);
786     checkFail(
787         () => callFunction(program, "foo", [], []),
788         (e) => e instanceof WTrapError);
789 }
790
791 function TEST_defaultInitializedNullArrayRefIntLiteral()
792 {
793     let program = doPrep(`
794         int foo()
795         {
796             thread int[] p = null;
797             return p[0];
798         }
799     `);
800     checkFail(
801         () => callFunction(program, "foo", [], []),
802         (e) => e instanceof WTrapError);
803 }
804
805 function TEST_passNullToPtrMonomorphicArrayRef()
806 {
807     let program = doPrep(`
808         int foo(thread int[] ptr)
809         {
810             return ptr[0u];
811         }
812         int bar()
813         {
814             return foo(null);
815         }
816     `);
817     checkFail(
818         () => callFunction(program, "bar", [], []),
819         (e) => e instanceof WTrapError);
820 }
821
822 function TEST_passNullToPtrPolymorphicArrayRef()
823 {
824     checkFail(
825         () => doPrep(`
826             T foo<T>(thread T[] ptr)
827             {
828                 return ptr[0u];
829             }
830             int bar()
831             {
832                 return foo(null);
833             }
834         `),
835         (e) => e instanceof WTypeError);
836 }
837
838 function TEST_returnIntLiteralUint()
839 {
840     let program = doPrep("uint foo() { return 42; }");
841     checkNumber(program, callFunction(program, "foo", [], []), 42);
842 }
843
844 function TEST_returnIntLiteralDouble()
845 {
846     let program = doPrep("double foo() { return 42; }");
847     checkNumber(program, callFunction(program, "foo", [], []), 42);
848 }
849
850 function TEST_badIntLiteralForInt()
851 {
852     checkFail(
853         () => doPrep("void foo() { int x = 3000000000; }"),
854         (e) => e instanceof WTypeError);
855 }
856
857 function TEST_badIntLiteralForUint()
858 {
859     checkFail(
860         () => doPrep("void foo() { uint x = 5000000000; }"),
861         (e) => e instanceof WTypeError);
862 }
863
864 function TEST_badIntLiteralForDouble()
865 {
866     checkFail(
867         () => doPrep("void foo() { double x = 5000000000000000000000000000000000000; }"),
868         (e) => e instanceof WSyntaxError);
869 }
870
871 function TEST_passNullAndNotNull()
872 {
873     let program = doPrep(`
874         T bar<T:primitive>(device T^ p, device T^)
875         {
876             return ^p;
877         }
878         int foo(device int^ p)
879         {
880             return bar(p, null);
881         }
882     `);
883     let buffer = new EBuffer(1);
884     buffer.set(0, 13);
885     checkInt(program, callFunction(program, "foo", [], [TypedValue.box(new PtrType(null, "device", program.intrinsics.int32), new EPtr(buffer, 0))]), 13);
886 }
887
888 function TEST_passNullAndNotNullFullPoly()
889 {
890     let program = doPrep(`
891         T bar<T:primitive>(T p, T)
892         {
893             return p;
894         }
895         int foo(device int^ p)
896         {
897             return ^bar(p, null);
898         }
899     `);
900     let buffer = new EBuffer(1);
901     buffer.set(0, 13);
902     checkInt(program, callFunction(program, "foo", [], [TypedValue.box(new PtrType(null, "device", program.intrinsics.int32), new EPtr(buffer, 0))]), 13);
903 }
904
905 function TEST_passNullAndNotNullFullPolyReverse()
906 {
907     let program = doPrep(`
908         T bar<T:primitive>(T, T p)
909         {
910             return p;
911         }
912         int foo(device int^ p)
913         {
914             return ^bar(null, p);
915         }
916     `);
917     let buffer = new EBuffer(1);
918     buffer.set(0, 13);
919     checkInt(program, callFunction(program, "foo", [], [TypedValue.box(new PtrType(null, "device", program.intrinsics.int32), new EPtr(buffer, 0))]), 13);
920 }
921
922 function TEST_nullTypeVariableUnify()
923 {
924     let left = new NullType(null);
925     let right = new TypeVariable(null, "T", null);
926     if (left.equals(right))
927         throw new Error("Should not be equal but are: " + left + " and " + right);
928     if (right.equals(left))
929         throw new Error("Should not be equal but are: " + left + " and " + right);
930     
931     function everyOrder(array, callback)
932     {
933         function recurse(array, callback, order)
934         {
935             if (!array.length)
936                 return callback.call(null, order);
937             
938             for (let i = 0; i < array.length; ++i) {
939                 let nextArray = array.concat();
940                 nextArray.splice(i, 1);
941                 recurse(nextArray, callback, order.concat([array[i]]));
942             }
943         }
944         
945         recurse(array, callback, []);
946     }
947     
948     function everyPair(things)
949     {
950         let result = [];
951         for (let i = 0; i < things.length; ++i) {
952             for (let j = 0; j < things.length; ++j) {
953                 if (i != j)
954                     result.push([things[i], things[j]]);
955             }
956         }
957         return result;
958     }
959     
960     everyOrder(
961         everyPair(["nullType", "variableType", "ptrType"]),
962         order => {
963             let types = {};
964             types.nullType = new NullType(null);
965             types.variableType = new TypeVariable(null, "T", null);
966             types.ptrType = new PtrType(null, "constant", new NativeType(null, "foo_t", true, []));
967             let unificationContext = new UnificationContext([types.variableType]);
968             for (let [leftName, rightName] of order) {
969                 let left = types[leftName];
970                 let right = types[rightName];
971                 let result = left.unify(unificationContext, right);
972                 if (!result)
973                     throw new Error("In order " + order + " cannot unify " + left + " with " + right);
974             }
975             if (!unificationContext.verify())
976                 throw new Error("In order " + order.map(value => "(" + value + ")") + " cannot verify");
977         });
978 }
979
980 function TEST_doubleNot()
981 {
982     let program = doPrep(`
983         bool foo(bool x)
984         {
985             return !!x;
986         }
987     `);
988     checkBool(program, callFunction(program, "foo", [], [makeBool(program, true)]), true);
989     checkBool(program, callFunction(program, "foo", [], [makeBool(program, false)]), false);
990 }
991
992 function TEST_simpleRecursion()
993 {
994     checkFail(
995         () => doPrep(`
996             void foo<T>(T x)
997             {
998                 foo(&x);
999             }
1000         `),
1001         (e) => e instanceof WTypeError);
1002 }
1003
1004 function TEST_protocolMonoSigPolyDef()
1005 {
1006     let program = doPrep(`
1007         struct IntAnd<T> {
1008             int first;
1009             T second;
1010         }
1011         IntAnd<T> intAnd<T>(int first, T second)
1012         {
1013             IntAnd<T> result;
1014             result.first = first;
1015             result.second = second;
1016             return result;
1017         }
1018         protocol IntAndable {
1019             IntAnd<int> intAnd(IntAndable, int);
1020         }
1021         int foo<T:IntAndable>(T first, int second)
1022         {
1023             IntAnd<int> result = intAnd(first, second);
1024             return result.first + result.second;
1025         }
1026     `);
1027     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 54), makeInt(program, 12)]), 54 + 12);
1028 }
1029
1030 function TEST_protocolPolySigPolyDef()
1031 {
1032     let program = doPrep(`
1033         struct IntAnd<T> {
1034             int first;
1035             T second;
1036         }
1037         IntAnd<T> intAnd<T>(int first, T second)
1038         {
1039             IntAnd<T> result;
1040             result.first = first;
1041             result.second = second;
1042             return result;
1043         }
1044         protocol IntAndable {
1045             IntAnd<T> intAnd<T>(IntAndable, T);
1046         }
1047         int foo<T:IntAndable>(T first, int second)
1048         {
1049             IntAnd<int> result = intAnd(first, second);
1050             return result.first + result.second;
1051         }
1052     `);
1053     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 54), makeInt(program, 12)]), 54 + 12);
1054 }
1055
1056 function TEST_protocolDoublePolySigDoublePolyDef()
1057 {
1058     let program = doPrep(`
1059         struct IntAnd<T, U> {
1060             int first;
1061             T second;
1062             U third;
1063         }
1064         IntAnd<T, U> intAnd<T, U>(int first, T second, U third)
1065         {
1066             IntAnd<T, U> result;
1067             result.first = first;
1068             result.second = second;
1069             result.third = third;
1070             return result;
1071         }
1072         protocol IntAndable {
1073             IntAnd<T, U> intAnd<T, U>(IntAndable, T, U);
1074         }
1075         int foo<T:IntAndable>(T first, int second, int third)
1076         {
1077             IntAnd<int, int> result = intAnd(first, second, third);
1078             return result.first + result.second + result.third;
1079         }
1080     `);
1081     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 54), makeInt(program, 12), makeInt(program, 39)]), 54 + 12 + 39);
1082 }
1083
1084 function TEST_protocolDoublePolySigDoublePolyDefExplicit()
1085 {
1086     let program = doPrep(`
1087         struct IntAnd<T, U> {
1088             int first;
1089             T second;
1090             U third;
1091         }
1092         IntAnd<T, U> intAnd<T, U>(int first, T second, U third)
1093         {
1094             IntAnd<T, U> result;
1095             result.first = first;
1096             result.second = second;
1097             result.third = third;
1098             return result;
1099         }
1100         protocol IntAndable {
1101             IntAnd<T, U> intAnd<T, U>(IntAndable, T, U);
1102         }
1103         int foo<T:IntAndable>(T first, int second, int third)
1104         {
1105             IntAnd<int, int> result = intAnd<int, int>(first, second, third);
1106             return result.first + result.second + result.third;
1107         }
1108     `);
1109     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 54), makeInt(program, 12), makeInt(program, 39)]), 54 + 12 + 39);
1110 }
1111
1112 function TEST_variableShadowing()
1113 {
1114     let program = doPrep(`
1115         int foo()
1116         {
1117             int y;
1118             int x = 7;
1119             {
1120                 int x = 8;
1121                 y = x;
1122             }
1123             return y;
1124         }
1125     `);
1126     checkInt(program, callFunction(program, "foo", [], []), 8);
1127     program = doPrep(`
1128         int foo()
1129         {
1130             int y;
1131             int x = 7;
1132             {
1133                 int x = 8;
1134             }
1135             y = x;
1136             return y;
1137         }
1138     `);
1139     checkInt(program, callFunction(program, "foo", [], []), 7);
1140 }
1141
1142 function TEST_ifStatement()
1143 {
1144     let program = doPrep(`
1145         int foo(int x)
1146         {
1147             int y = 6;
1148             if (x == 7) {
1149                 y = 8;
1150             }
1151             return y;
1152         }
1153     `);
1154     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 3)]), 6);
1155     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 4)]), 6);
1156     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 5)]), 6);
1157     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 6)]), 6);
1158     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 7)]), 8);
1159     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 8)]), 6);
1160     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 9)]), 6);
1161 }
1162
1163 function TEST_ifElseStatement()
1164 {
1165     let program = doPrep(`
1166         int foo(int x)
1167         {
1168             int y = 6;
1169             if (x == 7) {
1170                 y = 8;
1171             } else {
1172                 y = 9;
1173             }
1174             return y;
1175         }
1176     `);
1177     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 3)]), 9);
1178     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 4)]), 9);
1179     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 5)]), 9);
1180     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 6)]), 9);
1181     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 7)]), 8);
1182     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 8)]), 9);
1183     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 9)]), 9);
1184 }
1185
1186 function TEST_ifElseIfStatement()
1187 {
1188     let program = doPrep(`
1189         int foo(int x)
1190         {
1191             int y = 6;
1192             if (x == 7) {
1193                 y = 8;
1194             } else if (x == 8) {
1195                 y = 9;
1196             }
1197             return y;
1198         }
1199     `);
1200     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 3)]), 6);
1201     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 4)]), 6);
1202     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 5)]), 6);
1203     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 6)]), 6);
1204     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 7)]), 8);
1205     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 8)]), 9);
1206     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 9)]), 6);
1207 }
1208
1209 function TEST_ifElseIfElseStatement()
1210 {
1211     let program = doPrep(`
1212         int foo(int x)
1213         {
1214             int y = 6;
1215             if (x == 7) {
1216                 y = 8;
1217             } else if (x == 8) {
1218                 y = 9;
1219             } else {
1220                 y = 10;
1221             }
1222             return y;
1223         }
1224     `);
1225     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 3)]), 10);
1226     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 4)]), 10);
1227     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 5)]), 10);
1228     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 6)]), 10);
1229     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 7)]), 8);
1230     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 8)]), 9);
1231     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 9)]), 10);
1232 }
1233
1234 function TEST_returnIf()
1235 {
1236     checkFail(
1237         () => doPrep(`
1238             int foo(int x)
1239             {
1240                 int y = 6;
1241                 if (x == 7) {
1242                     return y;
1243                 }
1244             }
1245         `),
1246         (e) => e instanceof WTypeError);
1247     checkFail(
1248         () => doPrep(`
1249             int foo(int x)
1250             {
1251                 int y = 6;
1252                 if (x == 7) {
1253                     return y;
1254                 } else {
1255                     y = 8;
1256                 }
1257             }
1258         `),
1259         (e) => e instanceof WTypeError);
1260     checkFail(
1261         () => doPrep(`
1262             int foo(int x)
1263             {
1264                 int y = 6;
1265                 if (x == 7) {
1266                     y = 8;
1267                 } else {
1268                     return y;
1269                 }
1270             }
1271         `),
1272         (e) => e instanceof WTypeError);
1273     let program = doPrep(`
1274         int foo(int x)
1275         {
1276             int y = 6;
1277             if (x == 7) {
1278                 return 8;
1279             } else {
1280                 return 10;
1281             }
1282         }
1283     `);
1284     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 3)]), 10);
1285     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 4)]), 10);
1286     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 5)]), 10);
1287     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 6)]), 10);
1288     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 7)]), 8);
1289     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 8)]), 10);
1290     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 9)]), 10);
1291     checkFail(
1292         () => doPrep(`
1293             int foo(int x)
1294             {
1295                 int y = 6;
1296                 if (x == 7) {
1297                     return 8;
1298                 } else if (x == 9) {
1299                     return 10;
1300                 }
1301             }
1302         `),
1303         (e) => e instanceof WTypeError);
1304     program = doPrep(`
1305         int foo(int x)
1306         {
1307             int y = 6;
1308             if (x == 7) {
1309                 return 8;
1310             } else {
1311                 y = 9;
1312             }
1313             return y;
1314         }
1315     `);
1316     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 3)]), 9);
1317     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 4)]), 9);
1318     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 5)]), 9);
1319     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 6)]), 9);
1320     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 7)]), 8);
1321     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 8)]), 9);
1322     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 9)]), 9);
1323     checkFail(
1324         () => doPrep(`
1325             int foo(int x)
1326             {
1327                 int y = 6;
1328                 if (x == 7) {
1329                     return 8;
1330                 } else {
1331                     return 10;
1332                 }
1333                 return 11;
1334             }
1335         `),
1336         (e) => e instanceof WTypeError);
1337     program = doPrep(`
1338         int foo(int x)
1339         {
1340             int y = 6;
1341             if (x == 7)
1342                 int y = 8;
1343             return y;
1344         }
1345     `);
1346     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 7)]), 6);
1347 }
1348
1349 function TEST_simpleWhile()
1350 {
1351     let program = doPrep(`
1352         int foo(int x)
1353         {
1354             while (x < 13)
1355                 x = x * 2;
1356             return x;
1357         }
1358     `);
1359     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 1)]), 16);
1360 }
1361
1362 function TEST_protocolMonoPolySigDoublePolyDefExplicit()
1363 {
1364     checkFail(
1365         () => {
1366             let program = doPrep(`
1367                 struct IntAnd<T, U> {
1368                     int first;
1369                     T second;
1370                     U third;
1371                 }
1372                 IntAnd<T, U> intAnd<T, U>(int first, T second, U third)
1373                 {
1374                     IntAnd<T, U> result;
1375                     result.first = first;
1376                     result.second = second;
1377                     result.third = third;
1378                     return result;
1379                 }
1380                 protocol IntAndable {
1381                     IntAnd<T, int> intAnd<T>(IntAndable, T, int);
1382                 }
1383                 int foo<T:IntAndable>(T first, int second, int third)
1384                 {
1385                     IntAnd<int, int> result = intAnd<int>(first, second, third);
1386                     return result.first + result.second + result.third;
1387                 }
1388             `);
1389             callFunction(program, "foo", [], [makeInt(program, 54), makeInt(program, 12), makeInt(program, 39)]);
1390         },
1391         (e) => e instanceof WTypeError);
1392 }
1393
1394 function TEST_ambiguousOverloadSimple()
1395 {
1396     checkFail(
1397         () => doPrep(`
1398             void foo<T>(int, T) { }
1399             void foo<T>(T, int) { }
1400             void bar(int a, int b) { foo(a, b); }
1401         `),
1402         (e) => e instanceof WTypeError);
1403 }
1404
1405 function TEST_ambiguousOverloadOverlapping()
1406 {
1407     checkFail(
1408         () => doPrep(`
1409             void foo<T>(int, T) { }
1410             void foo<T>(T, T) { }
1411             void bar(int a, int b) { foo(a, b); }
1412         `),
1413         (e) => e instanceof WTypeError);
1414 }
1415
1416 function TEST_ambiguousOverloadTieBreak()
1417 {
1418     doPrep(`
1419         void foo<T>(int, T) { }
1420         void foo<T>(T, T) { }
1421         void foo(int, int) { }
1422         void bar(int a, int b) { foo(a, b); }
1423     `);
1424 }
1425
1426 function TEST_intOverloadResolution()
1427 {
1428     let program = doPrep(`
1429         int foo(int) { return 1; }
1430         int foo(uint) { return 2; }
1431         int foo(double) { return 3; }
1432         int bar() { return foo(42); }
1433     `);
1434     checkInt(program, callFunction(program, "bar", [], []), 1);
1435 }
1436
1437 function TEST_intOverloadResolutionReverseOrder()
1438 {
1439     let program = doPrep(`
1440         int foo(double) { return 3; }
1441         int foo(uint) { return 2; }
1442         int foo(int) { return 1; }
1443         int bar() { return foo(42); }
1444     `);
1445     checkInt(program, callFunction(program, "bar", [], []), 1);
1446 }
1447
1448 function TEST_intOverloadResolutionGeneric()
1449 {
1450     let program = doPrep(`
1451         int foo(int) { return 1; }
1452         int foo<T>(T) { return 2; }
1453         int bar() { return foo(42); }
1454     `);
1455     checkInt(program, callFunction(program, "bar", [], []), 1);
1456 }
1457
1458 function TEST_intLiteralGeneric()
1459 {
1460     checkFail(
1461         () => doPrep(`
1462             int foo<T>(T) { return 1; }
1463             int bar() { return foo(42); }
1464         `),
1465         (e) => e instanceof WTypeError);
1466 }
1467
1468 function TEST_intLiteralGeneric()
1469 {
1470     let program = doPrep(`
1471         T foo<T>(T x) { return x; }
1472         int bar() { return foo(int(42)); }
1473     `);
1474     checkInt(program, callFunction(program, "bar", [], []), 42);
1475 }
1476
1477 function TEST_simpleConstexpr()
1478 {
1479     let program = doPrep(`
1480         int foo<int a>(int b)
1481         {
1482             return a + b;
1483         }
1484         int bar(int b)
1485         {
1486             return foo<42>(b);
1487         }
1488     `);
1489     checkInt(program, callFunction(program, "bar", [], [makeInt(program, 58)]), 58 + 42);
1490 }
1491
1492 function TEST_break()
1493 {
1494     let program = doPrep(`
1495         int foo(int x)
1496         {
1497             while (true) {
1498                 x = x * 2;
1499                 if (x >= 7)
1500                     break;
1501             }
1502             return x;
1503         }
1504     `);
1505     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 1)]), 8);
1506     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 10)]), 20);
1507     program = doPrep(`
1508         int foo(int x)
1509         {
1510             while (true) {
1511                 while (true) {
1512                     x = x * 2;
1513                     if (x >= 7)
1514                         break;
1515                 }
1516                 x = x - 1;
1517                 break;
1518             }
1519             return x;
1520             
1521         }
1522     `);
1523     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 1)]), 7);
1524     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 10)]), 19);
1525     checkFail(
1526         () => doPrep(`
1527             int foo(int x)
1528             {
1529                 while (true) {
1530                     {
1531                         break;
1532                     }
1533                     x = x + 1;
1534                 }
1535                 return x;
1536             }
1537         `),
1538         (e) => e instanceof WTypeError);
1539     checkFail(
1540         () => doPrep(`
1541             int foo(int x)
1542             {
1543                 break;
1544                 return x;
1545             }
1546         `),
1547         (e) => e instanceof WTypeError);
1548     program = doPrep(`
1549             int foo(int x)
1550             {
1551                 while (true) {
1552                     if (x == 7) {
1553                         break;
1554                     }
1555                     x = x + 1;
1556                 }
1557                 return x;
1558             }
1559     `);
1560     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 1)]), 7);
1561     program = doPrep(`
1562             int foo(int x)
1563             {
1564                 while (true) {
1565                     break;
1566                 }
1567                 return x;
1568             }
1569     `);
1570     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 1)]), 1);
1571     program = doPrep(`
1572             int foo()
1573             {
1574                 while (true) {
1575                     return 7;
1576                 }
1577             }
1578     `);
1579     checkInt(program, callFunction(program, "foo", [], []), 7);
1580     checkFail(
1581         () => doPrep(`
1582             int foo(int x)
1583             {
1584                 while(true) {
1585                     break;
1586                     return 7;
1587                 }
1588             }
1589         `),
1590         (e) => e instanceof WTypeError);
1591 }
1592
1593 function TEST_continue()
1594 {
1595     let program = doPrep(`
1596         int foo(int x)
1597         {
1598             while (x < 10) {
1599                 if (x == 8) {
1600                     x = x + 1;
1601                     continue;
1602                 }
1603                 x = x * 2;
1604             }
1605             return x;
1606         }
1607     `);
1608     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 1)]), 18);
1609     checkFail(
1610         () => doPrep(`
1611             int foo(int x)
1612             {
1613                 continue;
1614                 return x;
1615                 
1616             }
1617         `),
1618         (e) => e instanceof WTypeError);
1619 }
1620
1621 function TEST_doWhile()
1622 {
1623     let program = doPrep(`
1624         int foo(int x)
1625         {
1626             int y = 7;
1627             do {
1628                 y = 8;
1629                 break;
1630             } while (x < 10);
1631             return y;
1632         }
1633     `);
1634     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 1)]), 8);
1635     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 11)]), 8);
1636     program = doPrep(`
1637         int foo(int x)
1638         {
1639             int y = 7;
1640             do {
1641                 y = 8;
1642                 break;
1643             } while (y == 7);
1644             return y;
1645         }
1646     `);
1647     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 1)]), 8);
1648     program = doPrep(`
1649         int foo(int x)
1650         {
1651             int sum = 0;
1652             do {
1653                 if (x == 11) {
1654                     x = 15;
1655                     continue;
1656                 }
1657                 sum = sum + x;
1658                 x = x + 1;
1659             } while (x < 13);
1660             return sum;
1661         }
1662     `);
1663     checkInt(program, callFunction(program, "foo", [], [makeInt(program, 9)]), 19);
1664 }
1665
1666 let filter = /.*/; // run everything by default
1667 if (this["arguments"]) {
1668     for (let i = 0; i < arguments.length; i++) {
1669         switch (arguments[0]) {
1670         case "--filter":
1671             filter = new RegExp(arguments[++i]);
1672             break;
1673         default:
1674             throw new Error("Unknown argument: ", arguments[i]);
1675         }
1676     }
1677 }
1678
1679 function doTest(object)
1680 {
1681     let before = preciseTime();
1682
1683     for (let s in object) {
1684         if (s.startsWith("TEST_") && s.match(filter)) {
1685             print(s + "...");
1686             object[s]();
1687             print("    OK!");
1688         }
1689     }
1690
1691     let after = preciseTime();
1692     
1693     print("That took " + (after - before) * 1000 + " ms.");
1694 }
1695
1696 if (!this.window)
1697     doTest(this);