From 2888ba14adb93f5ad73e0088c9def5ebf68dcab6 Mon Sep 17 00:00:00 2001 From: dcodeIO Date: Sat, 30 Dec 2017 05:11:58 +0100 Subject: [PATCH] PSON decoder example using namespaced imports --- README.md | 5 +- examples/.gitignore | 2 + .../game-of-life/assembly/game-of-life.ts | 33 +-- examples/i64-polyfill/assembly/i64.ts | 4 +- examples/pson/README.md | 19 ++ examples/pson/assembly/pson.ts | 156 +++++++++++ examples/pson/assembly/tsconfig.json | 6 + examples/pson/index.js | 71 +++++ examples/pson/package.json | 14 + examples/pson/tests/index.js | 24 ++ src/ast.ts | 7 +- src/compiler.ts | 9 +- src/module.ts | 28 +- tests/compiler/assert.ts | 2 + tests/compiler/assert.wast | 18 ++ tests/compiler/binary.ts | 10 +- tests/compiler/builtins.optimized.wast | 6 +- tests/compiler/builtins.ts | 23 +- tests/compiler/builtins.wast | 8 +- tests/compiler/do.optimized.wast | 142 ++++++++-- tests/compiler/do.ts | 37 ++- tests/compiler/do.wast | 242 +++++++++++++--- tests/compiler/export.optimized.wast | 1 + tests/compiler/export.ts | 1 + tests/compiler/export.wast | 6 + tests/compiler/for.ts | 4 +- tests/compiler/game-of-life.wast | 212 +++++++------- tests/compiler/import.wast | 5 +- tests/compiler/infer-type.ts | 22 +- tests/compiler/logical.ts | 8 +- tests/compiler/memcpy.ts | 6 +- tests/compiler/namespace.ts | 2 +- tests/compiler/portable-conversions.ts | 8 +- tests/compiler/reexport.optimized.wast | 2 +- tests/compiler/reexport.wast | 5 +- tests/compiler/ternary.ts | 2 +- tests/compiler/tlsf.ts | 4 +- tests/compiler/unary.ts | 8 +- tests/compiler/while.optimized.wast | 152 ++++++++-- tests/compiler/while.ts | 42 ++- tests/compiler/while.wast | 263 ++++++++++++++++-- 41 files changed, 1283 insertions(+), 336 deletions(-) create mode 100644 examples/pson/README.md create mode 100644 examples/pson/assembly/pson.ts create mode 100644 examples/pson/assembly/tsconfig.json create mode 100644 examples/pson/index.js create mode 100644 examples/pson/package.json create mode 100644 examples/pson/tests/index.js diff --git a/README.md b/README.md index 2e78bac1..20018864 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Build Status](https://travis-ci.org/AssemblyScript/assemblyscript.svg?branch=master)](https://travis-ci.org/AssemblyScript/assemblyscript) -**AssemblyScript** compiles strictly typed [TypeScript](http://www.typescriptlang.org) to [WebAssembly](http://webassembly.org) using [Binaryen](https://github.com/WebAssembly/binaryen). Unlike more complex toolchains, `asc` generates minimal WebAssembly modules while being just an `npm install` away. +**AssemblyScript** compiles strictly typed [TypeScript](http://www.typescriptlang.org) to [WebAssembly](http://webassembly.org) using [Binaryen](https://github.com/WebAssembly/binaryen). Unlike other toolchains, `asc` generates minimal WebAssembly modules while being just an `npm install` away. Examples -------- @@ -16,6 +16,9 @@ A few early examples to get an idea: * **[i64 polyfill](./examples/i64-polyfill)**
Exposes WebAssembly's i64 operations to JavaScript using 32-bit integers (low and high bits). +* **[PSON decoder](./examples/pson)**
+ A PSON decoder implemented in AssemblyScript. + Or browse the [compiler tests](./tests/compiler) for a more in-depth overview of what's supported already. Getting started diff --git a/examples/.gitignore b/examples/.gitignore index 2a0c6b29..55fb3e2f 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -1,3 +1,5 @@ *.wast *.wasm node_modules/ +npm-debug.log +package-lock.json diff --git a/examples/game-of-life/assembly/game-of-life.ts b/examples/game-of-life/assembly/game-of-life.ts index bd4c7baf..d400fcce 100644 --- a/examples/game-of-life/assembly/game-of-life.ts +++ b/examples/game-of-life/assembly/game-of-life.ts @@ -1,8 +1,8 @@ // A simplified version of the game of life as seen on http://dcode.io -var w: u32; // width -var h: u32; // height -var s: u32; // total size +var w: u32, // width + h: u32, // height + s: u32; // total size /** Initializes width and height. */ export function init(w_: u32, h_: u32): void { @@ -13,21 +13,18 @@ export function init(w_: u32, h_: u32): void { /** Performs one step. */ export function step(): void { - var y: u32, ym1: u32, yp1: u32; // y, y-1 and y+1 - var x: u32, xm1: u32, xp1: u32; // x, x-1 and x+1 - var hm1: u32 = h - 1, wm1: u32 = w - 1; - var n: u32, v: u8, c: u32 = 0; - for (y = 0; y < h; ++y) { - ym1 = select(hm1, y - 1, y == 0); - yp1 = select(0, y + 1, y == hm1); - for (x = 0; x < w; ++x) { - xm1 = select(wm1, x - 1, x == 0); - xp1 = select(0, x + 1, x == wm1); - n = load(ym1 * w + xm1) + load(ym1 * w + x) + load(ym1 * w + xp1) - + load(y * w + xm1) + load(y * w + xp1) - + load(yp1 * w + xm1) + load(yp1 * w + x) + load(yp1 * w + xp1); - v = load(y * w + x); - if (v) { + var hm1 = h - 1, + wm1 = w - 1; + for (var y: u32 = 0; y < h; ++y) { + var ym1 = select(hm1, y - 1, y == 0), + yp1 = select(0, y + 1, y == hm1); + for (var x: u32 = 0; x < w; ++x) { + var xm1 = select(wm1, x - 1, x == 0), + xp1 = select(0, x + 1, x == wm1); + var n = load(ym1 * w + xm1) + load(ym1 * w + x) + load(ym1 * w + xp1) + + load(y * w + xm1) + load(y * w + xp1) + + load(yp1 * w + xm1) + load(yp1 * w + x) + load(yp1 * w + xp1); + if (load(y * w + x)) { if (n < 2 || n > 3) store(s + y * w + x, 0); } else if (n == 3) diff --git a/examples/i64-polyfill/assembly/i64.ts b/examples/i64-polyfill/assembly/i64.ts index 769ca810..36e26b90 100644 --- a/examples/i64-polyfill/assembly/i64.ts +++ b/examples/i64-polyfill/assembly/i64.ts @@ -1,5 +1,5 @@ -let lo: u32; -let hi: u32; +var lo: u32, + hi: u32; export function getLo(): u32 { return lo; diff --git a/examples/pson/README.md b/examples/pson/README.md new file mode 100644 index 00000000..776ec5aa --- /dev/null +++ b/examples/pson/README.md @@ -0,0 +1,19 @@ +PSON decoder in WebAssembly +=========================== + +An [AssemblyScript](http://assemblyscript.org) example. Decodes a [PSON](https://github.com/dcodeIO/PSON) encoded buffer. + +Instructions +------------ + +To build [assembly/pson.ts](./assembly/pson.ts) to an untouched and an optimized `.wasm` including their respective `.wast` representations, run: + +``` +$> npm run build +``` + +Afterwards, to run the included test, do: + +``` +$> npm test +``` diff --git a/examples/pson/assembly/pson.ts b/examples/pson/assembly/pson.ts new file mode 100644 index 00000000..fc6ca112 --- /dev/null +++ b/examples/pson/assembly/pson.ts @@ -0,0 +1,156 @@ +const enum Token { + ZERO = 0x00, + MAX = 0xEF, + NULL = 0xf0, + TRUE = 0xf1, + FALSE = 0xf2, + EOBJECT = 0xf3, + EARRAY = 0xf4, + ESTRING = 0xf5, + OBJECT = 0xf6, + ARRAY = 0xf7, + INTEGER = 0xf8, + LONG = 0xf9, + FLOAT = 0xfa, + DOUBLE = 0xfb, + STRING = 0xfc, + STRING_ADD = 0xfd, + STRING_GET = 0xfe, + BINARY = 0xff +} + +namespace pson { + export declare function onNull(): void; + export declare function onTrue(): void; + export declare function onFalse(): void; + export declare function onEObject(): void; + export declare function onEArray(): void; + export declare function onEString(): void; + export declare function onObject(size: u32): void; + export declare function onArray(size: u32): void; + export declare function onInteger(value: i32): void; + export declare function onLong(valueLow: i32, valueHigh: i32): void; + export declare function onFloat(value: f32): void; + export declare function onDouble(value: f64): void; + export declare function onString(offset: usize, length: u32): void; + export declare function onBinary(offset: usize, length: u32): void; + export declare function onTruncated(): void; +} + +var offset: usize = 0; + +export function decode(length: usize): void { + offset = 0; + while (offset < length) + decodeValue(); + if (offset != length) + pson.onTruncated(); +} + +function decodeValue(): void { + var token: u32 = load(offset++); + var size: u32; + var long: u64; + switch (token) { + + case Token.NULL: + pson.onNull(); + break; + + case Token.TRUE: + pson.onTrue(); + break; + + case Token.FALSE: + pson.onFalse(); + break; + + case Token.EOBJECT: + pson.onEObject(); + break; + + case Token.EARRAY: + pson.onEArray(); + break; + + case Token.ESTRING: + pson.onEString(); + break; + + case Token.OBJECT: + pson.onObject(size = readVarint32()); + while (size--) { + decodeValue(); + decodeValue(); + } + break; + + case Token.ARRAY: + pson.onArray(size = readVarint32()); + while (size--) + decodeValue(); + break; + + case Token.INTEGER: + pson.onInteger(((size = readVarint32()) >> 1) ^ -(size & 1)); + break; + + case Token.LONG: + long = ((long = readVarint64()) >> 1) ^ -(long & 1); + pson.onLong(long, (long >>> 32)); + break; + + case Token.FLOAT: + pson.onFloat(load(offset)); + offset += 4; + break; + + case Token.DOUBLE: + pson.onDouble(load(offset)); + offset += 8; + break; + + case Token.STRING: + size = readVarint32(); + pson.onString(offset, size); + offset += size; + break; + + case Token.STRING_ADD: + case Token.STRING_GET: + // could be implemented via imports as well, but isn't necessary for this example + throw new Error("not implemented"); + + case Token.BINARY: + size = readVarint32(); + pson.onBinary(offset, size); + offset += size; + break; + + default: // small integer? + if (token > Token.MAX) + throw new Error("unexpected token"); + pson.onInteger((token >> 1) ^ -(token & 1)); + break; + } +} + +function readVarint32(): u32 { + var value: u32 = 0; + var shift: u32 = 0; + do { + var b = load(offset++); + value |= (b & 0x7f) << (7 * shift++); + } while (b & 0x80); + return value; +} + +function readVarint64(): u64 { + var value: u64 = 0; + var shift: u64 = 0; + do { + var b = load(offset++); + value |= (b & 0x7f) << (7 * shift++); + } while (b & 0x80); + return value; +} diff --git a/examples/pson/assembly/tsconfig.json b/examples/pson/assembly/tsconfig.json new file mode 100644 index 00000000..6e52b21c --- /dev/null +++ b/examples/pson/assembly/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "../../../std/assembly.json", + "include": [ + "./**/*.ts" + ] +} diff --git a/examples/pson/index.js b/examples/pson/index.js new file mode 100644 index 00000000..e0a94256 --- /dev/null +++ b/examples/pson/index.js @@ -0,0 +1,71 @@ +var fs = require("fs"); + +// Define imports. Just logs to console for the sake of this example. +var pson = { + onNull: function() { + console.log("null"); + }, + onTrue: function() { + console.log("true"); + }, + onFalse: function() { + console.log("false"); + }, + onEObject: function() { + console.log("{}"); + }, + onEArray: function() { + console.log("[]"); + }, + onEString: function() { + console.log("\"\""); + }, + onObject: function(size) { + console.log("{" + size + "}") + }, + onArray: function(size) { + console.log("[" + size + "]"); + }, + onInteger: function(value) { + console.log("integer: " + value); + }, + onLong: function(valueLow, valueHigh) { + console.log("long: " + valueLow + ", " + valueHigh); + }, + onFloat: function(value) { + console.log("float: " + value); + }, + onDouble: function(value) { + console.log("double: " + value); + }, + onString: function(offset, length) { + console.log("string(length=" + length + "): " + new Buffer(mem.slice(offset, offset + length)).toString()); + }, + onBinary: function(offset, length) { + console.log("binary(length=" + length + "): " + mem.slice(offset, offset + length)); + }, + onTruncated: function() { + console.log("buffer is truncated :-("); + } +}; + +// Instantiate the module +var mod = new WebAssembly.Module(fs.readFileSync(__dirname + "/pson.optimized.wasm")); +var ins = new WebAssembly.Instance(mod, { pson: pson }); +var mem = new Uint8Array(ins.exports.memory.buffer); + +// Export API +exports.decode = function(buffer) { + + // grow memory if necessary + if (mem.length < buffer.length) { + ins.exports.memory.grow(Math.ceil((buffer.length - mem.length) / 65536)); + mem = new Uint8Array(ins.exports.memory.buffer); + } + + // copy buffer to memory + mem.set(buffer); + + // start decoding (calls the imports defined above) + ins.exports.decode(buffer.length); +} diff --git a/examples/pson/package.json b/examples/pson/package.json new file mode 100644 index 00000000..6499903d --- /dev/null +++ b/examples/pson/package.json @@ -0,0 +1,14 @@ +{ + "name": "@assemblyscript/pson-example", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "npm run build:untouched && npm run build:optimized", + "build:untouched": "asc assembly/pson.ts -b pson.untouched.wasm -t pson.untouched.wast --validate", + "build:optimized": "asc -O assembly/pson.ts -b pson.optimized.wasm -t pson.optimized.wast --validate", + "test": "node tests" + }, + "devDependencies": { + "pson": "^2.0.0" + } +} diff --git a/examples/pson/tests/index.js b/examples/pson/tests/index.js new file mode 100644 index 00000000..8110f5b2 --- /dev/null +++ b/examples/pson/tests/index.js @@ -0,0 +1,24 @@ +var Long = require("long"); + +var psonJS = require("pson"); +var psonWASM = require(".."); + +// encode in JS +var buf = new psonJS.Encoder().encode({ + emptyObject: {}, + emptyArray: [], + emptyString: "", + object: { + aSmallInt: 42, + anInt: 9000, + aLong: Long.MIN_VALUE.add(1) + }, + array: [ + 0.25, // fits into float + 0.1 // always a double + ], + binary: Buffer.from([1, 2, 3]) +}).toBuffer(); + +// decode in WASM +psonWASM.decode(buf); diff --git a/src/ast.ts b/src/ast.ts index e822d19d..59e9865f 100644 --- a/src/ast.ts +++ b/src/ast.ts @@ -2182,7 +2182,7 @@ function builderEndsWith(sb: string[], code: CharCode): bool { } /** Converts a string to its literal representation including quotes. */ -export function stringToLiteral(str: string): string { +export function stringToLiteral(str: string, singleQuoted: bool = false): string { var ret = new Array(); var off = 0; for (var i = 0, k = str.length; i < k;) { @@ -2263,11 +2263,12 @@ export function stringToLiteral(str: string): string { break; } } + var quote = singleQuoted ? "'" : "\""; if (off == 0) { assert(ret.length == 0); - return "\"" + str + "\""; + return quote + str + quote; } if (i > off) ret.push(str.substring(off, i)); - return "\"" + ret.join("") + "\""; + return quote + ret.join("") + quote; } diff --git a/src/compiler.ts b/src/compiler.ts index 5dcf651b..fe84e48c 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -840,8 +840,8 @@ export class Compiler extends DiagnosticEmitter { compileDoStatement(statement: DoStatement): ExpressionRef { var label = this.currentFunction.enterBreakContext(); - var condition = this.compileExpression(statement.condition, Type.i32); var body = this.compileStatement(statement.statement); + var condition = this.compileExpression(statement.condition, Type.i32); this.currentFunction.leaveBreakContext(); var breakLabel = "break|" + label; var continueLabel = "continue|" + label; @@ -1494,8 +1494,11 @@ export class Compiler extends DiagnosticEmitter { case Token.PERCENT: left = this.compileExpression(expression.left, contextualType, ConversionKind.NONE); right = this.compileExpression(expression.right, this.currentType); - if (this.currentType.isAnyFloat) - throw new Error("not implemented"); // TODO: internal fmod, possibly simply imported from JS + if (this.currentType.isAnyFloat) { + // TODO: internal fmod, possibly simply imported from JS + this.error(DiagnosticCode.Operation_not_supported, expression.range); + return this.module.createUnreachable(); + } op = this.currentType.isSignedInteger ? this.currentType.isLongInteger ? BinaryOp.RemI64 diff --git a/src/module.ts b/src/module.ts index e4531792..6b1d9804 100644 --- a/src/module.ts +++ b/src/module.ts @@ -15,7 +15,7 @@ export type ImportRef = usize; export type ExportRef = usize; export type Index = u32; - export enum NativeType { +export enum NativeType { None = _BinaryenTypeNone(), I32 = _BinaryenTypeInt32(), I64 = _BinaryenTypeInt64(), @@ -796,7 +796,7 @@ export class Module { } // currently supports side effect free expressions only - cloneExpression(expr: ExpressionRef, noSideEffects: bool = false, maxDepth: i32 = 0x7fffffff): ExpressionRef { + cloneExpression(expr: ExpressionRef, noSideEffects: bool = false, maxDepth: i32 = i32.MAX_VALUE): ExpressionRef { if (this.noEmit || maxDepth < 0) return 0; var nested1: ExpressionRef, @@ -900,28 +900,24 @@ export class Relooper { } } -export function setAPITracing(on: bool): void { - _BinaryenSetAPITracing(on ? 1 : 0); -} - // helpers // can't do stack allocation here: STACKTOP is a global in WASM but a hidden variable in asm.js function allocU8Array(u8s: Uint8Array | null): usize { if (!u8s) return 0; - var ptr = Heap.allocate((u8s).length); + var ptr = Heap.allocate(u8s.length); var idx = ptr; - for (var i = 0, k = (u8s).length; i < k; ++i) - store(idx++, (u8s)[i]); + for (var i = 0, k = u8s.length; i < k; ++i) + store(idx++, u8s[i]); return ptr; } function allocI32Array(i32s: i32[] | null): usize { if (!i32s) return 0; - var ptr = Heap.allocate((i32s).length << 2); + var ptr = Heap.allocate(i32s.length << 2); var idx = ptr; - for (var i = 0, k = (i32s).length; i < k; ++i) { - var val = (i32s)[i]; + for (var i = 0, k = i32s.length; i < k; ++i) { + var val = i32s[i]; // store(idx, val) is not portable store(idx , ( val & 0xff) as u8); store(idx + 1, ((val >> 8) & 0xff) as u8); @@ -956,12 +952,12 @@ function stringLengthUTF8(str: string): usize { function allocString(str: string | null): usize { if (str == null) return 0; - var ptr = Heap.allocate(stringLengthUTF8((str)) + 1); + var ptr = Heap.allocate(stringLengthUTF8(str) + 1); var idx = ptr; - for (var i = 0, k = (str).length; i < k; ++i) { - var u = (str).charCodeAt(i); + for (var i = 0, k = str.length; i < k; ++i) { + var u = str.charCodeAt(i); if (u >= 0xD800 && u <= 0xDFFF && i + 1 < k) - u = 0x10000 + ((u & 0x3FF) << 10) | ((str).charCodeAt(++i) & 0x3FF); + u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt(++i) & 0x3FF); if (u <= 0x7F) store(idx++, u as u8); else if (u <= 0x7FF) { diff --git a/tests/compiler/assert.ts b/tests/compiler/assert.ts index 4d1656bd..5dfd0d5f 100644 --- a/tests/compiler/assert.ts +++ b/tests/compiler/assert.ts @@ -1 +1,3 @@ assert(true); +assert(1 == 1); +assert(0.5 > 0.4); diff --git a/tests/compiler/assert.wast b/tests/compiler/assert.wast index 0d7ca8ee..79f48403 100644 --- a/tests/compiler/assert.wast +++ b/tests/compiler/assert.wast @@ -11,6 +11,24 @@ ) (unreachable) ) + (if + (i32.eqz + (i32.eq + (i32.const 1) + (i32.const 1) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (f64.gt + (f64.const 0.5) + (f64.const 0.4) + ) + ) + (unreachable) + ) ) ) (; diff --git a/tests/compiler/binary.ts b/tests/compiler/binary.ts index 9a5f872c..74398742 100644 --- a/tests/compiler/binary.ts +++ b/tests/compiler/binary.ts @@ -1,6 +1,6 @@ -let b: bool = false; +var b = false; -let i: i32 = 0; +var i: i32 = 0; i < 1; i > 1; @@ -49,7 +49,7 @@ i &= 1; i |= 1; i ^= 1; -let I: i64 = 0; +var I: i64 = 0; I < 1; I > 1; @@ -98,7 +98,7 @@ I &= 1; I |= 1; I ^= 1; -let f: f32 = 0; +var f: f32 = 0; f < 1; f > 1; @@ -129,7 +129,7 @@ f -= 1; f *= 1; // f %= 1; -let F: f64 = 0; +var F: f64 = 0; F < 1; F > 1; diff --git a/tests/compiler/builtins.optimized.wast b/tests/compiler/builtins.optimized.wast index ed3daf84..b9262be6 100644 --- a/tests/compiler/builtins.optimized.wast +++ b/tests/compiler/builtins.optimized.wast @@ -7,9 +7,13 @@ (global $builtins/F (mut f64) (f64.const 0)) (global $builtins/s (mut i32) (i32.const 0)) (memory $0 1) + (export "test" (func $builtins/test)) (export "memory" (memory $0)) (start $start) - (func $start (; 0 ;) (type $v) + (func $builtins/test (; 0 ;) (type $v) + (nop) + ) + (func $start (; 1 ;) (type $v) (local $0 f32) (local $1 f64) (local $2 i32) diff --git a/tests/compiler/builtins.ts b/tests/compiler/builtins.ts index da7ace9d..d7b00df0 100644 --- a/tests/compiler/builtins.ts +++ b/tests/compiler/builtins.ts @@ -1,8 +1,8 @@ -let b: bool; +var b: bool; // integers -let i: i32; +var i: i32; clz(1); ctz(1); @@ -22,7 +22,7 @@ i = abs(-42); assert(i == 42); i = max(1, 2); assert(i == 2); i = min(1, 2); assert(i == 1); -let I: i64; +var I: i64; clz(1); ctz(1); @@ -42,7 +42,7 @@ I = min(1, 2); assert(i == 1); // floats -let f: f32; +var f: f32; NaN; Infinity; @@ -72,7 +72,7 @@ f = trunc(1.25); b = isNaN(1.25); b = isFinite(1.25); -let F: f64; +var F: f64; NaN; Infinity; @@ -129,7 +129,7 @@ F = reinterpret(25); // host -let s: usize; +var s: usize; current_memory(); grow_memory(1); @@ -179,8 +179,9 @@ assert(isFinite(0)); // imported -// TODO: Can't be interpreted due to 'Fatal: callImport: unknown import: env.parseInt' - -// parseInt(0); -// parseInt(0, 10); -// parseFloat(0); +export function test(): void { + // cannot be interpreted + // parseInt("01"); + // parseInt("1", 10); + // parseFloat("1.0"); +} diff --git a/tests/compiler/builtins.wast b/tests/compiler/builtins.wast index 854d6257..2c0c363f 100644 --- a/tests/compiler/builtins.wast +++ b/tests/compiler/builtins.wast @@ -8,9 +8,12 @@ (global $builtins/s (mut i32) (i32.const 0)) (global $HEAP_BASE i32 (i32.const 4)) (memory $0 1) + (export "test" (func $builtins/test)) (export "memory" (memory $0)) (start $start) - (func $start (; 0 ;) (type $v) + (func $builtins/test (; 0 ;) (type $v) + ) + (func $start (; 1 ;) (type $v) (local $0 i32) (local $1 i32) (local $2 i64) @@ -1085,6 +1088,7 @@ GLOBAL: builtins/f GLOBAL: builtins/F GLOBAL: builtins/s + FUNCTION_PROTOTYPE: builtins/test [program.exports] - + FUNCTION_PROTOTYPE: builtins/test ;) diff --git a/tests/compiler/do.optimized.wast b/tests/compiler/do.optimized.wast index 9d4d7f5e..44389967 100644 --- a/tests/compiler/do.optimized.wast +++ b/tests/compiler/do.optimized.wast @@ -1,42 +1,132 @@ (module - (type $iv (func (param i32))) + (type $v (func)) + (global $do/n (mut i32) (i32.const 10)) + (global $do/m (mut i32) (i32.const 0)) + (global $do/o (mut i32) (i32.const 0)) (memory $0 1) - (export "loopDo" (func $do/loopDo)) - (export "loopDoInDo" (func $do/loopDoInDo)) (export "memory" (memory $0)) - (func $do/loopDo (; 0 ;) (type $iv) (param $0 i32) + (start $start) + (func $start (; 0 ;) (type $v) + (local $0 i32) (loop $continue|0 - (br_if $continue|0 - (tee_local $0 - (i32.sub - (get_local $0) - (i32.const 1) - ) - ) - ) - ) - ) - (func $do/loopDoInDo (; 1 ;) (type $iv) (param $0 i32) - (loop $continue|0 - (set_local $0 + (set_global $do/n (i32.sub - (get_local $0) + (get_global $do/n) (i32.const 1) ) ) - (loop $continue|1 - (br_if $continue|1 - (tee_local $0 - (i32.sub - (get_local $0) - (i32.const 1) - ) - ) + (set_global $do/m + (i32.add + (get_global $do/m) + (i32.const 1) ) ) (br_if $continue|0 + (get_global $do/n) + ) + ) + (if + (get_global $do/n) + (unreachable) + ) + (if + (i32.ne + (get_global $do/m) + (i32.const 10) + ) + (unreachable) + ) + (set_global $do/n + (i32.const 10) + ) + (loop $continue|1 + (set_global $do/n + (i32.sub + (tee_local $0 + (get_global $do/n) + ) + (i32.const 1) + ) + ) + (br_if $continue|1 (get_local $0) ) ) + (if + (i32.ne + (get_global $do/n) + (i32.const -1) + ) + (unreachable) + ) + (set_global $do/n + (i32.const 10) + ) + (set_global $do/m + (i32.const 0) + ) + (loop $continue|2 + (set_global $do/n + (i32.sub + (get_global $do/n) + (i32.const 1) + ) + ) + (set_global $do/m + (i32.add + (get_global $do/m) + (i32.const 1) + ) + ) + (loop $continue|3 + (set_global $do/n + (i32.sub + (get_global $do/n) + (i32.const 1) + ) + ) + (set_global $do/o + (i32.add + (get_global $do/o) + (i32.const 1) + ) + ) + (br_if $continue|3 + (get_global $do/n) + ) + ) + (if + (get_global $do/n) + (unreachable) + ) + (if + (i32.ne + (get_global $do/o) + (i32.const 9) + ) + (unreachable) + ) + (br_if $continue|2 + (get_global $do/n) + ) + ) + (if + (get_global $do/n) + (unreachable) + ) + (if + (i32.ne + (get_global $do/m) + (i32.const 1) + ) + (unreachable) + ) + (if + (i32.ne + (get_global $do/o) + (i32.const 9) + ) + (unreachable) + ) ) ) diff --git a/tests/compiler/do.ts b/tests/compiler/do.ts index 38c9425b..38091a7e 100644 --- a/tests/compiler/do.ts +++ b/tests/compiler/do.ts @@ -1,14 +1,29 @@ -export function loopDo(n: i32): void { - do { - n = n - 1; - } while (n); -} +var n = 10; +var m = 0; +do { + n--; + m++; +} while (n); +assert(n == 0); +assert(m == 10); -export function loopDoInDo(n: i32): void { +n = 10; +do; while(n--); +assert(n == -1); + +n = 10; +m = 0; +var o = 0; +do { + n--; + m++; do { - n = n - 1; - do { - n = n - 1; - } while (n); + n--; + o++; } while (n); -} + assert(n == 0); + assert(o == 9); +} while (n); +assert(n == 0); +assert(m == 1); +assert(o == 9); diff --git a/tests/compiler/do.wast b/tests/compiler/do.wast index 864e2154..96ce67a7 100644 --- a/tests/compiler/do.wast +++ b/tests/compiler/do.wast @@ -1,54 +1,228 @@ (module - (type $iv (func (param i32))) + (type $v (func)) + (global $do/n (mut i32) (i32.const 10)) + (global $do/m (mut i32) (i32.const 0)) + (global $do/o (mut i32) (i32.const 0)) (global $HEAP_BASE i32 (i32.const 4)) (memory $0 1) - (export "loopDo" (func $do/loopDo)) - (export "loopDoInDo" (func $do/loopDoInDo)) (export "memory" (memory $0)) - (func $do/loopDo (; 0 ;) (type $iv) (param $0 i32) - (block $break|0 - (loop $continue|0 - (set_local $0 - (i32.sub - (get_local $0) - (i32.const 1) - ) - ) - (br_if $continue|0 - (get_local $0) - ) - ) - ) - ) - (func $do/loopDoInDo (; 1 ;) (type $iv) (param $0 i32) + (start $start) + (func $start (; 0 ;) (type $v) + (local $0 i32) (block $break|0 (loop $continue|0 (block - (set_local $0 - (i32.sub - (get_local $0) - (i32.const 1) - ) - ) - (block $break|1 - (loop $continue|1 + (drop + (block (result i32) (set_local $0 + (get_global $do/n) + ) + (set_global $do/n (i32.sub (get_local $0) (i32.const 1) ) ) - (br_if $continue|1 - (get_local $0) + (get_local $0) + ) + ) + (drop + (block (result i32) + (set_local $0 + (get_global $do/m) ) + (set_global $do/m + (i32.add + (get_local $0) + (i32.const 1) + ) + ) + (get_local $0) ) ) ) (br_if $continue|0 - (get_local $0) + (get_global $do/n) ) ) ) + (if + (i32.eqz + (i32.eq + (get_global $do/n) + (i32.const 0) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (get_global $do/m) + (i32.const 10) + ) + ) + (unreachable) + ) + (set_global $do/n + (i32.const 10) + ) + (block $break|1 + (loop $continue|1 + (nop) + (br_if $continue|1 + (block (result i32) + (set_local $0 + (get_global $do/n) + ) + (set_global $do/n + (i32.sub + (get_local $0) + (i32.const 1) + ) + ) + (get_local $0) + ) + ) + ) + ) + (if + (i32.eqz + (i32.eq + (get_global $do/n) + (i32.sub + (i32.const 0) + (i32.const 1) + ) + ) + ) + (unreachable) + ) + (set_global $do/n + (i32.const 10) + ) + (set_global $do/m + (i32.const 0) + ) + (block $break|2 + (loop $continue|2 + (block + (drop + (block (result i32) + (set_local $0 + (get_global $do/n) + ) + (set_global $do/n + (i32.sub + (get_local $0) + (i32.const 1) + ) + ) + (get_local $0) + ) + ) + (drop + (block (result i32) + (set_local $0 + (get_global $do/m) + ) + (set_global $do/m + (i32.add + (get_local $0) + (i32.const 1) + ) + ) + (get_local $0) + ) + ) + (block $break|3 + (loop $continue|3 + (block + (drop + (block (result i32) + (set_local $0 + (get_global $do/n) + ) + (set_global $do/n + (i32.sub + (get_local $0) + (i32.const 1) + ) + ) + (get_local $0) + ) + ) + (drop + (block (result i32) + (set_local $0 + (get_global $do/o) + ) + (set_global $do/o + (i32.add + (get_local $0) + (i32.const 1) + ) + ) + (get_local $0) + ) + ) + ) + (br_if $continue|3 + (get_global $do/n) + ) + ) + ) + (if + (i32.eqz + (i32.eq + (get_global $do/n) + (i32.const 0) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (get_global $do/o) + (i32.const 9) + ) + ) + (unreachable) + ) + ) + (br_if $continue|2 + (get_global $do/n) + ) + ) + ) + (if + (i32.eqz + (i32.eq + (get_global $do/n) + (i32.const 0) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (get_global $do/m) + (i32.const 1) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (get_global $do/o) + (i32.const 9) + ) + ) + (unreachable) + ) ) ) (; @@ -97,9 +271,9 @@ FUNCTION_PROTOTYPE: isize FUNCTION_PROTOTYPE: usize GLOBAL: HEAP_BASE - FUNCTION_PROTOTYPE: do/loopDo - FUNCTION_PROTOTYPE: do/loopDoInDo + GLOBAL: do/n + GLOBAL: do/m + GLOBAL: do/o [program.exports] - FUNCTION_PROTOTYPE: do/loopDo - FUNCTION_PROTOTYPE: do/loopDoInDo + ;) diff --git a/tests/compiler/export.optimized.wast b/tests/compiler/export.optimized.wast index a30cebe0..285e3c9f 100644 --- a/tests/compiler/export.optimized.wast +++ b/tests/compiler/export.optimized.wast @@ -10,6 +10,7 @@ (export "renamed_b" (global $export/b)) (export "two" (func $export/ns.two)) (export "memory" (memory $0)) + (start $export/ns.two) (func $export/add (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) (i32.add (get_local $0) diff --git a/tests/compiler/export.ts b/tests/compiler/export.ts index 1094aff3..e7857e2f 100644 --- a/tests/compiler/export.ts +++ b/tests/compiler/export.ts @@ -11,6 +11,7 @@ export { sub as renamed_sub }; export const a: i32 = 1; const b: i32 = 2; +b; export { b as renamed_b }; diff --git a/tests/compiler/export.wast b/tests/compiler/export.wast index db50f644..5291ec16 100644 --- a/tests/compiler/export.wast +++ b/tests/compiler/export.wast @@ -11,6 +11,7 @@ (export "renamed_b" (global $export/b)) (export "two" (func $export/ns.two)) (export "memory" (memory $0)) + (start $start) (func $export/add (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) (return (i32.add @@ -29,6 +30,11 @@ ) (func $export/ns.two (; 2 ;) (type $v) ) + (func $start (; 3 ;) (type $v) + (drop + (i32.const 2) + ) + ) ) (; [program.elements] diff --git a/tests/compiler/for.ts b/tests/compiler/for.ts index 0c392197..709b51b1 100644 --- a/tests/compiler/for.ts +++ b/tests/compiler/for.ts @@ -1,10 +1,10 @@ -let i: i32; +var i: i32; for (i = 0; i < 10; ++i) { ; } assert(i == 10); -for (let j: i32 = 0; j < 10; ++j) { +for (var j: i32 = 0; j < 10; ++j) { ; } diff --git a/tests/compiler/game-of-life.wast b/tests/compiler/game-of-life.wast index 07bcbd50..8df0eac8 100644 --- a/tests/compiler/game-of-life.wast +++ b/tests/compiler/game-of-life.wast @@ -33,206 +33,204 @@ (local $6 i32) (local $7 i32) (local $8 i32) - (local $9 i32) - (local $10 i32) - (nop) - (nop) (block - (set_local $6 + (set_local $0 (i32.sub (get_global $../../examples/game-of-life/assembly/game-of-life/h) (i32.const 1) ) ) - (set_local $7 + (set_local $1 (i32.sub (get_global $../../examples/game-of-life/assembly/game-of-life/w) (i32.const 1) ) ) ) - (block - (set_local $10 - (i32.const 0) - ) - ) (block $break|0 - (set_local $0 - (i32.const 0) + (block + (set_local $2 + (i32.const 0) + ) ) (loop $continue|0 (if (i32.lt_u - (get_local $0) + (get_local $2) (get_global $../../examples/game-of-life/assembly/game-of-life/h) ) (block (block - (set_local $1 - (select - (get_local $6) - (i32.sub + (block + (set_local $3 + (select (get_local $0) - (i32.const 1) - ) - (i32.eq - (get_local $0) - (i32.const 0) + (i32.sub + (get_local $2) + (i32.const 1) + ) + (i32.eq + (get_local $2) + (i32.const 0) + ) ) ) - ) - (set_local $2 - (select - (i32.const 0) - (i32.add - (get_local $0) - (i32.const 1) - ) - (i32.eq - (get_local $0) - (get_local $6) + (set_local $4 + (select + (i32.const 0) + (i32.add + (get_local $2) + (i32.const 1) + ) + (i32.eq + (get_local $2) + (get_local $0) + ) ) ) ) (block $break|1 - (set_local $3 - (i32.const 0) + (block + (set_local $5 + (i32.const 0) + ) ) (loop $continue|1 (if (i32.lt_u - (get_local $3) + (get_local $5) (get_global $../../examples/game-of-life/assembly/game-of-life/w) ) (block (block - (set_local $4 - (select - (get_local $7) - (i32.sub - (get_local $3) - (i32.const 1) + (block + (set_local $6 + (select + (get_local $1) + (i32.sub + (get_local $5) + (i32.const 1) + ) + (i32.eq + (get_local $5) + (i32.const 0) + ) ) - (i32.eq - (get_local $3) + ) + (set_local $7 + (select (i32.const 0) + (i32.add + (get_local $5) + (i32.const 1) + ) + (i32.eq + (get_local $5) + (get_local $1) + ) ) ) ) - (set_local $5 - (select - (i32.const 0) - (i32.add - (get_local $3) - (i32.const 1) - ) - (i32.eq - (get_local $3) - (get_local $7) - ) - ) - ) - (set_local $8 - (i32.add + (block + (set_local $8 (i32.add (i32.add (i32.add (i32.add (i32.add (i32.add - (i32.load8_u - (i32.add - (i32.mul - (get_local $1) - (get_global $../../examples/game-of-life/assembly/game-of-life/w) + (i32.add + (i32.load8_u + (i32.add + (i32.mul + (get_local $3) + (get_global $../../examples/game-of-life/assembly/game-of-life/w) + ) + (get_local $6) + ) + ) + (i32.load8_u + (i32.add + (i32.mul + (get_local $3) + (get_global $../../examples/game-of-life/assembly/game-of-life/w) + ) + (get_local $5) ) - (get_local $4) ) ) (i32.load8_u (i32.add (i32.mul - (get_local $1) + (get_local $3) (get_global $../../examples/game-of-life/assembly/game-of-life/w) ) - (get_local $3) + (get_local $7) ) ) ) (i32.load8_u (i32.add (i32.mul - (get_local $1) + (get_local $2) (get_global $../../examples/game-of-life/assembly/game-of-life/w) ) - (get_local $5) + (get_local $6) ) ) ) (i32.load8_u (i32.add (i32.mul - (get_local $0) + (get_local $2) (get_global $../../examples/game-of-life/assembly/game-of-life/w) ) - (get_local $4) + (get_local $7) ) ) ) (i32.load8_u (i32.add (i32.mul - (get_local $0) + (get_local $4) (get_global $../../examples/game-of-life/assembly/game-of-life/w) ) - (get_local $5) + (get_local $6) ) ) ) (i32.load8_u (i32.add (i32.mul - (get_local $2) + (get_local $4) (get_global $../../examples/game-of-life/assembly/game-of-life/w) ) - (get_local $4) + (get_local $5) ) ) ) (i32.load8_u (i32.add (i32.mul - (get_local $2) + (get_local $4) (get_global $../../examples/game-of-life/assembly/game-of-life/w) ) - (get_local $3) + (get_local $7) ) ) ) - (i32.load8_u - (i32.add - (i32.mul - (get_local $2) - (get_global $../../examples/game-of-life/assembly/game-of-life/w) - ) - (get_local $5) - ) - ) - ) - ) - (set_local $9 - (i32.load8_u - (i32.add - (i32.mul - (get_local $0) - (get_global $../../examples/game-of-life/assembly/game-of-life/w) - ) - (get_local $3) - ) ) ) (if - (get_local $9) + (i32.load8_u + (i32.add + (i32.mul + (get_local $2) + (get_global $../../examples/game-of-life/assembly/game-of-life/w) + ) + (get_local $5) + ) + ) (if (if (result i32) (i32.lt_u @@ -253,11 +251,11 @@ (i32.add (get_global $../../examples/game-of-life/assembly/game-of-life/s) (i32.mul - (get_local $0) + (get_local $2) (get_global $../../examples/game-of-life/assembly/game-of-life/w) ) ) - (get_local $3) + (get_local $5) ) (i32.const 0) ) @@ -272,20 +270,20 @@ (i32.add (get_global $../../examples/game-of-life/assembly/game-of-life/s) (i32.mul - (get_local $0) + (get_local $2) (get_global $../../examples/game-of-life/assembly/game-of-life/w) ) ) - (get_local $3) + (get_local $5) ) (i32.const 1) ) ) ) ) - (set_local $3 + (set_local $5 (i32.add - (get_local $3) + (get_local $5) (i32.const 1) ) ) @@ -295,9 +293,9 @@ ) ) ) - (set_local $0 + (set_local $2 (i32.add - (get_local $0) + (get_local $2) (i32.const 1) ) ) diff --git a/tests/compiler/import.wast b/tests/compiler/import.wast index f7541ce6..c88c0dec 100644 --- a/tests/compiler/import.wast +++ b/tests/compiler/import.wast @@ -1,8 +1,8 @@ (module (type $iii (func (param i32 i32) (result i32))) (type $v (func)) - (global $export/a i32 (i32.const 1)) (global $export/b i32 (i32.const 2)) + (global $export/a i32 (i32.const 1)) (global $HEAP_BASE i32 (i32.const 4)) (memory $0 1) (export "memory" (memory $0)) @@ -26,6 +26,9 @@ (func $export/ns.two (; 2 ;) (type $v) ) (func $start (; 3 ;) (type $v) + (drop + (i32.const 2) + ) (drop (i32.add (call $export/add diff --git a/tests/compiler/infer-type.ts b/tests/compiler/infer-type.ts index 0333c576..04e7f0cc 100644 --- a/tests/compiler/infer-type.ts +++ b/tests/compiler/infer-type.ts @@ -8,39 +8,39 @@ const F = 1.5; F; function locals(): void { - let li = 10; - let lI = 0x100000000; - let lF = 1.5; - let ai = i; - let aI = I; - let aF = F; + var li = 10; + var lI = 0x100000000; + var lF = 1.5; + var ai = i; + var aI = I; + var aF = F; } locals(); function reti(): i32 { return 0; } -let ri = reti(); +var ri = reti(); ri; function retI(): i64 { return 0; } -let rI = retI(); +var rI = retI(); rI; function retf(): f32 { return 0; } -let rf = retf(); +var rf = retf(); rf; function refF(): f64 { return 0; } -let rF = refF(); +var rF = refF(); rF; -for (let a = 0, b = 10; a < b; ++a) { +for (var a = 0, b = 10; a < b; ++a) { ; } diff --git a/tests/compiler/logical.ts b/tests/compiler/logical.ts index 233a45e4..14218e9a 100644 --- a/tests/compiler/logical.ts +++ b/tests/compiler/logical.ts @@ -6,7 +6,7 @@ 1 && 2 || unreachable(); 1.0 && 2.0 || unreachable(); -let i: i32; +var i: i32; i = 1 && 2; assert(i == 2); @@ -14,7 +14,7 @@ assert(i == 2); i = 0 || 1; assert(i == 1); -let I: i64; +var I: i64; I = 1 && 2; assert(I == 2); @@ -22,7 +22,7 @@ assert(I == 2); I = 0 || 1; assert(I == 1); -let f: f32; +var f: f32; f = 1.0 && 2.0; assert(f == 2.0); @@ -30,7 +30,7 @@ assert(f == 2.0); f = 0.0 || 1.0; assert(f == 1.0); -let F: f64; +var F: f64; F = 1.0 && 2.0; assert(F == 2.0); diff --git a/tests/compiler/memcpy.ts b/tests/compiler/memcpy.ts index 985105e1..61abf32b 100644 --- a/tests/compiler/memcpy.ts +++ b/tests/compiler/memcpy.ts @@ -1,7 +1,7 @@ export function memcpy(dest: usize, src: usize, n: usize): usize { // the following is based on musl's implementation of memcpy - let d: usize = dest, s: usize = src; - let w: u32, x: u32; + var d: usize = dest, s: usize = src; + var w: u32, x: u32; // copy 1 byte each until src is aligned to 4 bytes while (n && s % 4) { @@ -147,7 +147,7 @@ store(base + 8 , 0x2222222222222222); store(base + 16, 0x3333333333333333); store(base + 24, 0x4444444444444444); -let dest: usize; +var dest: usize; dest = memcpy(base + 1, base + 16, 4); assert(dest == base + 1); assert(load(base) == 0x1111113333333311); diff --git a/tests/compiler/namespace.ts b/tests/compiler/namespace.ts index b957f57f..91ccc25b 100644 --- a/tests/compiler/namespace.ts +++ b/tests/compiler/namespace.ts @@ -1,6 +1,6 @@ namespace Outer { export namespace Inner { - export let aVar: i32 = 0; + export var aVar: i32 = 0; export function aFunc(): i32 { return aVar; } export enum anEnum { ONE = 1, TWO = 2 } } diff --git a/tests/compiler/portable-conversions.ts b/tests/compiler/portable-conversions.ts index a8b6afd3..0a697920 100644 --- a/tests/compiler/portable-conversions.ts +++ b/tests/compiler/portable-conversions.ts @@ -1,7 +1,7 @@ -let i: i32 = 0; -let I: i64 = 0; -let f: f32 = 0; -let F: f64 = 0; +var i: i32 = 0; +var I: i64 = 0; +var f: f32 = 0; +var F: f64 = 0; i8(i); i8(I); diff --git a/tests/compiler/reexport.optimized.wast b/tests/compiler/reexport.optimized.wast index f3fc9b36..157cceed 100644 --- a/tests/compiler/reexport.optimized.wast +++ b/tests/compiler/reexport.optimized.wast @@ -1,8 +1,8 @@ (module (type $iii (func (param i32 i32) (result i32))) (type $v (func)) - (global $export/a i32 (i32.const 1)) (global $export/b i32 (i32.const 2)) + (global $export/a i32 (i32.const 1)) (memory $0 1) (export "add" (func $export/add)) (export "renamed_sub" (func $export/sub)) diff --git a/tests/compiler/reexport.wast b/tests/compiler/reexport.wast index b9740ca9..aca3b6a8 100644 --- a/tests/compiler/reexport.wast +++ b/tests/compiler/reexport.wast @@ -1,8 +1,8 @@ (module (type $iii (func (param i32 i32) (result i32))) (type $v (func)) - (global $export/a i32 (i32.const 1)) (global $export/b i32 (i32.const 2)) + (global $export/a i32 (i32.const 1)) (global $HEAP_BASE i32 (i32.const 4)) (memory $0 1) (export "add" (func $export/add)) @@ -32,6 +32,9 @@ (func $export/ns.two (; 2 ;) (type $v) ) (func $start (; 3 ;) (type $v) + (drop + (i32.const 2) + ) (drop (i32.add (call $export/add diff --git a/tests/compiler/ternary.ts b/tests/compiler/ternary.ts index b6ab6041..eeb549f0 100644 --- a/tests/compiler/ternary.ts +++ b/tests/compiler/ternary.ts @@ -2,7 +2,7 @@ 1 ? 1 : unreachable(); (0 ? unreachable() : 1) ? 1 : unreachable(); -let a: i32; +var a: i32; a = 0 ? unreachable() : 1; a = 1 ? 1 : unreachable(); diff --git a/tests/compiler/tlsf.ts b/tests/compiler/tlsf.ts index c959c3dd..ec768b6e 100644 --- a/tests/compiler/tlsf.ts +++ b/tests/compiler/tlsf.ts @@ -180,9 +180,9 @@ export function control$construct(ptr: usize): void { block$set_next_free(ptr, ptr); block$set_prev_free(ptr, ptr); control$set_fl_bitmap(ptr, 0); - for (let flIndex: usize = 0; flIndex < FL_INDEX_COUNT; ++flIndex) { + for (var flIndex: usize = 0; flIndex < FL_INDEX_COUNT; ++flIndex) { control$set_sl_bitmap(ptr, flIndex, 0); - for (let slIndex: usize = 0; slIndex < SL_INDEX_COUNT; ++slIndex) + for (var slIndex: usize = 0; slIndex < SL_INDEX_COUNT; ++slIndex) control$set_block(ptr, flIndex, slIndex, ptr); } } diff --git a/tests/compiler/unary.ts b/tests/compiler/unary.ts index d8993e60..7f7ead55 100644 --- a/tests/compiler/unary.ts +++ b/tests/compiler/unary.ts @@ -6,7 +6,7 @@ -1.25; !1.25; -let i: i32 = 0; +var i: i32 = 0; +i; -i; @@ -30,7 +30,7 @@ i = --i; i = i++; i = i--; -let I: i64 = 0; +var I: i64 = 0; +I; -I; @@ -54,7 +54,7 @@ I = --I; I = I++; I = I--; -let f: f32 = 0; +var f: f32 = 0; +f; -f; @@ -75,7 +75,7 @@ f = --f; f = f++; f = f--; -let F: f64 = 0; +var F: f64 = 0; +F; -F; diff --git a/tests/compiler/while.optimized.wast b/tests/compiler/while.optimized.wast index d7dfbaf4..e14044fc 100644 --- a/tests/compiler/while.optimized.wast +++ b/tests/compiler/while.optimized.wast @@ -1,17 +1,26 @@ (module - (type $iv (func (param i32))) + (type $v (func)) + (global $while/n (mut i32) (i32.const 10)) + (global $while/m (mut i32) (i32.const 0)) + (global $while/o (mut i32) (i32.const 0)) (memory $0 1) - (export "loopWhile" (func $while/loopWhile)) - (export "loopWhileInWhile" (func $while/loopWhileInWhile)) (export "memory" (memory $0)) - (func $while/loopWhile (; 0 ;) (type $iv) (param $0 i32) + (start $start) + (func $start (; 0 ;) (type $v) + (local $0 i32) (loop $continue|0 (if - (get_local $0) + (get_global $while/n) (block - (set_local $0 + (set_global $while/n (i32.sub - (get_local $0) + (get_global $while/n) + (i32.const 1) + ) + ) + (set_global $while/m + (i32.add + (get_global $while/m) (i32.const 1) ) ) @@ -19,35 +28,140 @@ ) ) ) - ) - (func $while/loopWhileInWhile (; 1 ;) (type $iv) (param $0 i32) - (loop $continue|0 + (if + (get_global $while/n) + (unreachable) + ) + (if + (i32.ne + (get_global $while/m) + (i32.const 10) + ) + (unreachable) + ) + (set_global $while/n + (i32.const 10) + ) + (set_global $while/m + (i32.const 0) + ) + (loop $continue|1 (if - (get_local $0) + (get_global $while/n) (block - (set_local $0 + (set_global $while/n (i32.sub - (get_local $0) + (get_global $while/n) (i32.const 1) ) ) - (loop $continue|1 + (set_global $while/m + (i32.add + (get_global $while/m) + (i32.const 1) + ) + ) + (loop $continue|2 (if - (get_local $0) + (get_global $while/n) (block - (set_local $0 + (set_global $while/n (i32.sub - (get_local $0) + (get_global $while/n) (i32.const 1) ) ) - (br $continue|1) + (set_global $while/o + (i32.add + (get_global $while/o) + (i32.const 1) + ) + ) + (br $continue|2) ) ) ) - (br $continue|0) + (if + (get_global $while/n) + (unreachable) + ) + (if + (i32.ne + (get_global $while/o) + (i32.const 9) + ) + (unreachable) + ) + (br $continue|1) ) ) ) + (if + (get_global $while/n) + (unreachable) + ) + (if + (i32.ne + (get_global $while/m) + (i32.const 1) + ) + (unreachable) + ) + (if + (i32.ne + (get_global $while/o) + (i32.const 9) + ) + (unreachable) + ) + (set_global $while/n + (i32.const 1) + ) + (set_global $while/m + (i32.const 0) + ) + (loop $continue|3 + (br_if $continue|3 + (if (result i32) + (block (result i32) + (set_global $while/n + (i32.sub + (tee_local $0 + (get_global $while/n) + ) + (i32.const 1) + ) + ) + (tee_local $0 + (get_local $0) + ) + ) + (block (result i32) + (set_global $while/m + (i32.add + (get_global $while/m) + (i32.const 1) + ) + ) + (get_global $while/m) + ) + (get_local $0) + ) + ) + ) + (if + (i32.ne + (get_global $while/n) + (i32.const -1) + ) + (unreachable) + ) + (if + (i32.ne + (get_global $while/m) + (i32.const 1) + ) + (unreachable) + ) ) ) diff --git a/tests/compiler/while.ts b/tests/compiler/while.ts index 95ad44f7..4f2d3f38 100644 --- a/tests/compiler/while.ts +++ b/tests/compiler/while.ts @@ -1,14 +1,32 @@ -export function loopWhile(n: i32): void { - while (n) { - n = n - 1; - } -} +var n = 10; +var m = 0; -export function loopWhileInWhile(n: i32): void { - while (n) { - n = n - 1; - while (n) { - n = n - 1; - } - } +while (n) { + n--; + m++; } +assert(n == 0); +assert(m == 10); + +n = 10; +m = 0; +var o = 0; +while (n) { + n--; + m++; + while (n) { + n--; + o++; + } + assert(n == 0); + assert(o == 9); +} +assert(n == 0); +assert(m == 1); +assert(o == 9); + +n = 1; +m = 0; +while (n-- && ++m); +assert(n == -1); +assert(m == 1); diff --git a/tests/compiler/while.wast b/tests/compiler/while.wast index 620299f0..0134242e 100644 --- a/tests/compiler/while.wast +++ b/tests/compiler/while.wast @@ -1,20 +1,47 @@ (module - (type $iv (func (param i32))) + (type $v (func)) + (global $while/n (mut i32) (i32.const 10)) + (global $while/m (mut i32) (i32.const 0)) + (global $while/o (mut i32) (i32.const 0)) (global $HEAP_BASE i32 (i32.const 4)) (memory $0 1) - (export "loopWhile" (func $while/loopWhile)) - (export "loopWhileInWhile" (func $while/loopWhileInWhile)) (export "memory" (memory $0)) - (func $while/loopWhile (; 0 ;) (type $iv) (param $0 i32) + (start $start) + (func $start (; 0 ;) (type $v) + (local $0 i32) (block $break|0 (loop $continue|0 (if - (get_local $0) + (get_global $while/n) (block - (set_local $0 - (i32.sub - (get_local $0) - (i32.const 1) + (block + (drop + (block (result i32) + (set_local $0 + (get_global $while/n) + ) + (set_global $while/n + (i32.sub + (get_local $0) + (i32.const 1) + ) + ) + (get_local $0) + ) + ) + (drop + (block (result i32) + (set_local $0 + (get_global $while/m) + ) + (set_global $while/m + (i32.add + (get_local $0) + (i32.const 1) + ) + ) + (get_local $0) + ) ) ) (br $continue|0) @@ -22,42 +49,218 @@ ) ) ) - ) - (func $while/loopWhileInWhile (; 1 ;) (type $iv) (param $0 i32) - (block $break|0 - (loop $continue|0 + (if + (i32.eqz + (i32.eq + (get_global $while/n) + (i32.const 0) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (get_global $while/m) + (i32.const 10) + ) + ) + (unreachable) + ) + (set_global $while/n + (i32.const 10) + ) + (set_global $while/m + (i32.const 0) + ) + (block $break|1 + (loop $continue|1 (if - (get_local $0) + (get_global $while/n) (block (block - (set_local $0 - (i32.sub + (drop + (block (result i32) + (set_local $0 + (get_global $while/n) + ) + (set_global $while/n + (i32.sub + (get_local $0) + (i32.const 1) + ) + ) (get_local $0) - (i32.const 1) ) ) - (block $break|1 - (loop $continue|1 + (drop + (block (result i32) + (set_local $0 + (get_global $while/m) + ) + (set_global $while/m + (i32.add + (get_local $0) + (i32.const 1) + ) + ) + (get_local $0) + ) + ) + (block $break|2 + (loop $continue|2 (if - (get_local $0) + (get_global $while/n) (block - (set_local $0 - (i32.sub - (get_local $0) - (i32.const 1) + (block + (drop + (block (result i32) + (set_local $0 + (get_global $while/n) + ) + (set_global $while/n + (i32.sub + (get_local $0) + (i32.const 1) + ) + ) + (get_local $0) + ) + ) + (drop + (block (result i32) + (set_local $0 + (get_global $while/o) + ) + (set_global $while/o + (i32.add + (get_local $0) + (i32.const 1) + ) + ) + (get_local $0) + ) ) ) - (br $continue|1) + (br $continue|2) ) ) ) ) + (if + (i32.eqz + (i32.eq + (get_global $while/n) + (i32.const 0) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (get_global $while/o) + (i32.const 9) + ) + ) + (unreachable) + ) ) - (br $continue|0) + (br $continue|1) ) ) ) ) + (if + (i32.eqz + (i32.eq + (get_global $while/n) + (i32.const 0) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (get_global $while/m) + (i32.const 1) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (get_global $while/o) + (i32.const 9) + ) + ) + (unreachable) + ) + (set_global $while/n + (i32.const 1) + ) + (set_global $while/m + (i32.const 0) + ) + (block $break|3 + (loop $continue|3 + (if + (if (result i32) + (tee_local $0 + (block (result i32) + (set_local $0 + (get_global $while/n) + ) + (set_global $while/n + (i32.sub + (get_local $0) + (i32.const 1) + ) + ) + (get_local $0) + ) + ) + (block (result i32) + (set_global $while/m + (i32.add + (get_global $while/m) + (i32.const 1) + ) + ) + (get_global $while/m) + ) + (get_local $0) + ) + (block + (nop) + (br $continue|3) + ) + ) + ) + ) + (if + (i32.eqz + (i32.eq + (get_global $while/n) + (i32.sub + (i32.const 0) + (i32.const 1) + ) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (i32.eq + (get_global $while/m) + (i32.const 1) + ) + ) + (unreachable) + ) ) ) (; @@ -106,9 +309,9 @@ FUNCTION_PROTOTYPE: isize FUNCTION_PROTOTYPE: usize GLOBAL: HEAP_BASE - FUNCTION_PROTOTYPE: while/loopWhile - FUNCTION_PROTOTYPE: while/loopWhileInWhile + GLOBAL: while/n + GLOBAL: while/m + GLOBAL: while/o [program.exports] - FUNCTION_PROTOTYPE: while/loopWhile - FUNCTION_PROTOTYPE: while/loopWhileInWhile + ;)