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