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