[WHLSL] Call expressions shouldn't have type arguments
[WebKit-https.git] / Tools / WebGPUShadingLanguageRI / Test.js
1 /*
2  * Copyright (C) 2018 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("pre");
30         document.getElementById("messages").appendChild(span);
31         span.innerText = text;
32         window.scrollTo(0,document.body.scrollHeight);
33     };
34     this.preciseTime = () => performance.now() / 1000;
35 } else
36     load("All.js");
37
38 function doPrep(code)
39 {
40     return prepare("/internal/test", 0, code);
41 }
42
43 function doLex(code)
44 {
45     let lexer = new Lexer("/internal/test", "native", 0, code);
46     var result = [];
47     for (;;) {
48         let next = lexer.next();
49         if (!next)
50             return result;
51         result.push(next);
52     }
53     return result;
54 }
55
56 function makeInt(program, value)
57 {
58     return TypedValue.box(program.intrinsics.int, value);
59 }
60
61 function makeUint(program, value)
62 {
63     return TypedValue.box(program.intrinsics.uint, value);
64 }
65
66 function makeUchar(program, value)
67 {
68     return TypedValue.box(program.intrinsics.uchar, value);
69 }
70
71 function makeBool(program, value)
72 {
73     return TypedValue.box(program.intrinsics.bool, value);
74 }
75
76 function makeFloat(program, value)
77 {
78     return TypedValue.box(program.intrinsics.float, value);
79 }
80
81 function makeEnum(program, enumName, value)
82 {
83     let enumType = program.types.get(enumName);
84     if (!enumType)
85         throw new Error("No type named " + enumName);
86     let enumMember = enumType.memberByName(value);
87     if (!enumMember)
88         throw new Error("No member named " + enumMember + " in " + enumType);
89     return TypedValue.box(enumType, enumMember.value.unifyNode.valueForSelectedType);
90 }
91
92 function checkNumber(program, result, expected)
93 {
94     if (!result.type.unifyNode.isNumber)
95         throw new Error("Wrong result type; result: " + result);
96     if (result.value != expected)
97         throw new Error("Wrong result: " + result.value + " (expected " + expected + ")");
98 }
99
100 function checkInt(program, result, expected)
101 {
102     if (!result.type.equals(program.intrinsics.int))
103         throw new Error("Wrong result type; result: " + result);
104     checkNumber(program, result, expected);
105 }
106
107 function checkEnum(program, result, expected)
108 {
109     if (!(result.type.unifyNode instanceof EnumType))
110         throw new Error("Wrong result type; result: " + result);
111     if (result.value != expected)
112         throw new Error("Wrong result: " + result.value + " (expected " + expected + ")");
113 }
114
115 function checkUint(program, result, expected)
116 {
117     if (!result.type.equals(program.intrinsics.uint))
118         throw new Error("Wrong result type: " + result.type);
119     if (result.value != expected)
120         throw new Error("Wrong result: " + result.value + " (expected " + expected + ")");
121 }
122
123 function checkUchar(program, result, expected)
124 {
125     if (!result.type.equals(program.intrinsics.uchar))
126         throw new Error("Wrong result type: " + result.type);
127     if (result.value != expected)
128         throw new Error("Wrong result: " + result.value + " (expected " + expected + ")");
129 }
130
131 function checkBool(program, result, expected)
132 {
133     if (!result.type.equals(program.intrinsics.bool))
134         throw new Error("Wrong result type: " + result.type);
135     if (result.value != expected)
136         throw new Error("Wrong result: " + result.value + " (expected " + expected + ")");
137 }
138
139 function checkFloat(program, result, expected)
140 {
141     if (!result.type.equals(program.intrinsics.float))
142         throw new Error("Wrong result type: " + result.type);
143     if (result.value != expected)
144         throw new Error("Wrong result: " + result.value + " (expected " + expected + ")");
145 }
146
147 function checkLexerToken(result, expectedIndex, expectedKind, expectedText)
148 {
149     if (result._index != expectedIndex)
150         throw new Error("Wrong lexer index; result: " + result._index + " (expected " + expectedIndex + ")");
151     if (result._kind != expectedKind)
152         throw new Error("Wrong lexer kind; result: " + result._kind + " (expected " + expectedKind + ")");
153     if (result._text != expectedText)
154         throw new Error("Wrong lexer text; result: " + result._text + " (expected " + expectedText + ")");
155 }
156
157 function checkFail(callback, predicate)
158 {
159     try {
160         callback();
161         throw new Error("Did not throw exception");
162     } catch (e) {
163         if (predicate(e)) {
164             print("    Caught: " + e);
165             return;
166         }
167         throw e;
168     }
169 }
170
171 let tests;
172 let okToTest = false;
173
174 tests = new Proxy({}, {
175     set(target, property, value, receiver)
176     {
177         if (property in target)
178             throw new Error("Trying to declare duplicate test: " + property);
179         target[property] = value;
180         return true;
181     }
182 });
183
184 tests.commentParsing = function() {
185     let program = doPrep(`
186         /* this comment
187         runs over multiple lines */
188         bool foo() { return true; }
189     `);
190     checkBool(program, callFunction(program, "foo", []), true);
191
192     checkFail(
193         () => doPrep(`
194         /* this comment
195         runs over multiple lines
196         bool foo() { return true; }
197         `),
198         (e) => e instanceof WSyntaxError);
199 }
200
201 tests.literalBool = function() {
202     let program = doPrep("bool foo() { return true; }");
203     checkBool(program, callFunction(program, "foo", []), true);
204 }
205
206 tests.identityBool = function() {
207     let program = doPrep("bool foo(bool x) { return x; }");
208     checkBool(program, callFunction(program, "foo", [makeBool(program, true)]), true);
209     checkBool(program, callFunction(program, "foo", [makeBool(program, false)]), false);
210 }
211
212 tests.intSimpleMath = function() {
213     let program = doPrep("int foo(int x, int y) { return x + y; }");
214     checkInt(program, callFunction(program, "foo", [makeInt(program, 7), makeInt(program, 5)]), 12);
215     program = doPrep("int foo(int x, int y) { return x - y; }");
216     checkInt(program, callFunction(program, "foo", [makeInt(program, 7), makeInt(program, 5)]), 2);
217     checkInt(program, callFunction(program, "foo", [makeInt(program, 5), makeInt(program, 7)]), -2);
218     program = doPrep("int foo(int x, int y) { return x * y; }");
219     checkInt(program, callFunction(program, "foo", [makeInt(program, 7), makeInt(program, 5)]), 35);
220     checkInt(program, callFunction(program, "foo", [makeInt(program, 7), makeInt(program, -5)]), -35);
221     program = doPrep("int foo(int x, int y) { return x / y; }");
222     checkInt(program, callFunction(program, "foo", [makeInt(program, 7), makeInt(program, 2)]), 3);
223     checkInt(program, callFunction(program, "foo", [makeInt(program, 7), makeInt(program, -2)]), -3);
224 }
225
226 tests.uintSimpleMath = function() {
227     let program = doPrep("uint foo(uint x, uint y) { return x + y; }");
228     checkUint(program, callFunction(program, "foo", [makeUint(program, 7), makeUint(program, 5)]), 12);
229     program = doPrep("uint foo(uint x, uint y) { return x - y; }");
230     checkUint(program, callFunction(program, "foo", [makeUint(program, 7), makeUint(program, 5)]), 2);
231     checkUint(program, callFunction(program, "foo", [makeUint(program, 5), makeUint(program, 7)]), 4294967294);
232     program = doPrep("uint foo(uint x, uint y) { return x * y; }");
233     checkUint(program, callFunction(program, "foo", [makeUint(program, 7), makeUint(program, 5)]), 35);
234     program = doPrep("uint foo(uint x, uint y) { return x / y; }");
235     checkUint(program, callFunction(program, "foo", [makeUint(program, 7), makeUint(program, 2)]), 3);
236 }
237
238 tests.ucharSimpleMath = function() {
239     let program = doPrep("uchar foo(uchar x, uchar y) { return x + y; }");
240     checkUchar(program, callFunction(program, "foo", [makeUchar(program, 7), makeUchar(program, 5)]), 12);
241     program = doPrep("uchar foo(uchar x, uchar y) { return x - y; }");
242     checkUchar(program, callFunction(program, "foo", [makeUchar(program, 7), makeUchar(program, 5)]), 2);
243     checkUchar(program, callFunction(program, "foo", [makeUchar(program, 5), makeUchar(program, 7)]), 254);
244     program = doPrep("uchar foo(uchar x, uchar y) { return x * y; }");
245     checkUchar(program, callFunction(program, "foo", [makeUchar(program, 7), makeUchar(program, 5)]), 35);
246     program = doPrep("uchar foo(uchar x, uchar y) { return x / y; }");
247     checkUchar(program, callFunction(program, "foo", [makeUchar(program, 7), makeUchar(program, 2)]), 3);
248 }
249
250 tests.equality = function() {
251     let program = doPrep("bool foo(uint x, uint y) { return x == y; }");
252     checkBool(program, callFunction(program, "foo", [makeUint(program, 7), makeUint(program, 5)]), false);
253     checkBool(program, callFunction(program, "foo", [makeUint(program, 7), makeUint(program, 7)]), true);
254     program = doPrep("bool foo(uchar x, uchar y) { return x == y; }");
255     checkBool(program, callFunction(program, "foo", [makeUchar(program, 7), makeUchar(program, 5)]), false);
256     checkBool(program, callFunction(program, "foo", [makeUchar(program, 7), makeUchar(program, 7)]), true);
257     program = doPrep("bool foo(int x, int y) { return x == y; }");
258     checkBool(program, callFunction(program, "foo", [makeInt(program, 7), makeInt(program, 5)]), false);
259     checkBool(program, callFunction(program, "foo", [makeInt(program, 7), makeInt(program, 7)]), true);
260     program = doPrep("bool foo(bool x, bool y) { return x == y; }");
261     checkBool(program, callFunction(program, "foo", [makeBool(program, false), makeBool(program, true)]), false);
262     checkBool(program, callFunction(program, "foo", [makeBool(program, true), makeBool(program, false)]), false);
263     checkBool(program, callFunction(program, "foo", [makeBool(program, false), makeBool(program, false)]), true);
264     checkBool(program, callFunction(program, "foo", [makeBool(program, true), makeBool(program, true)]), true);
265 }
266
267 tests.logicalNegation = function()
268 {
269     let program = doPrep("bool foo(bool x) { return !x; }");
270     checkBool(program, callFunction(program, "foo", [makeBool(program, true)]), false);
271     checkBool(program, callFunction(program, "foo", [makeBool(program, false)]), true);
272 }
273
274 tests.notEquality = function() {
275     let program = doPrep("bool foo(uint x, uint y) { return x != y; }");
276     checkBool(program, callFunction(program, "foo", [makeUint(program, 7), makeUint(program, 5)]), true);
277     checkBool(program, callFunction(program, "foo", [makeUint(program, 7), makeUint(program, 7)]), false);
278     program = doPrep("bool foo(uchar x, uchar y) { return x != y; }");
279     checkBool(program, callFunction(program, "foo", [makeUchar(program, 7), makeUchar(program, 5)]), true);
280     checkBool(program, callFunction(program, "foo", [makeUchar(program, 7), makeUchar(program, 7)]), false);
281     program = doPrep("bool foo(int x, int y) { return x != y; }");
282     checkBool(program, callFunction(program, "foo", [makeInt(program, 7), makeInt(program, 5)]), true);
283     checkBool(program, callFunction(program, "foo", [makeInt(program, 7), makeInt(program, 7)]), false);
284     program = doPrep("bool foo(bool x, bool y) { return x != y; }");
285     checkBool(program, callFunction(program, "foo", [makeBool(program, false), makeBool(program, true)]), true);
286     checkBool(program, callFunction(program, "foo", [makeBool(program, true), makeBool(program, false)]), true);
287     checkBool(program, callFunction(program, "foo", [makeBool(program, false), makeBool(program, false)]), false);
288     checkBool(program, callFunction(program, "foo", [makeBool(program, true), makeBool(program, true)]), false);
289 }
290
291 tests.equalityTypeFailure = function()
292 {
293     checkFail(
294         () => doPrep("bool foo(int x, uint y) { return x == y; }"),
295         (e) => e instanceof WTypeError && e.message.indexOf("/internal/test:1") != -1);
296 }
297
298 tests.generalNegation = function()
299 {
300     let program = doPrep("bool foo(int x) { return !x; }");
301     checkBool(program, callFunction(program, "foo", [makeInt(program, 7)]), false);
302     checkBool(program, callFunction(program, "foo", [makeInt(program, 0)]), true);
303 }
304
305 tests.add1 = function() {
306     let program = doPrep("int foo(int x) { return x + 1; }");
307     checkInt(program, callFunction(program, "foo", [makeInt(program, 42)]), 43);
308 }
309
310 tests.nameResolutionFailure = function()
311 {
312     checkFail(
313         () => doPrep("int foo(int x) { return x + y; }"),
314         (e) => e instanceof WTypeError && e.message.indexOf("/internal/test:1") != -1);
315 }
316
317 tests.simpleVariable = function()
318 {
319     let program = doPrep(`
320         int foo(int p)
321         {
322             int result = p;
323             return result;
324         }
325     `);
326     checkInt(program, callFunction(program, "foo", [makeInt(program, 42)]), 42);
327 }
328
329 tests.simpleAssignment = function()
330 {
331     let program = doPrep(`
332         int foo(int p)
333         {
334             int result;
335             result = p;
336             return result;
337         }
338     `);
339     checkInt(program, callFunction(program, "foo", [makeInt(program, 42)]), 42);
340 }
341
342 tests.simpleDefault = function()
343 {
344     let program = doPrep(`
345         int foo()
346         {
347             int result;
348             return result;
349         }
350     `);
351     checkInt(program, callFunction(program, "foo", []), 0);
352 }
353
354 tests.simpleDereference = function()
355 {
356     let program = doPrep(`
357         int foo(device int* p)
358         {
359             return *p;
360         }
361     `);
362     let buffer = new EBuffer(1);
363     buffer.set(0, 13);
364     checkInt(program, callFunction(program, "foo", [TypedValue.box(new PtrType(externalOrigin, "device", program.intrinsics.int), new EPtr(buffer, 0))]), 13);
365 }
366
367 tests.dereferenceStore = function()
368 {
369     let program = doPrep(`
370         void foo(device int* p)
371         {
372             *p = 52;
373         }
374     `);
375     let buffer = new EBuffer(1);
376     buffer.set(0, 13);
377     callFunction(program, "foo", [TypedValue.box(new PtrType(externalOrigin, "device", program.intrinsics.int), new EPtr(buffer, 0))]);
378     if (buffer.get(0) != 52)
379         throw new Error("Expected buffer to contain 52 but it contains: " + buffer.get(0));
380 }
381
382 tests.simpleMakePtr = function()
383 {
384     let program = doPrep(`
385         thread int* foo()
386         {
387             int x = 42;
388             return &x;
389         }
390     `);
391     let result = callFunction(program, "foo", []);
392     if (!result.type.isPtr)
393         throw new Error("Return type is not a pointer: " + result.type);
394     if (!result.type.elementType.equals(program.intrinsics.int))
395         throw new Error("Return type is not a pointer to an int: " + result.type);
396     if (!(result.value instanceof EPtr))
397         throw new Error("Return value is not an EPtr: " + result.value);
398     let value = result.value.loadValue();
399     if (value != 42)
400         throw new Error("Expected 42 but got: " + value);
401 }
402
403 tests.threadArrayLoad = function()
404 {
405     let program = doPrep(`
406         int foo(thread int[] array)
407         {
408             return array[0u];
409         }
410     `);
411     let buffer = new EBuffer(1);
412     buffer.set(0, 89);
413     let result = callFunction(program, "foo", [TypedValue.box(new ArrayRefType(externalOrigin, "thread", program.intrinsics.int), new EArrayRef(new EPtr(buffer, 0), 1))]);
414     checkInt(program, result, 89);
415 }
416
417 tests.threadArrayLoadIntLiteral = function()
418 {
419     let program = doPrep(`
420         int foo(thread int[] array)
421         {
422             return array[0];
423         }
424     `);
425     let buffer = new EBuffer(1);
426     buffer.set(0, 89);
427     let result = callFunction(program, "foo", [TypedValue.box(new ArrayRefType(externalOrigin, "thread", program.intrinsics.int), new EArrayRef(new EPtr(buffer, 0), 1))]);
428     checkInt(program, result, 89);
429 }
430
431 tests.deviceArrayLoad = function()
432 {
433     let program = doPrep(`
434         int foo(device int[] array)
435         {
436             return array[0u];
437         }
438     `);
439     let buffer = new EBuffer(1);
440     buffer.set(0, 89);
441     let result = callFunction(program, "foo", [TypedValue.box(new ArrayRefType(externalOrigin, "device", program.intrinsics.int), new EArrayRef(new EPtr(buffer, 0), 1))]);
442     checkInt(program, result, 89);
443 }
444
445 tests.threadArrayStore = function()
446 {
447     let program = doPrep(`
448         void foo(thread int[] array, int value)
449         {
450             array[0u] = value;
451         }
452     `);
453     let buffer = new EBuffer(1);
454     buffer.set(0, 15);
455     let arrayRef = TypedValue.box(
456         new ArrayRefType(externalOrigin, "thread", program.intrinsics.int),
457         new EArrayRef(new EPtr(buffer, 0), 1));
458     callFunction(program, "foo", [arrayRef, makeInt(program, 65)]);
459     if (buffer.get(0) != 65)
460         throw new Error("Bad value stored into buffer (expected 65): " + buffer.get(0));
461     callFunction(program, "foo", [arrayRef, makeInt(program, -111)]);
462     if (buffer.get(0) != -111)
463         throw new Error("Bad value stored into buffer (expected -111): " + buffer.get(0));
464 }
465
466 tests.deviceArrayStore = function()
467 {
468     let program = doPrep(`
469         void foo(device int[] array, int value)
470         {
471             array[0u] = value;
472         }
473     `);
474     let buffer = new EBuffer(1);
475     buffer.set(0, 15);
476     let arrayRef = TypedValue.box(
477         new ArrayRefType(externalOrigin, "device", program.intrinsics.int),
478         new EArrayRef(new EPtr(buffer, 0), 1));
479     callFunction(program, "foo", [arrayRef, makeInt(program, 65)]);
480     if (buffer.get(0) != 65)
481         throw new Error("Bad value stored into buffer (expected 65): " + buffer.get(0));
482     callFunction(program, "foo", [arrayRef, makeInt(program, -111)]);
483     if (buffer.get(0) != -111)
484         throw new Error("Bad value stored into buffer (expected -111): " + buffer.get(0));
485 }
486
487 tests.deviceArrayStoreIntLiteral = function()
488 {
489     let program = doPrep(`
490         void foo(device int[] array, int value)
491         {
492             array[0] = value;
493         }
494     `);
495     let buffer = new EBuffer(1);
496     buffer.set(0, 15);
497     let arrayRef = TypedValue.box(
498         new ArrayRefType(externalOrigin, "device", program.intrinsics.int),
499         new EArrayRef(new EPtr(buffer, 0), 1));
500     callFunction(program, "foo", [arrayRef, makeInt(program, 65)]);
501     if (buffer.get(0) != 65)
502         throw new Error("Bad value stored into buffer (expected 65): " + buffer.get(0));
503     callFunction(program, "foo", [arrayRef, makeInt(program, -111)]);
504     if (buffer.get(0) != -111)
505         throw new Error("Bad value stored into buffer (expected -111): " + buffer.get(0));
506 }
507
508 tests.typeMismatchReturn = function()
509 {
510     checkFail(
511         () => doPrep(`
512             int foo()
513             {
514                 return 0u;
515             }
516         `),
517         (e) => e instanceof WTypeError);
518 }
519
520 tests.typeMismatchVariableDecl = function()
521 {
522     checkFail(
523         () => doPrep(`
524             void foo(uint x)
525             {
526                 int y = x;
527             }
528         `),
529         (e) => e instanceof WTypeError);
530 }
531
532 tests.typeMismatchAssignment = function()
533 {
534     checkFail(
535         () => doPrep(`
536             void foo(uint x)
537             {
538                 int y;
539                 y = x;
540             }
541         `),
542         (e) => e instanceof WTypeError);
543 }
544
545 tests.typeMismatchReturnParam = function()
546 {
547     checkFail(
548         () => doPrep(`
549             int foo(uint x)
550             {
551                 return x;
552             }
553         `),
554         (e) => e instanceof WTypeError);
555 }
556
557 tests.badAdd = function()
558 {
559     checkFail(
560         () => doPrep(`
561             void foo(int x, uint y)
562             {
563                 uint z = x + y;
564             }
565         `),
566         (e) => e instanceof WTypeError && e.message.indexOf("native int operator+(int,int)") != -1);
567 }
568
569 tests.lexerKeyword = function()
570 {
571     let result = doLex("ident for while 123 123u { } {asd asd{ 1a3 1.2 + 3.4 + 1. + .2 1.2f 0.f .3f && ||");
572     if (result.length != 25)
573         throw new Error("Lexer emitted an incorrect number of tokens (expected 23): " + result.length);
574     checkLexerToken(result[0],  0,  "identifier",    "ident");
575     checkLexerToken(result[1],  6,  "keyword",       "for");
576     checkLexerToken(result[2],  10, "keyword",       "while");
577     checkLexerToken(result[3],  16, "intLiteral",    "123");
578     checkLexerToken(result[4],  20, "uintLiteral",   "123u");
579     checkLexerToken(result[5],  25, "punctuation",   "{");
580     checkLexerToken(result[6],  27, "punctuation",   "}");
581     checkLexerToken(result[7],  29, "punctuation",   "{");
582     checkLexerToken(result[8],  30, "identifier",    "asd");
583     checkLexerToken(result[9],  34, "identifier",    "asd");
584     checkLexerToken(result[10], 37, "punctuation",   "{");
585     checkLexerToken(result[11], 39, "intLiteral",    "1");
586     checkLexerToken(result[12], 40, "identifier",    "a3");
587     checkLexerToken(result[13], 43, "floatLiteral",  "1.2");
588     checkLexerToken(result[14], 47, "punctuation",   "+");
589     checkLexerToken(result[15], 49, "floatLiteral",  "3.4");
590     checkLexerToken(result[16], 53, "punctuation",   "+");
591     checkLexerToken(result[17], 55, "floatLiteral",  "1.");
592     checkLexerToken(result[18], 58, "punctuation",   "+");
593     checkLexerToken(result[19], 60, "floatLiteral",  ".2");
594     checkLexerToken(result[20], 63, "floatLiteral",  "1.2f");
595     checkLexerToken(result[21], 68, "floatLiteral",  "0.f");
596     checkLexerToken(result[22], 72, "floatLiteral",  ".3f");
597     checkLexerToken(result[23], 76, "punctuation",   "&&");
598     checkLexerToken(result[24], 79, "punctuation",   "||");
599 }
600
601 tests.simpleNoReturn = function()
602 {
603     checkFail(
604         () => doPrep("int foo() { }"),
605         (e) => e instanceof WTypeError);
606 }
607
608 tests.simpleUnreachableCode = function()
609 {
610     checkFail(
611         () => doPrep(`
612             void foo()
613             {
614                 return;
615                 int x;
616             }
617         `),
618         (e) => e instanceof WTypeError);
619 }
620
621 tests.simpleStruct = function()
622 {
623     let program = doPrep(`
624         struct Foo {
625             int x;
626             int y;
627         }
628         Foo foo(Foo foo)
629         {
630             Foo result;
631             result.x = foo.y;
632             result.y = foo.x;
633             return result;
634         }
635     `);
636     let structType = program.types.get("Foo");
637     if (!structType)
638         throw new Error("Did not find Foo type");
639     let buffer = new EBuffer(2);
640     buffer.set(0, 62);
641     buffer.set(1, 24);
642     let result = callFunction(program, "foo", [new TypedValue(structType, new EPtr(buffer, 0))]);
643     if (!result.type.equals(structType))
644         throw new Error("Wrong result type: " + result.type);
645     let x = result.ePtr.get(0);
646     let y = result.ePtr.get(1);
647     if (x != 24)
648         throw new Error("Wrong result for x: " + x + " (y = " + y + ")");
649     if (y != 62)
650         throw new Error("Wrong result for y: " + y + " (x + " + x + ")");
651 }
652
653 tests.loadNull = function()
654 {
655     checkFail(
656         () => doPrep(`
657             void sink(thread int* x) { }
658             void foo() { sink(*null); }
659         `),
660         (e) => e instanceof WTypeError && e.message.indexOf("Type passed to dereference is not a pointer: null") != -1);
661 }
662
663 tests.storeNull = function()
664 {
665     checkFail(
666         () => doPrep(`
667             void foo() { *null = 42; }
668         `),
669         (e) => e instanceof WTypeError && e.message.indexOf("Type passed to dereference is not a pointer: null") != -1);
670 }
671
672 tests.returnNull = function()
673 {
674     let program = doPrep(`
675         thread int* foo() { return null; }
676     `);
677     let result = callFunction(program, "foo", []);
678     if (!result.type.isPtr)
679         throw new Error("Return type is not a pointer: " + result.type);
680     if (!result.type.elementType.equals(program.intrinsics.int))
681         throw new Error("Return type is not a pointer to an int: " + result.type);
682     if (result.value != null)
683         throw new Error("Return value is not null: " + result.value);
684 }
685
686 tests.dereferenceDefaultNull = function()
687 {
688     let program = doPrep(`
689         int foo()
690         {
691             thread int* p;
692             return *p;
693         }
694     `);
695     checkFail(
696         () => callFunction(program, "foo", []),
697         (e) => e instanceof WTrapError);
698 }
699
700 tests.defaultInitializedNull = function()
701 {
702     let program = doPrep(`
703         int foo()
704         {
705             thread int* p = null;;
706             return *p;
707         }
708     `);
709     checkFail(
710         () => callFunction(program, "foo", []),
711         (e) => e instanceof WTrapError);
712 }
713
714 tests.passNullToPtrMonomorphic = function()
715 {
716     let program = doPrep(`
717         int foo(thread int* ptr)
718         {
719             return *ptr;
720         }
721         int bar()
722         {
723             return foo(null);
724         }
725     `);
726     checkFail(
727         () => callFunction(program, "bar", []),
728         (e) => e instanceof WTrapError);
729 }
730
731 tests.loadNullArrayRef = function()
732 {
733     checkFail(
734         () => doPrep(`
735             void sink(thread int* x) { }
736             void foo() { sink(null[0u]); }
737         `),
738         (e) => e instanceof WTypeError && e.message.indexOf("Cannot resolve access") != -1);
739 }
740
741 tests.storeNullArrayRef = function()
742 {
743     checkFail(
744         () => doPrep(`
745             void foo() { null[0u] = 42; }
746         `),
747         (e) => e instanceof WTypeError && e.message.indexOf("Cannot resolve access") != -1);
748 }
749
750 tests.returnNullArrayRef = function()
751 {
752     let program = doPrep(`
753         thread int[] foo() { return null; }
754     `);
755     let result = callFunction(program, "foo", []);
756     if (!result.type.isArrayRef)
757         throw new Error("Return type is not an array reference: " + result.type);
758     if (!result.type.elementType.equals(program.intrinsics.int))
759         throw new Error("Return type is not an int array reference: " + result.type);
760     if (result.value != null)
761         throw new Error("Return value is not null: " + result.value);
762 }
763
764 tests.dereferenceDefaultNullArrayRef = function()
765 {
766     let program = doPrep(`
767         int foo()
768         {
769             thread int[] p;
770             return p[0u];
771         }
772     `);
773     checkFail(
774         () => callFunction(program, "foo", []),
775         (e) => e instanceof WTrapError);
776 }
777
778 tests.defaultInitializedNullArrayRef = function()
779 {
780     let program = doPrep(`
781         int foo()
782         {
783             thread int[] p = null;
784             return p[0u];
785         }
786     `);
787     checkFail(
788         () => callFunction(program, "foo", []),
789         (e) => e instanceof WTrapError);
790 }
791
792 tests.defaultInitializedNullArrayRefIntLiteral = function()
793 {
794     let program = doPrep(`
795         int foo()
796         {
797             thread int[] p = null;
798             return p[0];
799         }
800     `);
801     checkFail(
802         () => callFunction(program, "foo", []),
803         (e) => e instanceof WTrapError);
804 }
805
806 tests.passNullToPtrMonomorphicArrayRef = function()
807 {
808     let program = doPrep(`
809         int foo(thread int[] ptr)
810         {
811             return ptr[0u];
812         }
813         int bar()
814         {
815             return foo(null);
816         }
817     `);
818     checkFail(
819         () => callFunction(program, "bar", []),
820         (e) => e instanceof WTrapError);
821 }
822
823 tests.returnIntLiteralUint = function()
824 {
825     let program = doPrep("uint foo() { return 42; }");
826     checkNumber(program, callFunction(program, "foo", []), 42);
827 }
828
829 tests.returnIntLiteralFloat = function()
830 {
831     let program = doPrep("float foo() { return 42; }");
832     checkNumber(program, callFunction(program, "foo", []), 42);
833 }
834
835 tests.badIntLiteralForInt = function()
836 {
837     checkFail(
838         () => doPrep("void foo() { int x = 3000000000; }"),
839         (e) => e instanceof WSyntaxError);
840 }
841
842 tests.badIntLiteralForUint = function()
843 {
844     checkFail(
845         () => doPrep("void foo() { uint x = 5000000000; }"),
846         (e) => e instanceof WSyntaxError);
847 }
848
849 tests.badIntLiteralForFloat = function()
850 {
851     checkFail(
852         () => doPrep("void foo() { float x = 5000000000000000000000000000000000000; }"),
853         (e) => e instanceof WSyntaxError);
854 }
855
856 tests.doubleNot = function()
857 {
858     let program = doPrep(`
859         bool foo(bool x)
860         {
861             return !!x;
862         }
863     `);
864     checkBool(program, callFunction(program, "foo", [makeBool(program, true)]), true);
865     checkBool(program, callFunction(program, "foo", [makeBool(program, false)]), false);
866 }
867
868 tests.simpleRecursion = function()
869 {
870     checkFail(
871         () => doPrep(`
872             void foo(int x)
873             {
874                 foo(x);
875             }
876         `),
877         (e) => e instanceof WTypeError);
878 }
879
880 tests.variableShadowing = function()
881 {
882     let program = doPrep(`
883         int foo()
884         {
885             int y;
886             int x = 7;
887             {
888                 int x = 8;
889                 y = x;
890             }
891             return y;
892         }
893     `);
894     checkInt(program, callFunction(program, "foo", []), 8);
895     program = doPrep(`
896         int foo()
897         {
898             int y;
899             int x = 7;
900             {
901                 int x = 8;
902             }
903             y = x;
904             return y;
905         }
906     `);
907     checkInt(program, callFunction(program, "foo", []), 7);
908 }
909
910 tests.ifStatement = function()
911 {
912     let program = doPrep(`
913         int foo(int x)
914         {
915             int y = 6;
916             if (x == 7) {
917                 y = 8;
918             }
919             return y;
920         }
921     `);
922     checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 6);
923     checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 6);
924     checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 6);
925     checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 6);
926     checkInt(program, callFunction(program, "foo", [makeInt(program, 7)]), 8);
927     checkInt(program, callFunction(program, "foo", [makeInt(program, 8)]), 6);
928     checkInt(program, callFunction(program, "foo", [makeInt(program, 9)]), 6);
929 }
930
931 tests.ifElseStatement = function()
932 {
933     let program = doPrep(`
934         int foo(int x)
935         {
936             int y = 6;
937             if (x == 7) {
938                 y = 8;
939             } else {
940                 y = 9;
941             }
942             return y;
943         }
944     `);
945     checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 9);
946     checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 9);
947     checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 9);
948     checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 9);
949     checkInt(program, callFunction(program, "foo", [makeInt(program, 7)]), 8);
950     checkInt(program, callFunction(program, "foo", [makeInt(program, 8)]), 9);
951     checkInt(program, callFunction(program, "foo", [makeInt(program, 9)]), 9);
952 }
953
954 tests.ifElseIfStatement = function()
955 {
956     let program = doPrep(`
957         int foo(int x)
958         {
959             int y = 6;
960             if (x == 7) {
961                 y = 8;
962             } else if (x == 8) {
963                 y = 9;
964             }
965             return y;
966         }
967     `);
968     checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 6);
969     checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 6);
970     checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 6);
971     checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 6);
972     checkInt(program, callFunction(program, "foo", [makeInt(program, 7)]), 8);
973     checkInt(program, callFunction(program, "foo", [makeInt(program, 8)]), 9);
974     checkInt(program, callFunction(program, "foo", [makeInt(program, 9)]), 6);
975 }
976
977 tests.ifElseIfElseStatement = function()
978 {
979     let program = doPrep(`
980         int foo(int x)
981         {
982             int y = 6;
983             if (x == 7) {
984                 y = 8;
985             } else if (x == 8) {
986                 y = 9;
987             } else {
988                 y = 10;
989             }
990             return y;
991         }
992     `);
993     checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 10);
994     checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 10);
995     checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 10);
996     checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 10);
997     checkInt(program, callFunction(program, "foo", [makeInt(program, 7)]), 8);
998     checkInt(program, callFunction(program, "foo", [makeInt(program, 8)]), 9);
999     checkInt(program, callFunction(program, "foo", [makeInt(program, 9)]), 10);
1000 }
1001
1002 tests.returnIf = function()
1003 {
1004     checkFail(
1005         () => doPrep(`
1006             int foo(int x)
1007             {
1008                 int y = 6;
1009                 if (x == 7) {
1010                     return y;
1011                 }
1012             }
1013         `),
1014         (e) => e instanceof WTypeError);
1015     checkFail(
1016         () => doPrep(`
1017             int foo(int x)
1018             {
1019                 int y = 6;
1020                 if (x == 7) {
1021                     return y;
1022                 } else {
1023                     y = 8;
1024                 }
1025             }
1026         `),
1027         (e) => e instanceof WTypeError);
1028     checkFail(
1029         () => doPrep(`
1030             int foo(int x)
1031             {
1032                 int y = 6;
1033                 if (x == 7) {
1034                     y = 8;
1035                 } else {
1036                     return y;
1037                 }
1038             }
1039         `),
1040         (e) => e instanceof WTypeError);
1041     let program = doPrep(`
1042         int foo(int x)
1043         {
1044             int y = 6;
1045             if (x == 7) {
1046                 return 8;
1047             } else {
1048                 return 10;
1049             }
1050         }
1051     `);
1052     checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 10);
1053     checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 10);
1054     checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 10);
1055     checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 10);
1056     checkInt(program, callFunction(program, "foo", [makeInt(program, 7)]), 8);
1057     checkInt(program, callFunction(program, "foo", [makeInt(program, 8)]), 10);
1058     checkInt(program, callFunction(program, "foo", [makeInt(program, 9)]), 10);
1059     checkFail(
1060         () => doPrep(`
1061             int foo(int x)
1062             {
1063                 int y = 6;
1064                 if (x == 7) {
1065                     return 8;
1066                 } else if (x == 9) {
1067                     return 10;
1068                 }
1069             }
1070         `),
1071         (e) => e instanceof WTypeError);
1072     program = doPrep(`
1073         int foo(int x)
1074         {
1075             int y = 6;
1076             if (x == 7) {
1077                 return 8;
1078             } else {
1079                 y = 9;
1080             }
1081             return y;
1082         }
1083     `);
1084     checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 9);
1085     checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 9);
1086     checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 9);
1087     checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 9);
1088     checkInt(program, callFunction(program, "foo", [makeInt(program, 7)]), 8);
1089     checkInt(program, callFunction(program, "foo", [makeInt(program, 8)]), 9);
1090     checkInt(program, callFunction(program, "foo", [makeInt(program, 9)]), 9);
1091     checkFail(
1092         () => doPrep(`
1093             int foo(int x)
1094             {
1095                 int y = 6;
1096                 if (x == 7) {
1097                     return 8;
1098                 } else {
1099                     return 10;
1100                 }
1101                 return 11;
1102             }
1103         `),
1104         (e) => e instanceof WTypeError);
1105     program = doPrep(`
1106         int foo(int x)
1107         {
1108             int y = 6;
1109             if (x == 7)
1110                 int y = 8;
1111             return y;
1112         }
1113     `);
1114     checkInt(program, callFunction(program, "foo", [makeInt(program, 7)]), 6);
1115 }
1116
1117 tests.simpleWhile = function()
1118 {
1119     let program = doPrep(`
1120         int foo(int x)
1121         {
1122             while (x < 13)
1123                 x = x * 2;
1124             return x;
1125         }
1126     `);
1127     checkInt(program, callFunction(program, "foo", [makeInt(program, 1)]), 16);
1128 }
1129
1130 tests.intOverloadResolution = function()
1131 {
1132     let program = doPrep(`
1133         int foo(int) { return 1; }
1134         int foo(uint) { return 2; }
1135         int foo(float) { return 3; }
1136         int bar() { return foo(42); }
1137     `);
1138     checkInt(program, callFunction(program, "bar", []), 1);
1139 }
1140
1141 tests.intOverloadResolutionReverseOrder = function()
1142 {
1143     let program = doPrep(`
1144         int foo(float) { return 3; }
1145         int foo(uint) { return 2; }
1146         int foo(int) { return 1; }
1147         int bar() { return foo(42); }
1148     `);
1149     checkInt(program, callFunction(program, "bar", []), 1);
1150 }
1151
1152 tests.break = function()
1153 {
1154     let program = doPrep(`
1155         int foo(int x)
1156         {
1157             while (true) {
1158                 x = x * 2;
1159                 if (x >= 7)
1160                     break;
1161             }
1162             return x;
1163         }
1164     `);
1165     checkInt(program, callFunction(program, "foo", [makeInt(program, 1)]), 8);
1166     checkInt(program, callFunction(program, "foo", [makeInt(program, 10)]), 20);
1167     program = doPrep(`
1168         int foo(int x)
1169         {
1170             while (true) {
1171                 while (true) {
1172                     x = x * 2;
1173                     if (x >= 7)
1174                         break;
1175                 }
1176                 x = x - 1;
1177                 break;
1178             }
1179             return x;
1180             
1181         }
1182     `);
1183     checkInt(program, callFunction(program, "foo", [makeInt(program, 1)]), 7);
1184     checkInt(program, callFunction(program, "foo", [makeInt(program, 10)]), 19);
1185     checkFail(
1186         () => doPrep(`
1187             int foo(int x)
1188             {
1189                 while (true) {
1190                     {
1191                         break;
1192                     }
1193                     x = x + 1;
1194                 }
1195                 return x;
1196             }
1197         `),
1198         (e) => e instanceof WTypeError);
1199     checkFail(
1200         () => doPrep(`
1201             int foo(int x)
1202             {
1203                 break;
1204                 return x;
1205             }
1206         `),
1207         (e) => e instanceof WTypeError);
1208     program = doPrep(`
1209             int foo(int x)
1210             {
1211                 while (true) {
1212                     if (x == 7) {
1213                         break;
1214                     }
1215                     x = x + 1;
1216                 }
1217                 return x;
1218             }
1219     `);
1220     checkInt(program, callFunction(program, "foo", [makeInt(program, 1)]), 7);
1221     program = doPrep(`
1222             int foo(int x)
1223             {
1224                 while (true) {
1225                     break;
1226                 }
1227                 return x;
1228             }
1229     `);
1230     checkInt(program, callFunction(program, "foo", [makeInt(program, 1)]), 1);
1231     program = doPrep(`
1232             int foo()
1233             {
1234                 while (true) {
1235                     return 7;
1236                 }
1237             }
1238     `);
1239     checkInt(program, callFunction(program, "foo", []), 7);
1240     checkFail(
1241         () => doPrep(`
1242             int foo(int x)
1243             {
1244                 while(true) {
1245                     break;
1246                     return 7;
1247                 }
1248             }
1249         `),
1250         (e) => e instanceof WTypeError);
1251 }
1252
1253 tests.continue = function()
1254 {
1255     let program = doPrep(`
1256         int foo(int x)
1257         {
1258             while (x < 10) {
1259                 if (x == 8) {
1260                     x = x + 1;
1261                     continue;
1262                 }
1263                 x = x * 2;
1264             }
1265             return x;
1266         }
1267     `);
1268     checkInt(program, callFunction(program, "foo", [makeInt(program, 1)]), 18);
1269     checkFail(
1270         () => doPrep(`
1271             int foo(int x)
1272             {
1273                 continue;
1274                 return x;
1275                 
1276             }
1277         `),
1278         (e) => e instanceof WTypeError);
1279 }
1280
1281 tests.doWhile = function()
1282 {
1283     let program = doPrep(`
1284         int foo(int x)
1285         {
1286             int y = 7;
1287             do {
1288                 y = 8;
1289                 break;
1290             } while (x < 10);
1291             return y;
1292         }
1293     `);
1294     checkInt(program, callFunction(program, "foo", [makeInt(program, 1)]), 8);
1295     checkInt(program, callFunction(program, "foo", [makeInt(program, 11)]), 8);
1296     program = doPrep(`
1297         int foo(int x)
1298         {
1299             int y = 7;
1300             do {
1301                 y = 8;
1302                 break;
1303             } while (y == 7);
1304             return y;
1305         }
1306     `);
1307     checkInt(program, callFunction(program, "foo", [makeInt(program, 1)]), 8);
1308     program = doPrep(`
1309         int foo(int x)
1310         {
1311             int sum = 0;
1312             do {
1313                 if (x == 11) {
1314                     x = 15;
1315                     continue;
1316                 }
1317                 sum = sum + x;
1318                 x = x + 1;
1319             } while (x < 13);
1320             return sum;
1321         }
1322     `);
1323     checkInt(program, callFunction(program, "foo", [makeInt(program, 9)]), 19);
1324 }
1325
1326 tests.forLoop = function()
1327 {
1328     let program = doPrep(`
1329         int foo(int x)
1330         {
1331             int sum = 0;
1332             int i;
1333             for (i = 0; i < x; i = i + 1) {
1334                 sum = sum + i;
1335             }
1336             return sum;
1337         }
1338     `);
1339     checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 3);
1340     checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 6);
1341     checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 10);
1342     program = doPrep(`
1343         int foo(int x)
1344         {
1345             int sum = 0;
1346             for (int i = 0; i < x; i = i + 1) {
1347                 sum = sum + i;
1348             }
1349             return sum;
1350         }
1351     `);
1352     checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 3);
1353     checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 6);
1354     checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 10);
1355     program = doPrep(`
1356         int foo(int x)
1357         {
1358             int sum = 0;
1359             int i = 100;
1360             for (int i = 0; i < x; i = i + 1) {
1361                 sum = sum + i;
1362             }
1363             return sum;
1364         }
1365     `);
1366     checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 3);
1367     checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 6);
1368     checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 10);
1369     program = doPrep(`
1370         int foo(int x)
1371         {
1372             int sum = 0;
1373             for (int i = 0; i < x; i = i + 1) {
1374                 if (i == 4)
1375                     continue;
1376                 sum = sum + i;
1377             }
1378             return sum;
1379         }
1380     `);
1381     checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 3);
1382     checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 6);
1383     checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 6);
1384     checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 11);
1385     program = doPrep(`
1386         int foo(int x)
1387         {
1388             int sum = 0;
1389             for (int i = 0; i < x; i = i + 1) {
1390                 if (i == 5)
1391                     break;
1392                 sum = sum + i;
1393             }
1394             return sum;
1395         }
1396     `);
1397     checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 3);
1398     checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 6);
1399     checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 10);
1400     checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 10);
1401     checkInt(program, callFunction(program, "foo", [makeInt(program, 7)]), 10);
1402     program = doPrep(`
1403         int foo(int x)
1404         {
1405             int sum = 0;
1406             for (int i = 0; ; i = i + 1) {
1407                 if (i >= x)
1408                     break;
1409                 sum = sum + i;
1410             }
1411             return sum;
1412         }
1413     `);
1414     checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 3);
1415     checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 6);
1416     checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 10);
1417     checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 15);
1418     checkInt(program, callFunction(program, "foo", [makeInt(program, 7)]), 21);
1419     program = doPrep(`
1420         int foo(int x)
1421         {
1422             int sum = 0;
1423             int i = 0;
1424             for ( ; ; i = i + 1) {
1425                 if (i >= x)
1426                     break;
1427                 sum = sum + i;
1428             }
1429             return sum;
1430         }
1431     `);
1432     checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 3);
1433     checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 6);
1434     checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 10);
1435     checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 15);
1436     checkInt(program, callFunction(program, "foo", [makeInt(program, 7)]), 21);
1437     program = doPrep(`
1438         int foo(int x)
1439         {
1440             int sum = 0;
1441             int i = 0;
1442             for ( ; ; ) {
1443                 if (i >= x)
1444                     break;
1445                 sum = sum + i;
1446                 i = i + 1;
1447             }
1448             return sum;
1449         }
1450     `);
1451     checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 3);
1452     checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 6);
1453     checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 10);
1454     checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 15);
1455     checkInt(program, callFunction(program, "foo", [makeInt(program, 7)]), 21);
1456     checkFail(
1457         () => doPrep(`
1458             void foo(int x)
1459             {
1460                 for (int i = 0; ; i = i + 1) {
1461                     break;
1462                     x = i;
1463                 }
1464             }
1465         `),
1466         (e) => e instanceof WTypeError);
1467     program = doPrep(`
1468         int foo(int x)
1469         {
1470             for ( ; ; ) {
1471                 return 7;
1472             }
1473         }
1474     `);
1475     checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 7);
1476     checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 7);
1477     checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 7);
1478     checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 7);
1479     checkInt(program, callFunction(program, "foo", [makeInt(program, 7)]), 7);
1480     checkFail(
1481         () => doPrep(`
1482             int foo(int x)
1483             {
1484                 for ( ; x < 10; ) {
1485                     return 7;
1486                 }
1487             }
1488         `),
1489         (e) => e instanceof WTypeError);
1490     program = doPrep(`
1491         int foo(int x)
1492         {
1493             for ( ; true; ) {
1494                 return 7;
1495             }
1496         }
1497     `);
1498     checkInt(program, callFunction(program, "foo", [makeInt(program, 3)]), 7);
1499     checkInt(program, callFunction(program, "foo", [makeInt(program, 4)]), 7);
1500     checkInt(program, callFunction(program, "foo", [makeInt(program, 5)]), 7);
1501     checkInt(program, callFunction(program, "foo", [makeInt(program, 6)]), 7);
1502     checkInt(program, callFunction(program, "foo", [makeInt(program, 7)]), 7);
1503 }
1504
1505 tests.prefixPlusPlus = function()
1506 {
1507     let program = doPrep(`
1508         int foo(int x)
1509         {
1510             ++x;
1511             return x;
1512         }
1513     `);
1514     checkInt(program, callFunction(program, "foo", [makeInt(program, 64)]), 65);
1515 }
1516
1517 tests.prefixPlusPlusResult = function()
1518 {
1519     let program = doPrep(`
1520         int foo(int x)
1521         {
1522             return ++x;
1523         }
1524     `);
1525     checkInt(program, callFunction(program, "foo", [makeInt(program, 64)]), 65);
1526 }
1527
1528 tests.postfixPlusPlus = function()
1529 {
1530     let program = doPrep(`
1531         int foo(int x)
1532         {
1533             x++;
1534             return x;
1535         }
1536     `);
1537     checkInt(program, callFunction(program, "foo", [makeInt(program, 64)]), 65);
1538 }
1539
1540 tests.postfixPlusPlusResult = function()
1541 {
1542     let program = doPrep(`
1543         int foo(int x)
1544         {
1545             return x++;
1546         }
1547     `);
1548     checkInt(program, callFunction(program, "foo", [makeInt(program, 64)]), 64);
1549 }
1550
1551 tests.prefixMinusMinus = function()
1552 {
1553     let program = doPrep(`
1554         int foo(int x)
1555         {
1556             --x;
1557             return x;
1558         }
1559     `);
1560     checkInt(program, callFunction(program, "foo", [makeInt(program, 64)]), 63);
1561 }
1562
1563 tests.prefixMinusMinusResult = function()
1564 {
1565     let program = doPrep(`
1566         int foo(int x)
1567         {
1568             return --x;
1569         }
1570     `);
1571     checkInt(program, callFunction(program, "foo", [makeInt(program, 64)]), 63);
1572 }
1573
1574 tests.postfixMinusMinus = function()
1575 {
1576     let program = doPrep(`
1577         int foo(int x)
1578         {
1579             x--;
1580             return x;
1581         }
1582     `);
1583     checkInt(program, callFunction(program, "foo", [makeInt(program, 64)]), 63);
1584 }
1585
1586 tests.postfixMinusMinusResult = function()
1587 {
1588     let program = doPrep(`
1589         int foo(int x)
1590         {
1591             return x--;
1592         }
1593     `);
1594     checkInt(program, callFunction(program, "foo", [makeInt(program, 64)]), 64);
1595 }
1596
1597 tests.plusEquals = function()
1598 {
1599     let program = doPrep(`
1600         int foo(int x)
1601         {
1602             x += 42;
1603             return x;
1604         }
1605     `);
1606     checkInt(program, callFunction(program, "foo", [makeInt(program, 385)]), 385 + 42);
1607 }
1608
1609 tests.plusEqualsResult = function()
1610 {
1611     let program = doPrep(`
1612         int foo(int x)
1613         {
1614             return x += 42;
1615         }
1616     `);
1617     checkInt(program, callFunction(program, "foo", [makeInt(program, 385)]), 385 + 42);
1618 }
1619
1620 tests.minusEquals = function()
1621 {
1622     let program = doPrep(`
1623         int foo(int x)
1624         {
1625             x -= 42;
1626             return x;
1627         }
1628     `);
1629     checkInt(program, callFunction(program, "foo", [makeInt(program, 385)]), 385 - 42);
1630 }
1631
1632 tests.minusEqualsResult = function()
1633 {
1634     let program = doPrep(`
1635         int foo(int x)
1636         {
1637             return x -= 42;
1638         }
1639     `);
1640     checkInt(program, callFunction(program, "foo", [makeInt(program, 385)]), 385 - 42);
1641 }
1642
1643 tests.timesEquals = function()
1644 {
1645     let program = doPrep(`
1646         int foo(int x)
1647         {
1648             x *= 42;
1649             return x;
1650         }
1651     `);
1652     checkInt(program, callFunction(program, "foo", [makeInt(program, 385)]), 385 * 42);
1653 }
1654
1655 tests.timesEqualsResult = function()
1656 {
1657     let program = doPrep(`
1658         int foo(int x)
1659         {
1660             return x *= 42;
1661         }
1662     `);
1663     checkInt(program, callFunction(program, "foo", [makeInt(program, 385)]), 385 * 42);
1664 }
1665
1666 tests.divideEquals = function()
1667 {
1668     let program = doPrep(`
1669         int foo(int x)
1670         {
1671             x /= 42;
1672             return x;
1673         }
1674     `);
1675     checkInt(program, callFunction(program, "foo", [makeInt(program, 385)]), (385 / 42) | 0);
1676 }
1677
1678 tests.divideEqualsResult = function()
1679 {
1680     let program = doPrep(`
1681         int foo(int x)
1682         {
1683             return x /= 42;
1684         }
1685     `);
1686     checkInt(program, callFunction(program, "foo", [makeInt(program, 385)]), (385 / 42) | 0);
1687 }
1688
1689 tests.twoIntLiterals = function()
1690 {
1691     let program = doPrep(`
1692         bool foo()
1693         {
1694             return 42 == 42;
1695         }
1696     `);
1697     checkBool(program, callFunction(program, "foo", []), true);
1698 }
1699
1700 tests.assignUintToInt = function()
1701 {
1702     checkFail(
1703         () => doPrep(`
1704             void foo()
1705             {
1706                 int x = 42u;
1707             }
1708         `),
1709         (e) => e instanceof WTypeError && e.message.indexOf("Type mismatch in variable initialization") != -1);
1710 }
1711
1712 tests.buildArrayThenSumIt = function()
1713 {
1714     let program = doPrep(`
1715         int foo()
1716         {
1717             int[42] array;
1718             for (uint i = 0; i < 42; i = i + 1)
1719                 array[i] = int(i + 5);
1720             int result;
1721             for (uint i = 0; i < 42; i = i + 1)
1722                 result = result + array[i];
1723             return result;
1724         }
1725     `);
1726     checkInt(program, callFunction(program, "foo", []), 42 * 5 + 42 * 41 / 2);
1727 }
1728
1729 tests.buildArrayThenSumItUsingArrayReference = function()
1730 {
1731     let program = doPrep(`
1732         int bar(thread int[] array)
1733         {
1734             for (uint i = 0; i < 42; i = i + 1)
1735                 array[i] = int(i + 5);
1736             int result;
1737             for (uint i = 0; i < 42; i = i + 1)
1738                 result = result + array[i];
1739             return result;
1740         }
1741         int foo()
1742         {
1743             int[42] array;
1744             return bar(@array);
1745         }
1746     `);
1747     checkInt(program, callFunction(program, "foo", []), 42 * 5 + 42 * 41 / 2);
1748 }
1749
1750 tests.overrideSubscriptStruct = function()
1751 {
1752     let program = doPrep(`
1753         struct Foo {
1754             int x;
1755             int y;
1756         }
1757         thread int* operator&[](thread Foo* foo, uint index)
1758         {
1759             if (index == 0)
1760                 return &foo->x;
1761             if (index == 1)
1762                 return &foo->y;
1763             return null;
1764         }
1765         int foo()
1766         {
1767             Foo foo;
1768             foo.x = 498;
1769             foo.y = 19;
1770             return foo[0] + foo[1] * 3;
1771         }
1772     `);
1773     checkInt(program, callFunction(program, "foo", []), 498 + 19 * 3);
1774 }
1775
1776 tests.overrideSubscriptStructAndDoStores = function()
1777 {
1778     let program = doPrep(`
1779         struct Foo {
1780             int x;
1781             int y;
1782         }
1783         thread int* operator&[](thread Foo* foo, uint index)
1784         {
1785             if (index == 0)
1786                 return &foo->x;
1787             if (index == 1)
1788                 return &foo->y;
1789             return null;
1790         }
1791         int foo()
1792         {
1793             Foo foo;
1794             foo[0] = 498;
1795             foo[1] = 19;
1796             return foo.x + foo.y;
1797         }
1798     `);
1799     checkInt(program, callFunction(program, "foo", []), 498 + 19);
1800 }
1801
1802 tests.overrideSubscriptStructAndUsePointers = function()
1803 {
1804     let program = doPrep(`
1805         struct Foo {
1806             int x;
1807             int y;
1808         }
1809         thread int* operator&[](thread Foo* foo, uint index)
1810         {
1811             if (index == 0)
1812                 return &foo->x;
1813             if (index == 1)
1814                 return &foo->y;
1815             return null;
1816         }
1817         int bar(thread Foo* foo)
1818         {
1819             return (*foo)[0] + (*foo)[1];
1820         }
1821         int foo()
1822         {
1823             Foo foo;
1824             foo.x = 498;
1825             foo.y = 19;
1826             return bar(&foo);
1827         }
1828     `);
1829     checkInt(program, callFunction(program, "foo", []), 498 + 19);
1830 }
1831
1832 tests.overrideSubscriptStructAndUsePointersIncorrectly = function()
1833 {
1834     checkFail(
1835         () => doPrep(`
1836             struct Foo {
1837                 int x;
1838                 int y;
1839             }
1840             thread int* operator&[](thread Foo* foo, uint index)
1841             {
1842                 if (index == 0)
1843                     return &foo->x;
1844                 if (index == 1)
1845                     return &foo->y;
1846                 return null;
1847             }
1848             int bar(thread Foo* foo)
1849             {
1850                 return foo[0] + foo[1];
1851             }
1852             int foo()
1853             {
1854                 Foo foo;
1855                 foo.x = 498;
1856                 foo.y = 19;
1857                 return bar(&foo);
1858             }
1859         `),
1860         (e) => e instanceof WTypeError);
1861 }
1862
1863 tests.makeArrayRefFromLocal = function()
1864 {
1865     let program = doPrep(`
1866         int bar(thread int[] ref)
1867         {
1868             return ref[0];
1869         }
1870         int foo()
1871         {
1872             int x = 48;
1873             return bar(@x);
1874         }
1875     `);
1876     checkInt(program, callFunction(program, "foo", []), 48);
1877 }
1878
1879 tests.makeArrayRefFromPointer = function()
1880 {
1881     let program = doPrep(`
1882         int bar(thread int[] ref)
1883         {
1884             return ref[0];
1885         }
1886         int baz(thread int* ptr)
1887         {
1888             return bar(@ptr);
1889         }
1890         int foo()
1891         {
1892             int x = 48;
1893             return baz(&x);
1894         }
1895     `);
1896     checkInt(program, callFunction(program, "foo", []), 48);
1897 }
1898
1899 tests.makeArrayRefFromArrayRef = function()
1900 {
1901     checkFail(
1902         () => doPrep(`
1903             int bar(thread int[] ref)
1904             {
1905                 return ref[0];
1906             }
1907             int baz(thread int[] ptr)
1908             {
1909                 return bar(@ptr);
1910             }
1911             int foo()
1912             {
1913                 int x = 48;
1914                 return baz(@x);
1915             }
1916         `),
1917         (e) => e instanceof WTypeError);
1918 }
1919
1920 tests.simpleLength = function()
1921 {
1922     let program = doPrep(`
1923         uint foo()
1924         {
1925             float[754] array;
1926             return (@array).length;
1927         }
1928     `);
1929     checkUint(program, callFunction(program, "foo", []), 754);
1930 }
1931
1932 tests.nonArrayRefArrayLengthSucceed = function()
1933 {
1934     let program = doPrep(`
1935         uint foo()
1936         {
1937             float[754] array;
1938             return array.length;
1939         }
1940         uint bar()
1941         {
1942             int[754] array;
1943             return array.length;
1944         }
1945     `);
1946     checkUint(program, callFunction(program, "foo", []), 754);
1947     checkUint(program, callFunction(program, "bar", []), 754);
1948 }
1949
1950 tests.nonArrayRefArrayLengthFail = function()
1951 {
1952     checkFail(
1953         () => doPrep(`
1954             thread uint* lengthPtr()
1955             {
1956                 int[42] array;
1957                 return &(array.length);
1958             }
1959         `),
1960         e => e instanceof WTypeError);
1961 }
1962
1963 tests.assignLength = function()
1964 {
1965     checkFail(
1966         () => doPrep(`
1967             void foo()
1968             {
1969                 float[754] array;
1970                 (@array).length = 42;
1971             }
1972         `),
1973         (e) => e instanceof WTypeError);
1974 }
1975
1976 tests.assignLengthHelper = function()
1977 {
1978     checkFail(
1979         () => doPrep(`
1980             void bar(thread float[] array)
1981             {
1982                 array.length = 42;
1983             }
1984             void foo()
1985             {
1986                 float[754] array;
1987                 bar(@array);
1988             }
1989         `),
1990         (e) => e instanceof WTypeError);
1991 }
1992
1993 tests.simpleGetter = function()
1994 {
1995     let program = doPrep(`
1996         struct Foo {
1997             int x;
1998         }
1999         int operator.y(Foo foo)
2000         {
2001             return foo.x;
2002         }
2003         int foo()
2004         {
2005             Foo foo;
2006             foo.x = 7804;
2007             return foo.y;
2008         }
2009     `);
2010     checkInt(program, callFunction(program, "foo", []), 7804);
2011 }
2012
2013 tests.simpleSetter = function()
2014 {
2015     let program = doPrep(`
2016         struct Foo {
2017             int x;
2018         }
2019         int operator.y(Foo foo)
2020         {
2021             return foo.x;
2022         }
2023         Foo operator.y=(Foo foo, int value)
2024         {
2025             foo.x = value;
2026             return foo;
2027         }
2028         int foo()
2029         {
2030             Foo foo;
2031             foo.y = 7804;
2032             return foo.x;
2033         }
2034     `);
2035     checkInt(program, callFunction(program, "foo", []), 7804);
2036 }
2037
2038 tests.nestedSubscriptLValueEmulationSimple = function()
2039 {
2040     let program = doPrep(`
2041         struct Foo {
2042             int[7] array;
2043         }
2044         int operator[](Foo foo, uint index)
2045         {
2046             return foo.array[index];
2047         }
2048         Foo operator[]=(Foo foo, uint index, int value)
2049         {
2050             foo.array[index] = value;
2051             return foo;
2052         }
2053         uint operator.length(Foo foo)
2054         {
2055             return foo.array.length;
2056         }
2057         int sum(Foo foo)
2058         {
2059             int result = 0;
2060             for (uint i = foo.length; i--;)
2061                 result += foo[i];
2062             return result;
2063         }
2064         struct Bar {
2065             Foo[6] array;
2066         }
2067         uint operator.length(Bar bar)
2068         {
2069             return bar.array.length;
2070         }
2071         Foo operator[](Bar bar, uint index)
2072         {
2073             return bar.array[index];
2074         }
2075         Bar operator[]=(Bar bar, uint index, Foo value)
2076         {
2077             bar.array[index] = value;
2078             return bar;
2079         }
2080         int sum(Bar bar)
2081         {
2082             int result = 0;
2083             for (uint i = bar.length; i--;)
2084                 result += sum(bar[i]);
2085             return result;
2086         }
2087         struct Baz {
2088             Bar[5] array;
2089         }
2090         Bar operator[](Baz baz, uint index)
2091         {
2092             return baz.array[index];
2093         }
2094         Baz operator[]=(Baz baz, uint index, Bar value)
2095         {
2096             baz.array[index] = value;
2097             return baz;
2098         }
2099         uint operator.length(Baz baz)
2100         {
2101             return baz.array.length;
2102         }
2103         int sum(Baz baz)
2104         {
2105             int result = 0;
2106             for (uint i = baz.length; i--;)
2107                 result += sum(baz[i]);
2108             return result;
2109         }
2110         void setValues(thread Baz* baz)
2111         {
2112             for (uint i = baz->length; i--;) {
2113                 for (uint j = (*baz)[i].length; j--;) {
2114                     for (uint k = (*baz)[i][j].length; k--;)
2115                         (*baz)[i][j][k] = int(i + j + k);
2116                 }
2117             }
2118         }
2119         int testSetValuesAndSum()
2120         {
2121             Baz baz;
2122             setValues(&baz);
2123             return sum(baz);
2124         }
2125         int testSetValuesMutateValuesAndSum()
2126         {
2127             Baz baz;
2128             setValues(&baz);
2129             for (uint i = baz.length; i--;) {
2130                 for (uint j = baz[i].length; j--;) {
2131                     for (uint k = baz[i][j].length; k--;)
2132                         baz[i][j][k] *= int(k);
2133                 }
2134             }
2135             return sum(baz);
2136         }
2137     `);
2138     checkInt(program, callFunction(program, "testSetValuesAndSum", []), 1575);
2139     checkInt(program, callFunction(program, "testSetValuesMutateValuesAndSum", []), 5565);
2140 }
2141
2142 tests.operatorBool = function()
2143 {
2144     let program = doPrep(`
2145         bool boolFromUcharFalse() { return bool(uchar(0)); }
2146         bool boolFromUcharTrue() { return bool(uchar(1)); }
2147
2148         bool boolFromUintFalse() { return bool(uint(0)); }
2149         bool boolFromUintTrue() { return bool(uint(1)); }
2150
2151         bool boolFromIntFalse() { return bool(int(0)); }
2152         bool boolFromIntTrue() { return bool(int(1)); }
2153
2154         bool boolFromFloatFalse() { return bool(float(0)); }
2155         bool boolFromFloatTrue() { return bool(float(1)); }
2156
2157         bool boolFromInt2False() { return bool(int2(0, 0)); }
2158         bool boolFromInt2True1() { return bool(int2(1, 0)); }
2159         bool boolFromInt2True2() { return bool(int2(0, 1)); }
2160
2161         bool boolFromFloat3False() { return bool(float3(0, 0, 0)); }
2162         bool boolFromFloat3True1() { return bool(float3(1, 0, 0)); }
2163         bool boolFromFloat3True2() { return bool(float3(0, 1, 0)); }
2164         bool boolFromFloat3True3() { return bool(float3(0, 0, 1)); }
2165
2166         bool boolFromUint4False() { return bool(uint4(0, 0, 0, 0)); }
2167         bool boolFromUint4True1() { return bool(uint4(1, 0, 0, 0)); }
2168         bool boolFromUint4True2() { return bool(uint4(0, 1, 0, 0)); }
2169         bool boolFromUint4True3() { return bool(uint4(0, 0, 1, 0)); }
2170         bool boolFromUint4True4() { return bool(uint4(0, 0, 0, 1)); }
2171
2172         struct X { int x; }
2173
2174         bool boolFromStructFalse()
2175         {
2176             X x;
2177             return bool(x);
2178         }
2179
2180         bool boolFromStructTrue()
2181         {
2182             X x;
2183             x.x = 1;
2184             return bool(x);
2185         }
2186
2187         enum Y { A, B }
2188
2189         bool boolFromEnumFalse() { return bool(Y.A); }
2190         bool boolFromEnumTrue() { return bool(Y.B); }
2191     `);
2192
2193     checkBool(program, callFunction(program, "boolFromUcharFalse", []), false);
2194     checkBool(program, callFunction(program, "boolFromUcharTrue", []), true);
2195
2196     checkBool(program, callFunction(program, "boolFromUintFalse", []), false);
2197     checkBool(program, callFunction(program, "boolFromUintTrue", []), true);
2198
2199     checkBool(program, callFunction(program, "boolFromIntFalse", []), false);
2200     checkBool(program, callFunction(program, "boolFromIntTrue", []), true);
2201
2202     checkBool(program, callFunction(program, "boolFromFloatFalse", []), false);
2203     checkBool(program, callFunction(program, "boolFromFloatTrue", []), true);
2204
2205     checkBool(program, callFunction(program, "boolFromInt2False", []), false);
2206     checkBool(program, callFunction(program, "boolFromInt2True1", []), true);
2207     checkBool(program, callFunction(program, "boolFromInt2True2", []), true);
2208
2209     checkBool(program, callFunction(program, "boolFromFloat3False", []), false);
2210     checkBool(program, callFunction(program, "boolFromFloat3True1", []), true);
2211     checkBool(program, callFunction(program, "boolFromFloat3True2", []), true);
2212     checkBool(program, callFunction(program, "boolFromFloat3True3", []), true);
2213
2214     checkBool(program, callFunction(program, "boolFromUint4False", []), false);
2215     checkBool(program, callFunction(program, "boolFromUint4True1", []), true);
2216     checkBool(program, callFunction(program, "boolFromUint4True2", []), true);
2217     checkBool(program, callFunction(program, "boolFromUint4True3", []), true);
2218     checkBool(program, callFunction(program, "boolFromUint4True4", []), true);
2219
2220     checkBool(program, callFunction(program, "boolFromStructFalse", []), false);
2221     checkBool(program, callFunction(program, "boolFromStructTrue", []), true);
2222
2223     checkBool(program, callFunction(program, "boolFromEnumFalse", []), false);
2224     checkBool(program, callFunction(program, "boolFromEnumTrue", []), true);
2225 }
2226
2227 tests.boolBitAnd = function()
2228 {
2229     let program = doPrep(`
2230         bool foo(bool a, bool b)
2231         {
2232             return a & b;
2233         }
2234     `);
2235     checkBool(program, callFunction(program, "foo", [makeBool(program, false), makeBool(program, false)]), false);
2236     checkBool(program, callFunction(program, "foo", [makeBool(program, true), makeBool(program, false)]), false);
2237     checkBool(program, callFunction(program, "foo", [makeBool(program, false), makeBool(program, true)]), false);
2238     checkBool(program, callFunction(program, "foo", [makeBool(program, true), makeBool(program, true)]), true);
2239 }
2240
2241 tests.boolBitOr = function()
2242 {
2243     let program = doPrep(`
2244         bool foo(bool a, bool b)
2245         {
2246             return a | b;
2247         }
2248     `);
2249     checkBool(program, callFunction(program, "foo", [makeBool(program, false), makeBool(program, false)]), false);
2250     checkBool(program, callFunction(program, "foo", [makeBool(program, true), makeBool(program, false)]), true);
2251     checkBool(program, callFunction(program, "foo", [makeBool(program, false), makeBool(program, true)]), true);
2252     checkBool(program, callFunction(program, "foo", [makeBool(program, true), makeBool(program, true)]), true);
2253 }
2254
2255 tests.boolBitXor = function()
2256 {
2257     let program = doPrep(`
2258         bool foo(bool a, bool b)
2259         {
2260             return a ^ b;
2261         }
2262     `);
2263     checkBool(program, callFunction(program, "foo", [makeBool(program, false), makeBool(program, false)]), false);
2264     checkBool(program, callFunction(program, "foo", [makeBool(program, true), makeBool(program, false)]), true);
2265     checkBool(program, callFunction(program, "foo", [makeBool(program, false), makeBool(program, true)]), true);
2266     checkBool(program, callFunction(program, "foo", [makeBool(program, true), makeBool(program, true)]), false);
2267 }
2268
2269 tests.boolBitNot = function()
2270 {
2271     let program = doPrep(`
2272         bool foo(bool a)
2273         {
2274             return ~a;
2275         }
2276     `);
2277     checkBool(program, callFunction(program, "foo", [makeBool(program, false)]), true);
2278     checkBool(program, callFunction(program, "foo", [makeBool(program, true)]), false);
2279 }
2280
2281 tests.intBitAnd = function()
2282 {
2283     let program = doPrep(`
2284         int foo(int a, int b)
2285         {
2286             return a & b;
2287         }
2288     `);
2289     checkInt(program, callFunction(program, "foo", [makeInt(program, 1), makeInt(program, 7)]), 1);
2290     checkInt(program, callFunction(program, "foo", [makeInt(program, 65535), makeInt(program, 42)]), 42);
2291     checkInt(program, callFunction(program, "foo", [makeInt(program, -1), makeInt(program, -7)]), -7);
2292     checkInt(program, callFunction(program, "foo", [makeInt(program, 0), makeInt(program, 85732)]), 0);
2293 }
2294
2295 tests.intBitOr = function()
2296 {
2297     let program = doPrep(`
2298         int foo(int a, int b)
2299         {
2300             return a | b;
2301         }
2302     `);
2303     checkInt(program, callFunction(program, "foo", [makeInt(program, 1), makeInt(program, 7)]), 7);
2304     checkInt(program, callFunction(program, "foo", [makeInt(program, 65535), makeInt(program, 42)]), 65535);
2305     checkInt(program, callFunction(program, "foo", [makeInt(program, -1), makeInt(program, -7)]), -1);
2306     checkInt(program, callFunction(program, "foo", [makeInt(program, 0), makeInt(program, 85732)]), 85732);
2307 }
2308
2309 tests.intBitXor = function()
2310 {
2311     let program = doPrep(`
2312         int foo(int a, int b)
2313         {
2314             return a ^ b;
2315         }
2316     `);
2317     checkInt(program, callFunction(program, "foo", [makeInt(program, 1), makeInt(program, 7)]), 6);
2318     checkInt(program, callFunction(program, "foo", [makeInt(program, 65535), makeInt(program, 42)]), 65493);
2319     checkInt(program, callFunction(program, "foo", [makeInt(program, -1), makeInt(program, -7)]), 6);
2320     checkInt(program, callFunction(program, "foo", [makeInt(program, 0), makeInt(program, 85732)]), 85732);
2321 }
2322
2323 tests.intBitNot = function()
2324 {
2325     let program = doPrep(`
2326         int foo(int a)
2327         {
2328             return ~a;
2329         }
2330     `);
2331     checkInt(program, callFunction(program, "foo", [makeInt(program, 1)]), -2);
2332     checkInt(program, callFunction(program, "foo", [makeInt(program, 65535)]), -65536);
2333     checkInt(program, callFunction(program, "foo", [makeInt(program, -1)]), 0);
2334     checkInt(program, callFunction(program, "foo", [makeInt(program, 0)]), -1);
2335 }
2336
2337 tests.intLShift = function()
2338 {
2339     let program = doPrep(`
2340         int foo(int a, uint b)
2341         {
2342             return a << b;
2343         }
2344     `);
2345     checkInt(program, callFunction(program, "foo", [makeInt(program, 1), makeUint(program, 7)]), 128);
2346     checkInt(program, callFunction(program, "foo", [makeInt(program, 65535), makeUint(program, 2)]), 262140);
2347     checkInt(program, callFunction(program, "foo", [makeInt(program, -1), makeUint(program, 5)]), -32);
2348     checkInt(program, callFunction(program, "foo", [makeInt(program, 0), makeUint(program, 3)]), 0);
2349 }
2350
2351 tests.intRShift = function()
2352 {
2353     let program = doPrep(`
2354         int foo(int a, uint b)
2355         {
2356             return a >> b;
2357         }
2358     `);
2359     checkInt(program, callFunction(program, "foo", [makeInt(program, 1), makeUint(program, 7)]), 0);
2360     checkInt(program, callFunction(program, "foo", [makeInt(program, 65535), makeUint(program, 2)]), 16383);
2361     checkInt(program, callFunction(program, "foo", [makeInt(program, -1), makeUint(program, 5)]), -1);
2362     checkInt(program, callFunction(program, "foo", [makeInt(program, 0), makeUint(program, 3)]), 0);
2363 }
2364
2365 tests.uintBitAnd = function()
2366 {
2367     let program = doPrep(`
2368         uint foo(uint a, uint b)
2369         {
2370             return a & b;
2371         }
2372     `);
2373     checkUint(program, callFunction(program, "foo", [makeUint(program, 1), makeUint(program, 7)]), 1);
2374     checkUint(program, callFunction(program, "foo", [makeUint(program, 65535), makeUint(program, 42)]), 42);
2375     checkUint(program, callFunction(program, "foo", [makeUint(program, -1), makeUint(program, -7)]), 4294967289);
2376     checkUint(program, callFunction(program, "foo", [makeUint(program, 0), makeUint(program, 85732)]), 0);
2377 }
2378
2379 tests.uintBitOr = function()
2380 {
2381     let program = doPrep(`
2382         uint foo(uint a, uint b)
2383         {
2384             return a | b;
2385         }
2386     `);
2387     checkUint(program, callFunction(program, "foo", [makeUint(program, 1), makeUint(program, 7)]), 7);
2388     checkUint(program, callFunction(program, "foo", [makeUint(program, 65535), makeUint(program, 42)]), 65535);
2389     checkUint(program, callFunction(program, "foo", [makeUint(program, -1), makeUint(program, -7)]), 4294967295);
2390     checkUint(program, callFunction(program, "foo", [makeUint(program, 0), makeUint(program, 85732)]), 85732);
2391 }
2392
2393 tests.uintBitXor = function()
2394 {
2395     let program = doPrep(`
2396         uint foo(uint a, uint b)
2397         {
2398             return a ^ b;
2399         }
2400     `);
2401     checkUint(program, callFunction(program, "foo", [makeUint(program, 1), makeUint(program, 7)]), 6);
2402     checkUint(program, callFunction(program, "foo", [makeUint(program, 65535), makeUint(program, 42)]), 65493);
2403     checkUint(program, callFunction(program, "foo", [makeUint(program, -1), makeUint(program, -7)]), 6);
2404     checkUint(program, callFunction(program, "foo", [makeUint(program, 0), makeUint(program, 85732)]), 85732);
2405 }
2406
2407 tests.uintBitNot = function()
2408 {
2409     let program = doPrep(`
2410         uint foo(uint a)
2411         {
2412             return ~a;
2413         }
2414     `);
2415     checkUint(program, callFunction(program, "foo", [makeUint(program, 1)]), 4294967294);
2416     checkUint(program, callFunction(program, "foo", [makeUint(program, 65535)]), 4294901760);
2417     checkUint(program, callFunction(program, "foo", [makeUint(program, -1)]), 0);
2418     checkUint(program, callFunction(program, "foo", [makeUint(program, 0)]), 4294967295);
2419 }
2420
2421 tests.uintLShift = function()
2422 {
2423     let program = doPrep(`
2424         uint foo(uint a, uint b)
2425         {
2426             return a << b;
2427         }
2428     `);
2429     checkUint(program, callFunction(program, "foo", [makeUint(program, 1), makeUint(program, 7)]), 128);
2430     checkUint(program, callFunction(program, "foo", [makeUint(program, 65535), makeUint(program, 2)]), 262140);
2431     checkUint(program, callFunction(program, "foo", [makeUint(program, -1), makeUint(program, 5)]), 4294967264);
2432     checkUint(program, callFunction(program, "foo", [makeUint(program, 0), makeUint(program, 3)]), 0);
2433 }
2434
2435 tests.uintRShift = function()
2436 {
2437     let program = doPrep(`
2438         uint foo(uint a, uint b)
2439         {
2440             return a >> b;
2441         }
2442     `);
2443     checkUint(program, callFunction(program, "foo", [makeUint(program, 1), makeUint(program, 7)]), 0);
2444     checkUint(program, callFunction(program, "foo", [makeUint(program, 65535), makeUint(program, 2)]), 16383);
2445     checkUint(program, callFunction(program, "foo", [makeUint(program, -1), makeUint(program, 5)]), 134217727);
2446     checkUint(program, callFunction(program, "foo", [makeUint(program, 0), makeUint(program, 3)]), 0);
2447 }
2448
2449 tests.ucharBitAnd = function()
2450 {
2451     let program = doPrep(`
2452         uchar foo(uchar a, uchar b)
2453         {
2454             return a & b;
2455         }
2456     `);
2457     checkUchar(program, callFunction(program, "foo", [makeUchar(program, 1), makeUchar(program, 7)]), 1);
2458     checkUchar(program, callFunction(program, "foo", [makeUchar(program, 65535), makeUchar(program, 42)]), 42);
2459     checkUchar(program, callFunction(program, "foo", [makeUchar(program, -1), makeUchar(program, -7)]), 249);
2460     checkUchar(program, callFunction(program, "foo", [makeUchar(program, 0), makeUchar(program, 85732)]), 0);
2461 }
2462
2463 tests.ucharBitOr = function()
2464 {
2465     let program = doPrep(`
2466         uchar foo(uchar a, uchar b)
2467         {
2468             return a | b;
2469         }
2470     `);
2471     checkUchar(program, callFunction(program, "foo", [makeUchar(program, 1), makeUchar(program, 7)]), 7);
2472     checkUchar(program, callFunction(program, "foo", [makeUchar(program, 65535), makeUchar(program, 42)]), 255);
2473     checkUchar(program, callFunction(program, "foo", [makeUchar(program, -1), makeUchar(program, -7)]), 255);
2474     checkUchar(program, callFunction(program, "foo", [makeUchar(program, 0), makeUchar(program, 85732)]), 228);
2475 }
2476
2477 tests.ucharBitXor = function()
2478 {
2479     let program = doPrep(`
2480         uchar foo(uchar a, uchar b)
2481         {
2482             return a ^ b;
2483         }
2484     `);
2485     checkUchar(program, callFunction(program, "foo", [makeUchar(program, 1), makeUchar(program, 7)]), 6);
2486     checkUchar(program, callFunction(program, "foo", [makeUchar(program, 65535), makeUchar(program, 42)]), 213);
2487     checkUchar(program, callFunction(program, "foo", [makeUchar(program, -1), makeUchar(program, -7)]), 6);
2488     checkUchar(program, callFunction(program, "foo", [makeUchar(program, 0), makeUchar(program, 85732)]), 228);
2489 }
2490
2491 tests.ucharBitNot = function()
2492 {
2493     let program = doPrep(`
2494         uchar foo(uchar a)
2495         {
2496             return ~a;
2497         }
2498     `);
2499     checkUchar(program, callFunction(program, "foo", [makeUchar(program, 1)]), 254);
2500     checkUchar(program, callFunction(program, "foo", [makeUchar(program, 65535)]), 0);
2501     checkUchar(program, callFunction(program, "foo", [makeUchar(program, -1)]), 0);
2502     checkUchar(program, callFunction(program, "foo", [makeUchar(program, 0)]), 255);
2503 }
2504
2505 tests.ucharLShift = function()
2506 {
2507     let program = doPrep(`
2508         uchar foo(uchar a, uint b)
2509         {
2510             return a << b;
2511         }
2512     `);
2513     checkUchar(program, callFunction(program, "foo", [makeUchar(program, 1), makeUint(program, 7)]), 128);
2514     checkUchar(program, callFunction(program, "foo", [makeUchar(program, 65535), makeUint(program, 2)]), 252);
2515     checkUchar(program, callFunction(program, "foo", [makeUchar(program, -1), makeUint(program, 5)]), 224);
2516     checkUchar(program, callFunction(program, "foo", [makeUchar(program, 0), makeUint(program, 3)]), 0);
2517 }
2518
2519 tests.ucharRShift = function()
2520 {
2521     let program = doPrep(`
2522         uchar foo(uchar a, uint b)
2523         {
2524             return a >> b;
2525         }
2526     `);
2527     checkUchar(program, callFunction(program, "foo", [makeUchar(program, 1), makeUint(program, 7)]), 0);
2528     checkUchar(program, callFunction(program, "foo", [makeUchar(program, 65535), makeUint(program, 2)]), 255);
2529     checkUchar(program, callFunction(program, "foo", [makeUchar(program, -1), makeUint(program, 5)]), 255);
2530     checkUchar(program, callFunction(program, "foo", [makeUchar(program, 0), makeUint(program, 3)]), 0);
2531 }
2532
2533 tests.floatMath = function()
2534 {
2535     let program = doPrep(`
2536         bool foo()
2537         {
2538             return 42.5 == 42.5;
2539         }
2540         bool foo2()
2541         {
2542             return 42.5f == 42.5;
2543         }
2544         bool foo3()
2545         {
2546             return 42.5 == 42.5f;
2547         }
2548         bool foo4()
2549         {
2550             return 42.5f == 42.5f;
2551         }
2552         bool foo5()
2553         {
2554             return 42.5f == 42.5f;
2555         }
2556         float bar(float x)
2557         {
2558             return x;
2559         }
2560         float foo6()
2561         {
2562             return bar(7.5);
2563         }
2564         float foo7()
2565         {
2566             return bar(7.5f);
2567         }
2568         float foo9()
2569         {
2570             return float(7.5);
2571         }
2572         float foo10()
2573         {
2574             return float(7.5f);
2575         }
2576         float foo12()
2577         {
2578             return float(7);
2579         }
2580         float foo13()
2581         {
2582             float x = 7.5f;
2583             return float(x);
2584         }
2585     `);
2586     checkBool(program, callFunction(program, "foo", []), true);
2587     checkBool(program, callFunction(program, "foo2", []), true);
2588     checkBool(program, callFunction(program, "foo3", []), true);
2589     checkBool(program, callFunction(program, "foo4", []), true);
2590     checkBool(program, callFunction(program, "foo5", []), true);
2591     checkFloat(program, callFunction(program, "foo6", []), 7.5);
2592     checkFloat(program, callFunction(program, "foo7", []), 7.5);
2593     checkFloat(program, callFunction(program, "foo9", []), 7.5);
2594     checkFloat(program, callFunction(program, "foo10", []), 7.5);
2595     checkFloat(program, callFunction(program, "foo12", []), 7);
2596     checkFloat(program, callFunction(program, "foo13", []), 7.5);
2597     checkFail(
2598         () => doPrep(`
2599             int bar(int x)
2600             {
2601                 return x;
2602             }
2603             int foo()
2604             {
2605                 bar(4.);
2606             }
2607         `),
2608         (e) => e instanceof WTypeError);
2609     checkFail(
2610         () => doPrep(`
2611             int bar(int x)
2612             {
2613                 return x;
2614             }
2615             int foo()
2616             {
2617                 bar(4.f);
2618             }
2619         `),
2620         (e) => e instanceof WTypeError);
2621     checkFail(
2622         () => doPrep(`
2623             int bar(int x)
2624             {
2625                 return x;
2626             }
2627             int foo()
2628             {
2629                 bar(4.f);
2630             }
2631         `),
2632         (e) => e instanceof WTypeError);
2633     checkFail(
2634         () => doPrep(`
2635             uint bar(uint x)
2636             {
2637                 return x;
2638             }
2639             int foo()
2640             {
2641                 bar(4.);
2642             }
2643         `),
2644         (e) => e instanceof WTypeError);
2645     checkFail(
2646         () => doPrep(`
2647             uint bar(uint x)
2648             {
2649                 return x;
2650             }
2651             int foo()
2652             {
2653                 bar(4.f);
2654             }
2655         `),
2656         (e) => e instanceof WTypeError);
2657     checkFail(
2658         () => doPrep(`
2659             uint bar(uint x)
2660             {
2661                 return x;
2662             }
2663             int foo()
2664             {
2665                 bar(4.f);
2666             }
2667         `),
2668         (e) => e instanceof WTypeError);
2669 }
2670
2671 tests.booleanMath = function()
2672 {
2673     let program = doPrep(`
2674         bool foo()
2675         {
2676             return true && true;
2677         }
2678         bool foo2()
2679         {
2680             return true && false;
2681         }
2682         bool foo3()
2683         {
2684             return false && true;
2685         }
2686         bool foo4()
2687         {
2688             return false && false;
2689         }
2690         bool foo5()
2691         {
2692             return true || true;
2693         }
2694         bool foo6()
2695         {
2696             return true || false;
2697         }
2698         bool foo7()
2699         {
2700             return false || true;
2701         }
2702         bool foo8()
2703         {
2704             return false || false;
2705         }
2706     `);
2707     checkBool(program, callFunction(program, "foo", []), true);
2708     checkBool(program, callFunction(program, "foo2", []), false);
2709     checkBool(program, callFunction(program, "foo3", []), false);
2710     checkBool(program, callFunction(program, "foo4", []), false);
2711     checkBool(program, callFunction(program, "foo5", []), true);
2712     checkBool(program, callFunction(program, "foo6", []), true);
2713     checkBool(program, callFunction(program, "foo7", []), true);
2714     checkBool(program, callFunction(program, "foo8", []), false);
2715 }
2716
2717 tests.booleanShortcircuiting = function()
2718 {
2719     let program = doPrep(`
2720         bool set(thread int* ptr, int value, bool retValue) 
2721         { 
2722             *ptr = value; 
2723             return retValue; 
2724         }
2725         
2726         int andTrue()
2727         {
2728             int x;
2729             bool y = set(&x, 1, true) && set(&x, 2, false);
2730             return x; 
2731         }
2732         
2733         int andFalse()
2734         {
2735             int x;
2736             bool y = set(&x, 1, false) && set(&x, 2, false);
2737             return x; 
2738         }
2739         
2740         int orTrue()
2741         {
2742             int x;
2743             bool y = set(&x, 1, true) || set(&x, 2, false);
2744             return x; 
2745         }
2746         
2747         int orFalse()
2748         {
2749             int x;
2750             bool y = set(&x, 1, false) || set(&x, 2, false);
2751             return x; 
2752         }
2753     `);
2754
2755     checkInt(program, callFunction(program, "andTrue", []), 2);
2756     checkInt(program, callFunction(program, "andFalse", []), 1);
2757     checkInt(program, callFunction(program, "orTrue", []), 1);
2758     checkInt(program, callFunction(program, "orFalse", []), 2);
2759 }
2760
2761 tests.typedefArray = function()
2762 {
2763     let program = doPrep(`
2764         typedef ArrayTypedef = int[2];
2765         int foo()
2766         {
2767             ArrayTypedef arrayTypedef;
2768             return arrayTypedef[0];
2769         }
2770     `);
2771     checkInt(program, callFunction(program, "foo", []), 0);
2772 }
2773
2774 tests.shaderTypes = function()
2775 {
2776     checkFail(
2777         () => doPrep(`
2778             struct Foo {
2779                 float4 x;
2780             }
2781             vertex Foo bar()
2782             {
2783                 Foo result;
2784                 result.x = float4();
2785                 return result;
2786             }
2787             Foo foo() {
2788                 return bar();
2789             }
2790         `),
2791         (e) => e instanceof WTypeError);
2792     checkFail(
2793         () => doPrep(`
2794             vertex float bar()
2795             {
2796                 return 4.;
2797             }
2798         `),
2799         (e) => e instanceof WTypeError);
2800     checkFail(
2801         () => doPrep(`
2802             struct Foo {
2803                 float4 x;
2804             }
2805             vertex Foo bar(device Foo* x)
2806             {
2807                 return Foo();
2808             }
2809         `),
2810         (e) => e instanceof WTypeError);
2811     checkFail(
2812         () => doPrep(`
2813             struct Boo {
2814                 float4 x;
2815             }
2816             struct Foo {
2817                 float4 x;
2818                 device Boo* y;
2819             }
2820             vertex Foo bar()
2821             {
2822                 return Foo();
2823             }
2824         `),
2825         (e) => e instanceof WTypeError);
2826     checkFail(
2827         () => doPrep(`
2828             struct Foo {
2829                 float4 x;
2830             }
2831             struct Boo {
2832                 device Foo* y;
2833             }
2834             vertex Foo bar(Boo b)
2835             {
2836                 return Foo();
2837             }
2838         `),
2839         (e) => e instanceof WTypeError);
2840     checkFail(
2841         () => doPrep(`
2842             struct Foo {
2843                 float4 x;
2844             }
2845             vertex Foo bar(device Foo* x)
2846             {
2847                 return Foo();
2848             }
2849         `),
2850         (e) => e instanceof WTypeError);
2851     checkFail(
2852         () => doPrep(`
2853             struct Foo {
2854                 float4 x;
2855             }
2856             fragment Foo bar(Foo foo)
2857             {
2858                 return Foo();
2859             }
2860         `),
2861         (e) => e instanceof WTypeError);
2862     checkFail(
2863         () => doPrep(`
2864             struct Foo {
2865                 float4 x;
2866             }
2867             fragment Foo bar(device Foo* stageIn)
2868             {
2869                 return Foo();
2870             }
2871         `),
2872         (e) => e instanceof WTypeError);
2873     checkFail(
2874         () => doPrep(`
2875             struct Boo {
2876                 float4 x;
2877             }
2878             struct Foo {
2879                 float4 x;
2880                 device Boo* y;
2881             }
2882             fragment Boo bar(Foo stageIn)
2883             {
2884                 return boo();
2885             }
2886         `),
2887         (e) => e instanceof WTypeError);
2888     checkFail(
2889         () => doPrep(`
2890             struct Boo {
2891                 float4 x;
2892             }
2893             struct Foo {
2894                 float4 x;
2895                 device Boo* y;
2896             }
2897             fragment Foo bar(Boo stageIn)
2898             {
2899                 return Foo();
2900             }
2901         `),
2902         (e) => e instanceof WTypeError);
2903 }
2904
2905 tests.vectorTypeSyntax = function()
2906 {
2907     const program = doPrep(`
2908         int foo2()
2909         {
2910             int2 x;
2911             vector<int, 2> z = int2(3, 4);
2912             x = z;
2913             return x.y;
2914         }
2915
2916         int foo3()
2917         {
2918             int3 x;
2919             vector<int, 3> z = int3(3, 4, 5);
2920             x = z;
2921             return x.z;
2922         }
2923
2924         int foo4()
2925         {
2926             int4 x;
2927             vector<int,4> z = int4(3, 4, 5, 6);
2928             x = z;
2929             return x.w;
2930         }
2931
2932         bool vec2OperatorCast()
2933         {
2934             int2 x = vector<int,2>(1, 2);
2935             vector<int, 2> y = int2(1, 2);
2936             return x == y && x.x == 1 && x.y == 2 && y.x == 1 && y.y == 2;
2937         }`);
2938
2939     checkInt(program, callFunction(program, "foo2", []), 4);
2940     checkInt(program, callFunction(program, "foo3", []), 5);
2941     checkInt(program, callFunction(program, "foo4", []), 6);
2942
2943     checkBool(program, callFunction(program, "vec2OperatorCast", []), true);
2944 }
2945
2946 tests.builtinVectors = function()
2947 {
2948     let program = doPrep(`
2949         int foo()
2950         {
2951             int2 a = int2(3, 4);
2952             return a[0];
2953         }
2954         int foo2()
2955         {
2956             int2 a = int2(3, 4);
2957             int3 b = int3(a, 5);
2958             return b[1];
2959         }
2960         int foo3()
2961         {
2962             int3 a = int3(3, 4, 5);
2963             int4 b = int4(6, a);
2964             return b[1];
2965         }
2966         int foo4()
2967         {
2968             int2 a = int2(3, 4);
2969             int2 b = int2(5, 6);
2970             int4 c = int4(a, b);
2971             return c[2];
2972         }
2973         bool foo5()
2974         {
2975             int4 a = int4(3, 4, 5, 6);
2976             int2 b = int2(4, 5);
2977             int4 c = int4(3, b, 6);
2978             return a == c;
2979         }
2980         bool foo6()
2981         {
2982             int2 a = int2(4, 5);
2983             int3 b = int3(3, a);
2984             int3 c = int3(3, 4, 6);
2985             return b == c;
2986         }
2987         uint foou()
2988         {
2989             uint2 a = uint2(3, 4);
2990             return a[0];
2991         }
2992         uint foou2()
2993         {
2994             uint2 a = uint2(3, 4);
2995             uint3 b = uint3(a, 5);
2996             return b[1];
2997         }
2998         uint foou3()
2999         {
3000             uint3 a = uint3(3, 4, 5);
3001             uint4 b = uint4(6, a);
3002             return b[1];
3003         }
3004         uint foou4()
3005         {
3006             uint2 a = uint2(3, 4);
3007             uint2 b = uint2(5, 6);
3008             uint4 c = uint4(a, b);
3009             return c[2];
3010         }
3011         bool foou5()
3012         {
3013             uint4 a = uint4(3, 4, 5, 6);
3014             uint2 b = uint2(4, 5);
3015             uint4 c = uint4(3, b, 6);
3016             return a == c;
3017         }
3018         bool foou6()
3019         {
3020             uint2 a = uint2(4, 5);
3021             uint3 b = uint3(3, a);
3022             uint3 c = uint3(3, 4, 6);
3023             return b == c;
3024         }
3025         float foof()
3026         {
3027             float2 a = float2(3., 4.);
3028             return a[0];
3029         }
3030         float foof2()
3031         {
3032             float2 a = float2(3., 4.);
3033             float3 b = float3(a, 5.);
3034             return b[1];
3035         }
3036         float foof3()
3037         {
3038             float3 a = float3(3., 4., 5.);
3039             float4 b = float4(6., a);
3040             return b[1];
3041         }
3042         float foof4()
3043         {
3044             float2 a = float2(3., 4.);
3045             float2 b = float2(5., 6.);
3046             float4 c = float4(a, b);
3047             return c[2];
3048         }
3049         bool foof5()
3050         {
3051             float4 a = float4(3., 4., 5., 6.);
3052             float2 b = float2(4., 5.);
3053             float4 c = float4(3., b, 6.);
3054             return a == c;
3055         }
3056         bool foof6()
3057         {
3058             float2 a = float2(4., 5.);
3059             float3 b = float3(3., a);
3060             float3 c = float3(3., 4., 6.);
3061             return b == c;
3062         }
3063     `);
3064     checkInt(program, callFunction(program, "foo", []), 3);
3065     checkInt(program, callFunction(program, "foo2", []), 4);
3066     checkInt(program, callFunction(program, "foo3", []), 3);
3067     checkInt(program, callFunction(program, "foo4", []), 5);
3068     checkBool(program, callFunction(program, "foo5", []), true);
3069     checkBool(program, callFunction(program, "foo6", []), false);
3070     checkUint(program, callFunction(program, "foou", []), 3);
3071     checkUint(program, callFunction(program, "foou2", []), 4);
3072     checkUint(program, callFunction(program, "foou3", []), 3);
3073     checkUint(program, callFunction(program, "foou4", []), 5);
3074     checkBool(program, callFunction(program, "foou5", []), true);
3075     checkBool(program, callFunction(program, "foou6", []), false);
3076     checkFloat(program, callFunction(program, "foof", []), 3);
3077     checkFloat(program, callFunction(program, "foof2", []), 4);
3078     checkFloat(program, callFunction(program, "foof3", []), 3);
3079     checkFloat(program, callFunction(program, "foof4", []), 5);
3080     checkBool(program, callFunction(program, "foof5", []), true);
3081     checkBool(program, callFunction(program, "foof6", []), false);
3082 }
3083
3084 tests.builtinVectorGetters = function()
3085 {
3086     const typeNames = [ "uint", "int", "float" ];
3087     const sizes = [ 2, 3, 4 ];
3088     const elements = [ "x", "y", "z", "w" ];
3089     const initializerList = [ 1, 2, 3, 4 ];
3090
3091     let tests = [];
3092     let src = "";
3093     for (let typeName of typeNames) {
3094         for (let size of sizes) {
3095             for (let i = 0; i < size; i++) {
3096                 const functionName = `${typeName}${size}${elements[i]}`;
3097                 src += `${typeName} ${functionName}()
3098                         {
3099                             ${typeName}${size} x = ${typeName}${size}(${initializerList.slice(0, size).join(", ")});
3100                             return x.${elements[i]};
3101                         }
3102                         `;
3103                 tests.push({ type: typeName, name: functionName, expectation: initializerList[i] });
3104             }
3105         }
3106     }
3107
3108     let program = doPrep(src);
3109     const checkFuncs = {
3110         "uint": checkUint,
3111         "int": checkInt,
3112         "float": checkFloat
3113     };
3114     for (let test of tests) {
3115         const checkFunc = checkFuncs[test.type];
3116         checkFunc(program, callFunction(program, test.name, [], []), test.expectation);
3117     }
3118 }
3119
3120 tests.builtinVectorSetters = function()
3121 {
3122     const typeNames = [ "uint", "int", "float" ];
3123     const sizes = [ 2, 3, 4 ];
3124     const elements = [ "x", "y", "z", "w" ];
3125     const initializerList = [ 1, 2, 3, 4 ];
3126
3127     let tests = [];
3128     let src = "";
3129     for (let typeName of typeNames) {
3130         for (let size of sizes) {
3131             for (let i = 0; i < size; i++) {
3132                 const functionName = `${typeName}${size}${elements[i]}`;
3133                 src += `${typeName} ${functionName}()
3134                         {
3135                             ${typeName}${size} x = ${typeName}${size}(${initializerList.slice(0, size).join(", ")});
3136                             x.${elements[i]} = 34;
3137                             return x.${elements[i]};
3138                         }
3139                         `;
3140                 tests.push({ type: typeName, name: functionName, expectation: 34 });
3141             }
3142         }
3143     }
3144
3145     let program = doPrep(src);
3146     const checkFuncs = {
3147         "uint": checkUint,
3148         "int": checkInt,
3149         "float": checkFloat
3150     };
3151     for (let test of tests) {
3152         const checkFunc = checkFuncs[test.type];
3153         checkFunc(program, callFunction(program, test.name, [], []), test.expectation);
3154     }
3155 }
3156
3157 tests.builtinVectorIndexSetters = function()
3158 {
3159     const typeNames = [ "uint", "int", "float" ];
3160     const sizes = [ 2, 3, 4 ];
3161     const elements = [ "x", "y", "z", "w" ];
3162     const initializerList = [ 1, 2, 3, 4 ];
3163
3164     let tests = [];
3165     let src = "";
3166     for (let typeName of typeNames) {
3167         for (let size of sizes) {
3168             for (let i = 0; i < size; i++) {
3169                 const functionName = `${typeName}${size}${elements[i]}`;
3170                 src += `${typeName} ${functionName}()
3171                         {
3172                             ${typeName}${size} x = ${typeName}${size}(${initializerList.slice(0, size).join(", ")});
3173                             x[${i}] = 34;
3174                             return x[${i}];
3175                         }
3176                         `;
3177                 tests.push({ type: typeName, name: functionName, expectation: 34 });
3178             }
3179         }
3180     }
3181
3182     let program = doPrep(src);
3183     const checkFuncs = {
3184         "uint": checkUint,
3185         "int": checkInt,
3186         "float": checkFloat
3187     };
3188     for (let test of tests) {
3189         const checkFunc = checkFuncs[test.type];
3190         checkFunc(program, callFunction(program, test.name, [], []), test.expectation);
3191     }
3192 }
3193
3194 tests.simpleEnum = function()
3195 {
3196     let program = doPrep(`
3197         enum Foo {
3198             War,
3199             Famine,
3200             Pestilence,
3201             Death
3202         }
3203         Foo war()
3204         {
3205             return Foo.War;
3206         }
3207         Foo famine()
3208         {
3209             return Foo.Famine;
3210         }
3211         Foo pestilence()
3212         {
3213             return Foo.Pestilence;
3214         }
3215         Foo death()
3216         {
3217             return Foo.Death;
3218         }
3219         bool equals(Foo a, Foo b)
3220         {
3221             return a == b;
3222         }
3223         bool notEquals(Foo a, Foo b)
3224         {
3225             return a != b;
3226         }
3227         bool testSimpleEqual()
3228         {
3229             return equals(Foo.War, Foo.War);
3230         }
3231         bool testAnotherEqual()
3232         {
3233             return equals(Foo.Pestilence, Foo.Pestilence);
3234         }
3235         bool testNotEqual()
3236         {
3237             return equals(Foo.Famine, Foo.Death);
3238         }
3239         bool testSimpleNotEqual()
3240         {
3241             return notEquals(Foo.War, Foo.War);
3242         }
3243         bool testAnotherNotEqual()
3244         {
3245             return notEquals(Foo.Pestilence, Foo.Pestilence);
3246         }
3247         bool testNotNotEqual()
3248         {
3249             return notEquals(Foo.Famine, Foo.Death);
3250         }
3251         int intWar()
3252         {
3253             return int(war());
3254         }
3255         int intFamine()
3256         {
3257             return int(famine());
3258         }
3259         int intPestilence()
3260         {
3261             return int(pestilence());
3262         }
3263         int intDeath()
3264         {
3265             return int(death());
3266         }
3267         int warValue()
3268         {
3269             return war().value;
3270         }
3271         int famineValue()
3272         {
3273             return famine().value;
3274         }
3275         int pestilenceValue()
3276         {
3277             return pestilence().value;
3278         }
3279         int deathValue()
3280         {
3281             return death().value;
3282         }
3283         int warValueLiteral()
3284         {
3285             return Foo.War.value;
3286         }
3287         int famineValueLiteral()
3288         {
3289             return Foo.Famine.value;
3290         }
3291         int pestilenceValueLiteral()
3292         {
3293             return Foo.Pestilence.value;
3294         }
3295         int deathValueLiteral()
3296         {
3297             return Foo.Death.value;
3298         }
3299         Foo intWarBackwards()
3300         {
3301             return Foo(intWar());
3302         }
3303         Foo intFamineBackwards()
3304         {
3305             return Foo(intFamine());
3306         }
3307         Foo intPestilenceBackwards()
3308         {
3309             return Foo(intPestilence());
3310         }
3311         Foo intDeathBackwards()
3312         {
3313             return Foo(intDeath());
3314         }
3315     `);
3316     checkEnum(program, callFunction(program, "war", []), 0);
3317     checkEnum(program, callFunction(program, "famine", []), 1);
3318     checkEnum(program, callFunction(program, "pestilence", []), 2);
3319     checkEnum(program, callFunction(program, "death", []), 3);
3320     checkBool(program, callFunction(program, "testSimpleEqual", []), true);
3321     checkBool(program, callFunction(program, "testAnotherEqual", []), true);
3322     checkBool(program, callFunction(program, "testNotEqual", []), false);
3323     checkBool(program, callFunction(program, "testSimpleNotEqual", []), false);
3324     checkBool(program, callFunction(program, "testAnotherNotEqual", []), false);
3325     checkBool(program, callFunction(program, "testNotNotEqual", []), true);
3326     checkInt(program, callFunction(program, "intWar", []), 0);
3327     checkInt(program, callFunction(program, "intFamine", []), 1);
3328     checkInt(program, callFunction(program, "intPestilence", []), 2);
3329     checkInt(program, callFunction(program, "intDeath", []), 3);
3330     checkInt(program, callFunction(program, "warValue", []), 0);
3331     checkInt(program, callFunction(program, "famineValue", []), 1);
3332     checkInt(program, callFunction(program, "pestilenceValue", []), 2);
3333     checkInt(program, callFunction(program, "deathValue", []), 3);
3334     checkInt(program, callFunction(program, "warValueLiteral", []), 0);
3335     checkInt(program, callFunction(program, "famineValueLiteral", []), 1);
3336     checkInt(program, callFunction(program, "pestilenceValueLiteral", []), 2);
3337     checkInt(program, callFunction(program, "deathValueLiteral", []), 3);
3338     checkEnum(program, callFunction(program, "intWarBackwards", []), 0);
3339     checkEnum(program, callFunction(program, "intFamineBackwards", []), 1);
3340     checkEnum(program, callFunction(program, "intPestilenceBackwards", []), 2);
3341     checkEnum(program, callFunction(program, "intDeathBackwards", []), 3);
3342 }
3343
3344 tests.enumWithManualValues = function()
3345 {
3346     let program = doPrep(`
3347         enum Foo {
3348             War = 72,
3349             Famine = 0,
3350             Pestilence = 23,
3351             Death = -42
3352         }
3353         Foo war()
3354         {
3355             return Foo.War;
3356         }
3357         Foo famine()
3358         {
3359             return Foo.Famine;
3360         }
3361         Foo pestilence()
3362         {
3363             return Foo.Pestilence;
3364         }
3365         Foo death()
3366         {
3367             return Foo.Death;
3368         }
3369     `);
3370     checkEnum(program, callFunction(program, "war", []), 72);
3371     checkEnum(program, callFunction(program, "famine", []), 0);
3372     checkEnum(program, callFunction(program, "pestilence", []), 23);
3373     checkEnum(program, callFunction(program, "death", []), -42);
3374 }
3375
3376 tests.enumWithoutZero = function()
3377 {
3378     checkFail(
3379         () => doPrep(`
3380             enum Foo {
3381                 War = 72,
3382                 Famine = 64,
3383                 Pestilence = 23,
3384                 Death = -42
3385             }
3386         `),
3387         e => e instanceof WTypeError);
3388 }
3389
3390 tests.enumDuplicates = function()
3391 {
3392     checkFail(
3393         () => doPrep(`
3394             enum Foo {
3395                 War = -42,
3396                 Famine = 0,
3397                 Pestilence = 23,
3398                 Death = -42
3399             }
3400         `),
3401         e => e instanceof WTypeError);
3402 }
3403
3404 tests.enumWithSomeManualValues = function()
3405 {
3406     let program = doPrep(`
3407         enum Foo {
3408             War = 72,
3409             Famine,
3410             Pestilence = 0,
3411             Death
3412         }
3413         Foo war()
3414         {
3415             return Foo.War;
3416         }
3417         Foo famine()
3418         {
3419             return Foo.Famine;
3420         }
3421         Foo pestilence()
3422         {