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