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