Fix game-of-life example inconsistencies; Fix ternary expression issues in void contexts and variable statements; Simplify HEAP_BASE handling

This commit is contained in:
dcodeIO 2018-04-18 15:12:33 +02:00
parent 4026c087fd
commit 5a2f834c0d
19 changed files with 654 additions and 559 deletions

2
dist/asc.js vendored

File diff suppressed because one or more lines are too long

2
dist/asc.js.map vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
node_modules/
node_modules/

View File

@ -1,21 +1,21 @@
Conway's Game of Life
=====================
An [AssemblyScript](http://assemblyscript.org) example. Continuously updates the cellular automaton and visualizes its state on a canvas.
An [AssemblyScript](http://assemblyscript.org) example. Continuously updates the cellular automaton and visualizes its state on a canvas. Compiles to ~450 bytes of optimized WASM, no strings attached.
Instructions
------------
You have to install the 'opn' package to be able to run the `npm browser` command
First, install the development dependencies:
```
$> npm install
```
To build [assembly/game-of-life.ts](./assembly/game-of-life.ts) to an untouched and an optimized `.wasm` including their respective `.wat` representations, run:
Now, to build [assembly/game-of-life.ts](./assembly/game-of-life.ts) to an untouched and an optimized `.wasm` including their respective `.wat` representations, run:
```
$> npm run build
```
Afterwards, open [game-of-life.html](./game-of-life.html) in a browser (ideally one that allows `fetch`ing the `.wasm` from the local filesystem).
Afterwards, run `node server` to start a <a href="http://localhost:9080">local server</a>. Should also automatically launch a browser.

View File

@ -1,37 +1,54 @@
// A simplified version of the game of life as seen on http://dcode.io
// The Game of Life, also known simply as Life, is a cellular automaton devised by the British
// mathematician John Horton Conway in 1970.
// see: https://en.wikipedia.org/wiki/Conway's_Game_of_Life
var w: u32, // width
h: u32, // height
s: u32; // total size
var w: i32, h: i32, s: i32;
/** Initializes width and height. */
export function init(w_: u32, h_: u32): void {
w = w_;
h = h_;
s = w * h;
/** Initializes width and height. Called once from JS. */
export function init(width: i32, height: i32): void {
w = width;
h = height;
s = width * height;
}
/** Performs one step. */
/** Performs one step. Called about 30 times a second from JS. */
export function step(): void {
var hm1 = h - 1,
wm1 = w - 1;
for (var y: u32 = 0; y < h; ++y) {
var ym1 = select<u32>(hm1, y - 1, y == 0),
yp1 = select<u32>(0, y + 1, y == hm1);
for (var x: u32 = 0; x < w; ++x) {
var xm1 = select<u32>(wm1, x - 1, x == 0),
xp1 = select<u32>(0, x + 1, x == wm1);
var n = (
var hm1 = h - 1, // h - 1
wm1 = w - 1; // w - 1
// The universe of the Game of Life is an infinite two-dimensional orthogonal grid of square
// "cells", each of which is in one of two possible states, alive or dead.
for (let y = 0; y < h; ++y) {
let ym1 = y == 0 ? hm1 : y - 1, // y - 1
yp1 = y == hm1 ? 0 : y + 1; // y + 1
for (let x = 0; x < w; ++x) {
let xm1 = x == 0 ? wm1 : x - 1, // x - 1
xp1 = x == wm1 ? 0 : x + 1; // x + 1
// Every cell interacts with its eight neighbours, which are the cells that are horizontally,
// vertically, or diagonally adjacent:
let aliveNeighbors = (
load<u8>(ym1 * w + xm1) + load<u8>(ym1 * w + x) + load<u8>(ym1 * w + xp1) +
load<u8>(y * w + xm1) + load<u8>(y * w + xp1) +
load<u8>(yp1 * w + xm1) + load<u8>(yp1 * w + x) + load<u8>(yp1 * w + xp1)
);
if (load<u8>(y * w + x)) {
if (n < 2 || n > 3) {
store<u8>(s + y * w + x, 0);
let alive = load<u8>(y * w + x);
if (alive) {
switch (aliveNeighbors) {
// A live cell with fewer than 2 live neighbors dies, as if caused by underpopulation.
// A live cell with more than 3 live neighbors dies, as if by overpopulation.
default: { store<u8>(s + y * w + x, 0); break; }
// A live cell with 2 or 3 live neighbors lives on to the next generation.
case 2: case 3:
}
} else {
switch (aliveNeighbors) {
// A dead cell with exactly 3 live neighbors becomes a live cell, as if by reproduction.
case 3: { store<u8>(s + y * w + x, 1); break; }
default:
}
} else if (n == 3) {
store<u8>(s + y * w + x, 1);
}
}
}

View File

@ -1,27 +1,47 @@
<canvas id="canvas" width="640" height="480"></canvas><script>
<html>
<head>
<style>
html, body { height: 100%; margin: 0; overflow: hidden; color: #111; background: #fff; font-family: sans-serif; }
h1 { padding: 20px; font-size: 12pt; }
a { color: #111; text-decoration: none; }
a:hover { color: #0074C1; text-decoration: underline; }
canvas { position: absolute; top: 60px; left: 20px; width: calc(100% - 40px); height: calc(100% - 80px); }
</style>
</head>
<body>
<h1>
<a href="https://en.wikipedia.org/wiki/Conway's_Game_of_Life">Conway's Game Of Life</a> in
<a href="http://assemblyscript.org">AssemblyScript</a>
</h1>
<canvas id="canvas"></canvas>
<script>
// Fetch the .wasm
fetch("game-of-life.optimized.wasm").then(response => response.arrayBuffer()).then(binary => {
// Set up the canvas with a 2D rendering context
var cnv = document.getElementById("canvas");
var ctx = cnv.getContext("2d");
var bcr = cnv.getBoundingClientRect();
cnv.width = bcr.width | 0;
cnv.height = bcr.height | 0;
// Instantiate the module
var module = new WebAssembly.Module(binary);
var instance = new WebAssembly.Instance(module, { env: { abort: function() {} } });
// Compute the size of the universe (here: 2px per cell)
var w = bcr.width >>> 1;
var h = bcr.height >>> 1;
var s = w * h; // memory required to store either input or output
var S = s + s; // total memory required to store input and output
// Set up the canvas with a 2D rendering context
var cnv = document.getElementById("canvas");
var ctx = cnv.getContext("2d");
var w = cnv.width,
h = cnv.height,
s = w * h, // memory required to store either input or output
S = s + s; // total memory required to store input and output
// Compute the size of and instantiate the module's memory
var nPages = ((S + 0xffff) & ~0xffff) >>> 16; // aligned up in 64k units
var memory = new WebAssembly.Memory({ initial: nPages });
// Grow the (exported) memory if its size isn't sufficient
var memory = instance.exports.memory;
if (memory.buffer.byteLength < S)
memory.grow(Math.ceil((S - memory.buffer.byteLength) / 65536));
// Fetch and instantiate the module
WebAssembly.instantiateStreaming(fetch("game-of-life.optimized.wasm"), {
env: { memory: memory }
})
.then(module => {
var exports = module.instance.exports;
// Initialize with width and height
instance.exports.init(w, h);
// Tell the module about the universe's width and height
exports.init(w, h);
// Fill input at [0, s-1] with random live cells
var mem = new Uint8Array(memory.buffer);
@ -31,23 +51,26 @@ fetch("game-of-life.optimized.wasm").then(response => response.arrayBuffer()).th
// Update about 30 times a second
(function update() {
setTimeout(update, 33);
instance.exports.step();
mem.set(mem.subarray(s, S), 0); // copy output -> input
setTimeout(update, 30);
exports.step();
mem.copyWithin(0, s, S); // copy output at [s, S] to input at [0, s]
})();
// Keep rendering the output at [s, 2*s-1]
// Keep rendering the output at [s, S]
(function render() {
requestAnimationFrame(render);
ctx.clearRect(0, 0, w, h);
ctx.fillStyle = "rgba(238,238,238,0.67)";
ctx.fillRect(0, 0, w << 1, h << 1);
ctx.fillStyle = "#333";
for (var y = 0; y < h; ++y)
for (var x = 0; x < w; ++x)
if (mem[s + y * w + x])
ctx.fillRect(x, y, 1, 1);
ctx.fillRect(x << 1, y << 1, 2, 2);
})();
}).catch(err => {
throw err;
});
</script>
</body>
</html>

Binary file not shown.

View File

@ -1,10 +1,10 @@
(module
(type $iiv (func (param i32 i32)))
(type $v (func))
(import "env" "memory" (memory $0 1))
(global $assembly/game-of-life/w (mut i32) (i32.const 0))
(global $assembly/game-of-life/h (mut i32) (i32.const 0))
(global $assembly/game-of-life/s (mut i32) (i32.const 0))
(memory $0 1)
(export "init" (func $assembly/game-of-life/init))
(export "step" (func $assembly/game-of-life/step))
(export "memory" (memory $0))
@ -23,9 +23,9 @@
(set_global $assembly/game-of-life/s
;;@ assembly/game-of-life.ts:11:6
(i32.mul
(get_global $assembly/game-of-life/w)
;;@ assembly/game-of-life.ts:11:10
(get_global $assembly/game-of-life/h)
(get_local $0)
;;@ assembly/game-of-life.ts:11:14
(get_local $1)
)
)
)
@ -38,7 +38,7 @@
(local $5 i32)
(local $6 i32)
(local $7 i32)
(set_local $6
(set_local $5
;;@ assembly/game-of-life.ts:16:12
(i32.sub
(get_global $assembly/game-of-life/h)
@ -46,7 +46,7 @@
(i32.const 1)
)
)
(set_local $7
(set_local $6
;;@ assembly/game-of-life.ts:17:12
(i32.sub
(get_global $assembly/game-of-life/w)
@ -56,66 +56,64 @@
)
(loop $continue|0
(if
;;@ assembly/game-of-life.ts:18:23
(i32.lt_u
;;@ assembly/game-of-life.ts:21:18
(i32.lt_s
(get_local $0)
;;@ assembly/game-of-life.ts:18:27
;;@ assembly/game-of-life.ts:21:22
(get_global $assembly/game-of-life/h)
)
(block
(set_local $4
;;@ assembly/game-of-life.ts:19:14
(select
;;@ assembly/game-of-life.ts:19:31
(set_local $3
;;@ assembly/game-of-life.ts:23:14
(if (result i32)
(get_local $0)
;;@ assembly/game-of-life.ts:23:29
(i32.sub
(get_local $0)
;;@ assembly/game-of-life.ts:19:35
;;@ assembly/game-of-life.ts:23:33
(i32.const 1)
)
;;@ assembly/game-of-life.ts:19:26
(get_local $6)
;;@ assembly/game-of-life.ts:19:38
(get_local $0)
;;@ assembly/game-of-life.ts:23:23
(get_local $5)
)
)
(set_local $5
;;@ assembly/game-of-life.ts:20:14
(select
;;@ assembly/game-of-life.ts:20:26
(i32.const 0)
;;@ assembly/game-of-life.ts:20:29
(i32.add
(get_local $0)
;;@ assembly/game-of-life.ts:20:33
(i32.const 1)
)
;;@ assembly/game-of-life.ts:20:36
(set_local $4
;;@ assembly/game-of-life.ts:24:14
(if (result i32)
(i32.eq
(get_local $0)
;;@ assembly/game-of-life.ts:20:41
(get_local $6)
;;@ assembly/game-of-life.ts:24:19
(get_local $5)
)
;;@ assembly/game-of-life.ts:24:25
(i32.const 0)
;;@ assembly/game-of-life.ts:24:29
(i32.add
(get_local $0)
;;@ assembly/game-of-life.ts:24:33
(i32.const 1)
)
)
)
;;@ assembly/game-of-life.ts:21:9
;;@ assembly/game-of-life.ts:25:9
(set_local $1
;;@ assembly/game-of-life.ts:21:22
;;@ assembly/game-of-life.ts:25:17
(i32.const 0)
)
(loop $continue|1
(if
;;@ assembly/game-of-life.ts:21:25
(i32.lt_u
;;@ assembly/game-of-life.ts:25:20
(i32.lt_s
(get_local $1)
;;@ assembly/game-of-life.ts:21:29
;;@ assembly/game-of-life.ts:25:24
(get_global $assembly/game-of-life/w)
)
(block
;;@ assembly/game-of-life.ts:24:6
;;@ assembly/game-of-life.ts:31:6
(set_local $2
;;@ assembly/game-of-life.ts:24:14
;;@ assembly/game-of-life.ts:31:27
(i32.add
;;@ assembly/game-of-life.ts:25:8
;;@ assembly/game-of-life.ts:32:8
(i32.add
(i32.add
(i32.add
@ -123,236 +121,228 @@
(i32.add
(i32.add
(i32.load8_u
;;@ assembly/game-of-life.ts:25:17
;;@ assembly/game-of-life.ts:32:17
(i32.add
(i32.mul
(get_local $4)
;;@ assembly/game-of-life.ts:25:23
(get_local $3)
;;@ assembly/game-of-life.ts:32:23
(get_global $assembly/game-of-life/w)
)
(tee_local $2
;;@ assembly/game-of-life.ts:22:16
(select
;;@ assembly/game-of-life.ts:22:33
;;@ assembly/game-of-life.ts:26:16
(if (result i32)
(get_local $1)
;;@ assembly/game-of-life.ts:26:31
(i32.sub
(get_local $1)
;;@ assembly/game-of-life.ts:22:37
;;@ assembly/game-of-life.ts:26:35
(i32.const 1)
)
;;@ assembly/game-of-life.ts:22:28
(get_local $7)
;;@ assembly/game-of-life.ts:22:40
(get_local $1)
;;@ assembly/game-of-life.ts:26:25
(get_local $6)
)
)
)
)
;;@ assembly/game-of-life.ts:25:34
;;@ assembly/game-of-life.ts:32:34
(i32.load8_u
;;@ assembly/game-of-life.ts:25:43
;;@ assembly/game-of-life.ts:32:43
(i32.add
(i32.mul
(get_local $4)
;;@ assembly/game-of-life.ts:25:49
(get_local $3)
;;@ assembly/game-of-life.ts:32:49
(get_global $assembly/game-of-life/w)
)
;;@ assembly/game-of-life.ts:25:53
;;@ assembly/game-of-life.ts:32:53
(get_local $1)
)
)
)
;;@ assembly/game-of-life.ts:25:58
;;@ assembly/game-of-life.ts:32:58
(i32.load8_u
;;@ assembly/game-of-life.ts:25:67
;;@ assembly/game-of-life.ts:32:67
(i32.add
(i32.mul
(get_local $4)
;;@ assembly/game-of-life.ts:25:73
(get_local $3)
;;@ assembly/game-of-life.ts:32:73
(get_global $assembly/game-of-life/w)
)
(tee_local $3
;;@ assembly/game-of-life.ts:23:16
(select
;;@ assembly/game-of-life.ts:23:28
(i32.const 0)
;;@ assembly/game-of-life.ts:23:31
(i32.add
(get_local $1)
;;@ assembly/game-of-life.ts:23:35
(i32.const 1)
)
;;@ assembly/game-of-life.ts:23:38
(tee_local $7
;;@ assembly/game-of-life.ts:27:16
(if (result i32)
(i32.eq
(get_local $1)
;;@ assembly/game-of-life.ts:23:43
(get_local $7)
;;@ assembly/game-of-life.ts:27:21
(get_local $6)
)
;;@ assembly/game-of-life.ts:27:27
(i32.const 0)
;;@ assembly/game-of-life.ts:27:31
(i32.add
(get_local $1)
;;@ assembly/game-of-life.ts:27:35
(i32.const 1)
)
)
)
)
)
)
;;@ assembly/game-of-life.ts:26:8
;;@ assembly/game-of-life.ts:33:8
(i32.load8_u
;;@ assembly/game-of-life.ts:26:17
;;@ assembly/game-of-life.ts:33:17
(i32.add
(i32.mul
(get_local $0)
;;@ assembly/game-of-life.ts:26:23
;;@ assembly/game-of-life.ts:33:23
(get_global $assembly/game-of-life/w)
)
;;@ assembly/game-of-life.ts:26:27
;;@ assembly/game-of-life.ts:33:27
(get_local $2)
)
)
)
;;@ assembly/game-of-life.ts:26:58
;;@ assembly/game-of-life.ts:33:58
(i32.load8_u
;;@ assembly/game-of-life.ts:26:67
;;@ assembly/game-of-life.ts:33:67
(i32.add
(i32.mul
(get_local $0)
;;@ assembly/game-of-life.ts:26:73
;;@ assembly/game-of-life.ts:33:73
(get_global $assembly/game-of-life/w)
)
;;@ assembly/game-of-life.ts:26:77
(get_local $3)
;;@ assembly/game-of-life.ts:33:77
(get_local $7)
)
)
)
;;@ assembly/game-of-life.ts:27:8
;;@ assembly/game-of-life.ts:34:8
(i32.load8_u
;;@ assembly/game-of-life.ts:27:17
;;@ assembly/game-of-life.ts:34:17
(i32.add
(i32.mul
(get_local $5)
;;@ assembly/game-of-life.ts:27:23
(get_local $4)
;;@ assembly/game-of-life.ts:34:23
(get_global $assembly/game-of-life/w)
)
;;@ assembly/game-of-life.ts:27:27
;;@ assembly/game-of-life.ts:34:27
(get_local $2)
)
)
)
;;@ assembly/game-of-life.ts:27:34
;;@ assembly/game-of-life.ts:34:34
(i32.load8_u
;;@ assembly/game-of-life.ts:27:43
;;@ assembly/game-of-life.ts:34:43
(i32.add
(i32.mul
(get_local $5)
;;@ assembly/game-of-life.ts:27:49
(get_local $4)
;;@ assembly/game-of-life.ts:34:49
(get_global $assembly/game-of-life/w)
)
;;@ assembly/game-of-life.ts:27:53
;;@ assembly/game-of-life.ts:34:53
(get_local $1)
)
)
)
;;@ assembly/game-of-life.ts:27:58
;;@ assembly/game-of-life.ts:34:58
(i32.load8_u
;;@ assembly/game-of-life.ts:27:67
;;@ assembly/game-of-life.ts:34:67
(i32.add
(i32.mul
(get_local $5)
;;@ assembly/game-of-life.ts:27:73
(get_local $4)
;;@ assembly/game-of-life.ts:34:73
(get_global $assembly/game-of-life/w)
)
;;@ assembly/game-of-life.ts:27:77
(get_local $3)
;;@ assembly/game-of-life.ts:34:77
(get_local $7)
)
)
)
)
;;@ assembly/game-of-life.ts:29:6
;;@ assembly/game-of-life.ts:38:6
(if
;;@ assembly/game-of-life.ts:29:10
;;@ assembly/game-of-life.ts:37:18
(i32.load8_u
;;@ assembly/game-of-life.ts:29:19
;;@ assembly/game-of-life.ts:37:27
(i32.add
(i32.mul
(get_local $0)
;;@ assembly/game-of-life.ts:29:23
;;@ assembly/game-of-life.ts:37:31
(get_global $assembly/game-of-life/w)
)
;;@ assembly/game-of-life.ts:29:27
;;@ assembly/game-of-life.ts:37:35
(get_local $1)
)
)
;;@ assembly/game-of-life.ts:30:8
(if
;;@ assembly/game-of-life.ts:30:12
(i32.and
(if (result i32)
(tee_local $3
(i32.lt_s
(get_local $2)
;;@ assembly/game-of-life.ts:30:16
(i32.const 2)
)
)
(get_local $3)
;;@ assembly/game-of-life.ts:30:21
(i32.gt_s
(get_local $2)
;;@ assembly/game-of-life.ts:30:25
(i32.const 3)
)
;;@ assembly/game-of-life.ts:39:8
(block $break|2
(br_if $break|2
(i32.eq
;;@ assembly/game-of-life.ts:39:16
(get_local $2)
;;@ assembly/game-of-life.ts:44:15
(i32.const 2)
)
(i32.const 1)
)
;;@ assembly/game-of-life.ts:31:10
(br_if $break|2
(i32.eq
(get_local $2)
;;@ assembly/game-of-life.ts:44:23
(i32.const 3)
)
)
;;@ assembly/game-of-life.ts:42:21
(i32.store8
;;@ assembly/game-of-life.ts:31:20
;;@ assembly/game-of-life.ts:42:31
(i32.add
(i32.add
(get_global $assembly/game-of-life/s)
;;@ assembly/game-of-life.ts:31:24
;;@ assembly/game-of-life.ts:42:35
(i32.mul
(get_local $0)
;;@ assembly/game-of-life.ts:31:28
;;@ assembly/game-of-life.ts:42:39
(get_global $assembly/game-of-life/w)
)
)
;;@ assembly/game-of-life.ts:31:32
;;@ assembly/game-of-life.ts:42:43
(get_local $1)
)
;;@ assembly/game-of-life.ts:31:35
;;@ assembly/game-of-life.ts:42:46
(i32.const 0)
)
)
;;@ assembly/game-of-life.ts:33:13
(if
;;@ assembly/game-of-life.ts:33:17
(i32.eq
;;@ assembly/game-of-life.ts:47:16
(get_local $2)
;;@ assembly/game-of-life.ts:33:22
;;@ assembly/game-of-life.ts:49:15
(i32.const 3)
)
;;@ assembly/game-of-life.ts:34:8
;;@ assembly/game-of-life.ts:49:20
(i32.store8
;;@ assembly/game-of-life.ts:34:18
;;@ assembly/game-of-life.ts:49:30
(i32.add
(i32.add
(get_global $assembly/game-of-life/s)
;;@ assembly/game-of-life.ts:34:22
;;@ assembly/game-of-life.ts:49:34
(i32.mul
(get_local $0)
;;@ assembly/game-of-life.ts:34:26
;;@ assembly/game-of-life.ts:49:38
(get_global $assembly/game-of-life/w)
)
)
;;@ assembly/game-of-life.ts:34:30
;;@ assembly/game-of-life.ts:49:42
(get_local $1)
)
;;@ assembly/game-of-life.ts:34:33
;;@ assembly/game-of-life.ts:49:45
(i32.const 1)
)
)
)
;;@ assembly/game-of-life.ts:21:32
;;@ assembly/game-of-life.ts:25:27
(set_local $1
(i32.add
;;@ assembly/game-of-life.ts:21:34
;;@ assembly/game-of-life.ts:25:29
(get_local $1)
(i32.const 1)
)
@ -361,10 +351,10 @@
)
)
)
;;@ assembly/game-of-life.ts:18:30
;;@ assembly/game-of-life.ts:21:25
(set_local $0
(i32.add
;;@ assembly/game-of-life.ts:18:32
;;@ assembly/game-of-life.ts:21:27
(get_local $0)
(i32.const 1)
)

View File

@ -1,11 +1,11 @@
(module
(type $iiv (func (param i32 i32)))
(type $v (func))
(import "env" "memory" (memory $0 1))
(global $assembly/game-of-life/w (mut i32) (i32.const 0))
(global $assembly/game-of-life/h (mut i32) (i32.const 0))
(global $assembly/game-of-life/s (mut i32) (i32.const 0))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "init" (func $assembly/game-of-life/init))
(export "step" (func $assembly/game-of-life/step))
(export "memory" (memory $0))
@ -24,9 +24,9 @@
(set_global $assembly/game-of-life/s
;;@ assembly/game-of-life.ts:11:6
(i32.mul
(get_global $assembly/game-of-life/w)
;;@ assembly/game-of-life.ts:11:10
(get_global $assembly/game-of-life/h)
(get_local $0)
;;@ assembly/game-of-life.ts:11:14
(get_local $1)
)
)
)
@ -41,6 +41,7 @@
(local $7 i32)
(local $8 i32)
(local $9 i32)
(local $10 i32)
;;@ assembly/game-of-life.ts:16:2
(block
(set_local $0
@ -60,125 +61,121 @@
)
)
)
;;@ assembly/game-of-life.ts:18:2
;;@ assembly/game-of-life.ts:21:2
(block $break|0
;;@ assembly/game-of-life.ts:18:7
;;@ assembly/game-of-life.ts:21:7
(set_local $2
;;@ assembly/game-of-life.ts:18:20
;;@ assembly/game-of-life.ts:21:15
(i32.const 0)
)
(loop $continue|0
(if
;;@ assembly/game-of-life.ts:18:23
(i32.lt_u
;;@ assembly/game-of-life.ts:21:18
(i32.lt_s
(get_local $2)
;;@ assembly/game-of-life.ts:18:27
;;@ assembly/game-of-life.ts:21:22
(get_global $assembly/game-of-life/h)
)
(block
(block
(block
(set_local $3
;;@ assembly/game-of-life.ts:19:14
(select
;;@ assembly/game-of-life.ts:19:26
(get_local $0)
;;@ assembly/game-of-life.ts:19:31
(i32.sub
(get_local $2)
;;@ assembly/game-of-life.ts:19:35
(i32.const 1)
)
;;@ assembly/game-of-life.ts:19:38
;;@ assembly/game-of-life.ts:23:14
(if (result i32)
(i32.eq
(get_local $2)
;;@ assembly/game-of-life.ts:19:43
;;@ assembly/game-of-life.ts:23:19
(i32.const 0)
)
;;@ assembly/game-of-life.ts:23:23
(get_local $0)
;;@ assembly/game-of-life.ts:23:29
(i32.sub
(get_local $2)
;;@ assembly/game-of-life.ts:23:33
(i32.const 1)
)
)
)
(set_local $4
;;@ assembly/game-of-life.ts:20:14
(select
;;@ assembly/game-of-life.ts:20:26
(i32.const 0)
;;@ assembly/game-of-life.ts:20:29
(i32.add
(get_local $2)
;;@ assembly/game-of-life.ts:20:33
(i32.const 1)
)
;;@ assembly/game-of-life.ts:20:36
;;@ assembly/game-of-life.ts:24:14
(if (result i32)
(i32.eq
(get_local $2)
;;@ assembly/game-of-life.ts:20:41
;;@ assembly/game-of-life.ts:24:19
(get_local $0)
)
;;@ assembly/game-of-life.ts:24:25
(i32.const 0)
;;@ assembly/game-of-life.ts:24:29
(i32.add
(get_local $2)
;;@ assembly/game-of-life.ts:24:33
(i32.const 1)
)
)
)
)
;;@ assembly/game-of-life.ts:21:4
;;@ assembly/game-of-life.ts:25:4
(block $break|1
;;@ assembly/game-of-life.ts:21:9
;;@ assembly/game-of-life.ts:25:9
(set_local $5
;;@ assembly/game-of-life.ts:21:22
;;@ assembly/game-of-life.ts:25:17
(i32.const 0)
)
(loop $continue|1
(if
;;@ assembly/game-of-life.ts:21:25
(i32.lt_u
;;@ assembly/game-of-life.ts:25:20
(i32.lt_s
(get_local $5)
;;@ assembly/game-of-life.ts:21:29
;;@ assembly/game-of-life.ts:25:24
(get_global $assembly/game-of-life/w)
)
(block
(block
(block
(set_local $6
;;@ assembly/game-of-life.ts:22:16
(select
;;@ assembly/game-of-life.ts:22:28
(get_local $1)
;;@ assembly/game-of-life.ts:22:33
(i32.sub
(get_local $5)
;;@ assembly/game-of-life.ts:22:37
(i32.const 1)
)
;;@ assembly/game-of-life.ts:22:40
;;@ assembly/game-of-life.ts:26:16
(if (result i32)
(i32.eq
(get_local $5)
;;@ assembly/game-of-life.ts:22:45
;;@ assembly/game-of-life.ts:26:21
(i32.const 0)
)
;;@ assembly/game-of-life.ts:26:25
(get_local $1)
;;@ assembly/game-of-life.ts:26:31
(i32.sub
(get_local $5)
;;@ assembly/game-of-life.ts:26:35
(i32.const 1)
)
)
)
(set_local $7
;;@ assembly/game-of-life.ts:23:16
(select
;;@ assembly/game-of-life.ts:23:28
(i32.const 0)
;;@ assembly/game-of-life.ts:23:31
(i32.add
(get_local $5)
;;@ assembly/game-of-life.ts:23:35
(i32.const 1)
)
;;@ assembly/game-of-life.ts:23:38
;;@ assembly/game-of-life.ts:27:16
(if (result i32)
(i32.eq
(get_local $5)
;;@ assembly/game-of-life.ts:23:43
;;@ assembly/game-of-life.ts:27:21
(get_local $1)
)
;;@ assembly/game-of-life.ts:27:27
(i32.const 0)
;;@ assembly/game-of-life.ts:27:31
(i32.add
(get_local $5)
;;@ assembly/game-of-life.ts:27:35
(i32.const 1)
)
)
)
)
;;@ assembly/game-of-life.ts:24:6
;;@ assembly/game-of-life.ts:31:6
(set_local $8
;;@ assembly/game-of-life.ts:24:14
;;@ assembly/game-of-life.ts:31:27
(i32.add
;;@ assembly/game-of-life.ts:25:8
;;@ assembly/game-of-life.ts:32:8
(i32.add
(i32.add
(i32.add
@ -186,207 +183,237 @@
(i32.add
(i32.add
(i32.load8_u
;;@ assembly/game-of-life.ts:25:17
;;@ assembly/game-of-life.ts:32:17
(i32.add
(i32.mul
(get_local $3)
;;@ assembly/game-of-life.ts:25:23
;;@ assembly/game-of-life.ts:32:23
(get_global $assembly/game-of-life/w)
)
;;@ assembly/game-of-life.ts:25:27
;;@ assembly/game-of-life.ts:32:27
(get_local $6)
)
)
;;@ assembly/game-of-life.ts:25:34
;;@ assembly/game-of-life.ts:32:34
(i32.load8_u
;;@ assembly/game-of-life.ts:25:43
;;@ assembly/game-of-life.ts:32:43
(i32.add
(i32.mul
(get_local $3)
;;@ assembly/game-of-life.ts:25:49
;;@ assembly/game-of-life.ts:32:49
(get_global $assembly/game-of-life/w)
)
;;@ assembly/game-of-life.ts:25:53
;;@ assembly/game-of-life.ts:32:53
(get_local $5)
)
)
)
;;@ assembly/game-of-life.ts:25:58
;;@ assembly/game-of-life.ts:32:58
(i32.load8_u
;;@ assembly/game-of-life.ts:25:67
;;@ assembly/game-of-life.ts:32:67
(i32.add
(i32.mul
(get_local $3)
;;@ assembly/game-of-life.ts:25:73
;;@ assembly/game-of-life.ts:32:73
(get_global $assembly/game-of-life/w)
)
;;@ assembly/game-of-life.ts:25:77
;;@ assembly/game-of-life.ts:32:77
(get_local $7)
)
)
)
;;@ assembly/game-of-life.ts:26:8
;;@ assembly/game-of-life.ts:33:8
(i32.load8_u
;;@ assembly/game-of-life.ts:26:17
;;@ assembly/game-of-life.ts:33:17
(i32.add
(i32.mul
(get_local $2)
;;@ assembly/game-of-life.ts:26:23
;;@ assembly/game-of-life.ts:33:23
(get_global $assembly/game-of-life/w)
)
;;@ assembly/game-of-life.ts:26:27
;;@ assembly/game-of-life.ts:33:27
(get_local $6)
)
)
)
;;@ assembly/game-of-life.ts:26:58
;;@ assembly/game-of-life.ts:33:58
(i32.load8_u
;;@ assembly/game-of-life.ts:26:67
;;@ assembly/game-of-life.ts:33:67
(i32.add
(i32.mul
(get_local $2)
;;@ assembly/game-of-life.ts:26:73
;;@ assembly/game-of-life.ts:33:73
(get_global $assembly/game-of-life/w)
)
;;@ assembly/game-of-life.ts:26:77
;;@ assembly/game-of-life.ts:33:77
(get_local $7)
)
)
)
;;@ assembly/game-of-life.ts:27:8
;;@ assembly/game-of-life.ts:34:8
(i32.load8_u
;;@ assembly/game-of-life.ts:27:17
;;@ assembly/game-of-life.ts:34:17
(i32.add
(i32.mul
(get_local $4)
;;@ assembly/game-of-life.ts:27:23
;;@ assembly/game-of-life.ts:34:23
(get_global $assembly/game-of-life/w)
)
;;@ assembly/game-of-life.ts:27:27
;;@ assembly/game-of-life.ts:34:27
(get_local $6)
)
)
)
;;@ assembly/game-of-life.ts:27:34
;;@ assembly/game-of-life.ts:34:34
(i32.load8_u
;;@ assembly/game-of-life.ts:27:43
;;@ assembly/game-of-life.ts:34:43
(i32.add
(i32.mul
(get_local $4)
;;@ assembly/game-of-life.ts:27:49
;;@ assembly/game-of-life.ts:34:49
(get_global $assembly/game-of-life/w)
)
;;@ assembly/game-of-life.ts:27:53
;;@ assembly/game-of-life.ts:34:53
(get_local $5)
)
)
)
;;@ assembly/game-of-life.ts:27:58
;;@ assembly/game-of-life.ts:34:58
(i32.load8_u
;;@ assembly/game-of-life.ts:27:67
;;@ assembly/game-of-life.ts:34:67
(i32.add
(i32.mul
(get_local $4)
;;@ assembly/game-of-life.ts:27:73
;;@ assembly/game-of-life.ts:34:73
(get_global $assembly/game-of-life/w)
)
;;@ assembly/game-of-life.ts:27:77
;;@ assembly/game-of-life.ts:34:77
(get_local $7)
)
)
)
)
;;@ assembly/game-of-life.ts:29:6
(if
;;@ assembly/game-of-life.ts:29:10
;;@ assembly/game-of-life.ts:37:6
(set_local $9
;;@ assembly/game-of-life.ts:37:18
(i32.load8_u
;;@ assembly/game-of-life.ts:29:19
;;@ assembly/game-of-life.ts:37:27
(i32.add
(i32.mul
(get_local $2)
;;@ assembly/game-of-life.ts:29:23
;;@ assembly/game-of-life.ts:37:31
(get_global $assembly/game-of-life/w)
)
;;@ assembly/game-of-life.ts:29:27
;;@ assembly/game-of-life.ts:37:35
(get_local $5)
)
)
;;@ assembly/game-of-life.ts:30:8
(if
;;@ assembly/game-of-life.ts:30:12
(i32.and
(if (result i32)
(tee_local $9
(i32.lt_s
)
;;@ assembly/game-of-life.ts:38:6
(if
;;@ assembly/game-of-life.ts:38:10
(get_local $9)
;;@ assembly/game-of-life.ts:39:8
(block $break|2
(block $case2|2
(block $case1|2
(block $case0|2
(set_local $10
;;@ assembly/game-of-life.ts:39:16
(get_local $8)
;;@ assembly/game-of-life.ts:30:16
(i32.const 2)
)
(br_if $case1|2
(i32.eq
(get_local $10)
;;@ assembly/game-of-life.ts:44:15
(i32.const 2)
)
)
(br_if $case2|2
(i32.eq
(get_local $10)
;;@ assembly/game-of-life.ts:44:23
(i32.const 3)
)
)
(br $case0|2)
)
(get_local $9)
;;@ assembly/game-of-life.ts:30:21
(i32.gt_s
(get_local $8)
;;@ assembly/game-of-life.ts:30:25
(i32.const 3)
;;@ assembly/game-of-life.ts:42:19
(block
;;@ assembly/game-of-life.ts:42:21
(i32.store8
;;@ assembly/game-of-life.ts:42:31
(i32.add
(i32.add
(get_global $assembly/game-of-life/s)
;;@ assembly/game-of-life.ts:42:35
(i32.mul
(get_local $2)
;;@ assembly/game-of-life.ts:42:39
(get_global $assembly/game-of-life/w)
)
)
;;@ assembly/game-of-life.ts:42:43
(get_local $5)
)
;;@ assembly/game-of-life.ts:42:46
(i32.const 0)
)
;;@ assembly/game-of-life.ts:42:50
(br $break|2)
)
)
(i32.const 1)
)
;;@ assembly/game-of-life.ts:31:10
(i32.store8
;;@ assembly/game-of-life.ts:31:20
(i32.add
(i32.add
(get_global $assembly/game-of-life/s)
;;@ assembly/game-of-life.ts:31:24
(i32.mul
(get_local $2)
;;@ assembly/game-of-life.ts:31:28
(get_global $assembly/game-of-life/w)
)
)
;;@ assembly/game-of-life.ts:31:32
(get_local $5)
)
;;@ assembly/game-of-life.ts:31:35
(i32.const 0)
)
)
;;@ assembly/game-of-life.ts:33:13
(if
;;@ assembly/game-of-life.ts:33:17
(i32.eq
(get_local $8)
;;@ assembly/game-of-life.ts:33:22
(i32.const 3)
)
;;@ assembly/game-of-life.ts:34:8
(i32.store8
;;@ assembly/game-of-life.ts:34:18
(i32.add
(i32.add
(get_global $assembly/game-of-life/s)
;;@ assembly/game-of-life.ts:34:22
(i32.mul
(get_local $2)
;;@ assembly/game-of-life.ts:34:26
(get_global $assembly/game-of-life/w)
;;@ assembly/game-of-life.ts:47:8
(block $break|3
(block $case1|3
(block $case0|3
(set_local $10
;;@ assembly/game-of-life.ts:47:16
(get_local $8)
)
(br_if $case0|3
(i32.eq
(get_local $10)
;;@ assembly/game-of-life.ts:49:15
(i32.const 3)
)
)
;;@ assembly/game-of-life.ts:34:30
(get_local $5)
(br $case1|3)
)
;;@ assembly/game-of-life.ts:49:18
(block
;;@ assembly/game-of-life.ts:49:20
(i32.store8
;;@ assembly/game-of-life.ts:49:30
(i32.add
(i32.add
(get_global $assembly/game-of-life/s)
;;@ assembly/game-of-life.ts:49:34
(i32.mul
(get_local $2)
;;@ assembly/game-of-life.ts:49:38
(get_global $assembly/game-of-life/w)
)
)
;;@ assembly/game-of-life.ts:49:42
(get_local $5)
)
;;@ assembly/game-of-life.ts:49:45
(i32.const 1)
)
;;@ assembly/game-of-life.ts:49:49
(br $break|3)
)
;;@ assembly/game-of-life.ts:34:33
(i32.const 1)
)
)
)
)
;;@ assembly/game-of-life.ts:21:32
;;@ assembly/game-of-life.ts:25:27
(set_local $5
(i32.add
;;@ assembly/game-of-life.ts:21:34
;;@ assembly/game-of-life.ts:25:29
(get_local $5)
(i32.const 1)
)
@ -397,10 +424,10 @@
)
)
)
;;@ assembly/game-of-life.ts:18:30
;;@ assembly/game-of-life.ts:21:25
(set_local $2
(i32.add
;;@ assembly/game-of-life.ts:18:32
;;@ assembly/game-of-life.ts:21:27
(get_local $2)
(i32.const 1)
)

View File

@ -4,11 +4,10 @@
"private": true,
"scripts": {
"build": "npm run build:untouched && npm run build:optimized",
"build:untouched": "asc assembly/game-of-life.ts -b game-of-life.untouched.wasm -t game-of-life.untouched.wat --validate --sourceMap --measure",
"build:optimized": "asc -O assembly/game-of-life.ts -b game-of-life.optimized.wasm -t game-of-life.optimized.wat --validate --sourceMap --measure",
"browser": "node server.js"
"build:untouched": "asc assembly/game-of-life.ts -b game-of-life.untouched.wasm -t game-of-life.untouched.wat --importMemory --validate --sourceMap --measure",
"build:optimized": "asc -O3 assembly/game-of-life.ts -b game-of-life.optimized.wasm -t game-of-life.optimized.wat --importMemory --validate --sourceMap --noDebug --measure"
},
"dependencies": {
"devDependencies": {
"opn": "^5.3.0"
}
}

View File

@ -1,18 +1,32 @@
var open = require('opn');
var http = require('http');
var fs = require('fs');
var http = require("http");
var fs = require("fs");
var open = require("opn");
const PORT = 9080;
const PORT = 9080;
fs.readFile('./game-of-life.html', function (err, html) {
if (err) throw err;
http.createServer(function(request, response) {
response.writeHeader(200, {"Content-Type": "text/html"});
response.write(html);
response.end();
}).listen(PORT);
http.createServer((req, res) => {
var url = req.url;
console.log(req.method + " " + url);
if (/^\/([\w\-_]+(\.\w+)+)?$/i.test(url)) {
if (url === "/") url = "/game-of-life.html";
fs.readFile(__dirname + url, function(err, data) {
if (err) {
res.writeHeader(404);
} else {
res.writeHeader(200, {
"Content-Type":
/\.wasm$/.test(url) ? "application/wasm" :
/\.(json|map)$/.test(url) ? "application/json"
: "text/html"
});
res.write(data);
}
res.end();
});
} else {
res.writeHeader(404);
res.end();
}
}).listen(PORT, () => {
open("http://localhost:9080/");
});
open('http://localhost:9080/game-of-life.html');

View File

@ -47,25 +47,6 @@ import {
OperatorKind
} from "./program";
/** Compiles a get of a built-in global. */
export function compileGetConstant(
compiler: Compiler,
global: Global,
reportNode: Node
): ExpressionRef {
switch (global.internalName) {
case "HEAP_BASE": { // never inlined for linking purposes
compiler.currentType = compiler.options.usizeType;
return compiler.module.createGetGlobal("HEAP_BASE", compiler.currentType.toNativeType());
}
}
compiler.error(
DiagnosticCode.Operation_not_supported,
reportNode.range
);
return compiler.module.createUnreachable();
}
/** Compiles a call to a built-in function. */
export function compileCall(
compiler: Compiler,

View File

@ -5,7 +5,6 @@
import {
compileCall as compileBuiltinCall,
compileGetConstant as compileBuiltinGetConstant,
compileAllocate as compileBuiltinAllocate,
compileAbort as compileBuiltinAbort
} from "./builtins";
@ -458,8 +457,8 @@ export class Compiler extends DiagnosticEmitter {
}
compileGlobal(global: Global): bool {
if (global.is(CommonFlags.COMPILED) || global.is(CommonFlags.AMBIENT | CommonFlags.BUILTIN)) return true;
global.set(CommonFlags.COMPILED); // ^ built-ins are compiled on use
if (global.is(CommonFlags.COMPILED)) return true;
global.set(CommonFlags.COMPILED);
var module = this.module;
var declaration = global.declaration;
@ -510,6 +509,9 @@ export class Compiler extends DiagnosticEmitter {
}
}
// ambient builtins like 'HEAP_BASE' need to be resolved but are added explicitly
if (global.is(CommonFlags.AMBIENT | CommonFlags.BUILTIN)) return true;
var nativeType = global.type.toNativeType();
var isConstant = global.isAny(CommonFlags.CONST) || global.is(CommonFlags.STATIC | CommonFlags.READONLY);
@ -928,18 +930,7 @@ export class Compiler extends DiagnosticEmitter {
if (signature.requiredParameters < signature.parameterTypes.length) {
// export the trampoline if the function takes optional parameters
instance = this.ensureTrampoline(instance);
if (!this.argcSet) {
this.ensureArgumentCount(0);
this.argcSet = module.addFunction("~setargc",
this.ensureFunctionType([ Type.u32 ], Type.void),
null,
module.createSetGlobal("~argc",
module.createGetLocal(0, NativeType.I32)
)
);
// export a helper to set argc prior to calling it
module.addFunctionExport("~setargc", "_setargc");
}
this.ensureArgcSet();
}
module.addFunctionExport(instance.internalName, mangleExportName(instance));
}
@ -5098,6 +5089,38 @@ export class Compiler extends DiagnosticEmitter {
return trampoline;
}
/** Makes sure that the argument count helper global is present and returns its name. */
private ensureArgcVar(): string {
var internalName = "~argc";
if (!this.argcVar) {
let module = this.module;
this.argcVar = module.addGlobal(
internalName,
NativeType.I32,
true,
module.createI32(0)
);
}
return internalName;
}
/** Makes sure that the argument count helper setter is present and returns its name. */
private ensureArgcSet(): string {
var internalName = "~setargc";
if (!this.argcSet) {
let module = this.module;
this.argcSet = module.addFunction(internalName,
this.ensureFunctionType([ Type.u32 ], Type.void),
null,
module.createSetGlobal(this.ensureArgcVar(),
module.createGetLocal(0, NativeType.I32)
)
);
module.addFunctionExport(internalName, "_setargc");
}
return internalName;
}
/** Creates a direct call to the specified function. */
makeCallDirect(
instance: Function,
@ -5137,7 +5160,7 @@ export class Compiler extends DiagnosticEmitter {
let nativeReturnType = returnType.toNativeType();
this.currentType = returnType;
return module.createBlock(null, [
this.ensureArgumentCount(numArguments),
module.createSetGlobal(this.ensureArgcVar(), module.createI32(numArguments)),
module.createCall(instance.internalName, operands, nativeReturnType)
], nativeReturnType);
}
@ -5224,25 +5247,13 @@ export class Compiler extends DiagnosticEmitter {
var returnType = signature.returnType;
this.currentType = returnType;
return module.createBlock(null, [
this.ensureArgumentCount(numArguments), // might still be calling a trampoline
module.createSetGlobal(this.ensureArgcVar(), // might still be calling a trampoline
module.createI32(numArguments)
),
module.createCallIndirect(indexArg, operands, signature.toSignatureString())
], returnType.toNativeType());
}
/** Makes sure that the argument count helper global is present and returns an expression that sets it. */
private ensureArgumentCount(argumentCount: i32): ExpressionRef {
var module = this.module;
if (!this.argcVar) {
this.argcVar = module.addGlobal(
"~argc",
NativeType.I32,
true,
module.createI32(0)
);
}
return module.createSetGlobal("~argc", module.createI32(argumentCount));
}
compileCommaExpression(expression: CommaExpression, contextualType: Type): ExpressionRef {
var expressions = expression.expressions;
var numExpressions = expressions.length;
@ -5430,9 +5441,6 @@ export class Compiler extends DiagnosticEmitter {
return this.module.createGetLocal(localIndex, localType.toNativeType());
}
case ElementKind.GLOBAL: {
if (target.is(CommonFlags.AMBIENT | CommonFlags.BUILTIN)) {
return compileBuiltinGetConstant(this, <Global>target, expression);
}
if (!this.compileGlobal(<Global>target)) { // reports; not yet compiled if a static field
return this.module.createUnreachable();
}
@ -5898,9 +5906,6 @@ export class Compiler extends DiagnosticEmitter {
switch (target.kind) {
case ElementKind.GLOBAL: { // static property
if (target.is(CommonFlags.AMBIENT | CommonFlags.BUILTIN)) {
return compileBuiltinGetConstant(this, <Global>target, propertyAccess);
}
if (!this.compileGlobal(<Global>target)) { // reports; not yet compiled if a static field
return module.createUnreachable();
}
@ -6008,6 +6013,8 @@ export class Compiler extends DiagnosticEmitter {
var currentFunction = this.currentFunction;
var ifThenExpr: ExpressionRef;
var ifElseExpr: ExpressionRef;
var ifThenType: Type;
var ifElseType: Type;
// if part of a constructor, keep track of memory allocations
if (currentFunction.is(CommonFlags.CONSTRUCTOR)) {
@ -6015,14 +6022,16 @@ export class Compiler extends DiagnosticEmitter {
flow = flow.enterBranchOrScope();
currentFunction.flow = flow;
ifThenExpr = this.compileExpression(ifThen, contextualType);
ifThenExpr = this.compileExpressionRetainType(ifThen, contextualType);
ifThenType = this.currentType;
let ifThenAllocates = flow.is(FlowFlags.ALLOCATES);
flow = flow.leaveBranchOrScope();
currentFunction.flow = flow;
flow = flow.enterBranchOrScope();
currentFunction.flow = flow;
ifElseExpr = this.compileExpression(ifElse, contextualType);
ifElseExpr = this.compileExpressionRetainType(ifElse, contextualType);
ifElseType = this.currentType;
let ifElseAllocates = flow.is(FlowFlags.ALLOCATES);
flow = flow.leaveBranchOrScope();
currentFunction.flow = flow;
@ -6031,10 +6040,23 @@ export class Compiler extends DiagnosticEmitter {
// otherwise simplify
} else {
ifThenExpr = this.compileExpression(ifThen, contextualType);
ifElseExpr = this.compileExpression(ifElse, contextualType);
ifThenExpr = this.compileExpressionRetainType(ifThen, contextualType);
ifThenType = this.currentType;
ifElseExpr = this.compileExpressionRetainType(ifElse, contextualType);
ifElseType = this.currentType;
}
var commonType = Type.commonCompatible(ifThenType, ifElseType, false);
if (!commonType) {
this.error(
DiagnosticCode.Type_0_is_not_assignable_to_type_1,
expression.range, ifThenType.toString(), ifElseType.toString()
);
this.currentType = contextualType;
return this.module.createUnreachable();
}
ifThenExpr = this.convertExpression(ifThenExpr, ifThenType, commonType, ConversionKind.IMPLICIT, ifThen);
ifElseExpr = this.convertExpression(ifElseExpr, ifElseType, commonType, ConversionKind.IMPLICIT, ifElse);
this.currentType = commonType;
return this.module.createIf(condExpr, ifThenExpr, ifElseExpr);
}

View File

@ -3101,7 +3101,7 @@ export class Parser extends DiagnosticEmitter {
);
return null;
}
let ifElse = this.parseExpression(tn);
let ifElse = this.parseExpression(tn, precedence > Precedence.COMMA ? Precedence.COMMA + 1 : 0);
if (!ifElse) return null;
expr = Node.createTernaryExpression(
expr,

View File

@ -17,8 +17,8 @@
)
(set_global $../../examples/game-of-life/assembly/game-of-life/s
(i32.mul
(get_global $../../examples/game-of-life/assembly/game-of-life/w)
(get_global $../../examples/game-of-life/assembly/game-of-life/h)
(get_local $0)
(get_local $1)
)
)
)
@ -31,13 +31,13 @@
(local $5 i32)
(local $6 i32)
(local $7 i32)
(set_local $6
(set_local $5
(i32.sub
(get_global $../../examples/game-of-life/assembly/game-of-life/h)
(i32.const 1)
)
)
(set_local $7
(set_local $6
(i32.sub
(get_global $../../examples/game-of-life/assembly/game-of-life/w)
(i32.const 1)
@ -45,22 +45,22 @@
)
(loop $continue|0
(if
(i32.lt_u
(i32.lt_s
(get_local $0)
(get_global $../../examples/game-of-life/assembly/game-of-life/h)
)
(block
(set_local $4
(set_local $3
(select
(i32.sub
(get_local $0)
(i32.const 1)
)
(get_local $6)
(get_local $5)
(get_local $0)
)
)
(set_local $5
(set_local $4
(select
(i32.const 0)
(i32.add
@ -69,7 +69,7 @@
)
(i32.eq
(get_local $0)
(get_local $6)
(get_local $5)
)
)
)
@ -78,7 +78,7 @@
)
(loop $continue|1
(if
(i32.lt_u
(i32.lt_s
(get_local $1)
(get_global $../../examples/game-of-life/assembly/game-of-life/w)
)
@ -94,7 +94,7 @@
(i32.load8_u
(i32.add
(i32.mul
(get_local $4)
(get_local $3)
(get_global $../../examples/game-of-life/assembly/game-of-life/w)
)
(tee_local $2
@ -103,7 +103,7 @@
(get_local $1)
(i32.const 1)
)
(get_local $7)
(get_local $6)
(get_local $1)
)
)
@ -112,7 +112,7 @@
(i32.load8_u
(i32.add
(i32.mul
(get_local $4)
(get_local $3)
(get_global $../../examples/game-of-life/assembly/game-of-life/w)
)
(get_local $1)
@ -122,10 +122,10 @@
(i32.load8_u
(i32.add
(i32.mul
(get_local $4)
(get_local $3)
(get_global $../../examples/game-of-life/assembly/game-of-life/w)
)
(tee_local $3
(tee_local $7
(select
(i32.const 0)
(i32.add
@ -134,7 +134,7 @@
)
(i32.eq
(get_local $1)
(get_local $7)
(get_local $6)
)
)
)
@ -157,14 +157,14 @@
(get_local $0)
(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 $5)
(get_local $4)
(get_global $../../examples/game-of-life/assembly/game-of-life/w)
)
(get_local $2)
@ -174,7 +174,7 @@
(i32.load8_u
(i32.add
(i32.mul
(get_local $5)
(get_local $4)
(get_global $../../examples/game-of-life/assembly/game-of-life/w)
)
(get_local $1)
@ -184,10 +184,10 @@
(i32.load8_u
(i32.add
(i32.mul
(get_local $5)
(get_local $4)
(get_global $../../examples/game-of-life/assembly/game-of-life/w)
)
(get_local $3)
(get_local $7)
)
)
)
@ -203,21 +203,17 @@
)
)
(if
(i32.and
(if (result i32)
(tee_local $3
(i32.lt_s
(get_local $2)
(i32.const 2)
)
(i32.eqz
(i32.or
(i32.eq
(get_local $2)
(i32.const 2)
)
(get_local $3)
(i32.gt_s
(i32.eq
(get_local $2)
(i32.const 3)
)
)
(i32.const 1)
)
(i32.store8
(i32.add

View File

@ -18,8 +18,8 @@
)
(set_global $../../examples/game-of-life/assembly/game-of-life/s
(i32.mul
(get_global $../../examples/game-of-life/assembly/game-of-life/w)
(get_global $../../examples/game-of-life/assembly/game-of-life/h)
(get_local $0)
(get_local $1)
)
)
)
@ -34,6 +34,7 @@
(local $7 i32)
(local $8 i32)
(local $9 i32)
(local $10 i32)
(block
(set_local $0
(i32.sub
@ -54,7 +55,7 @@
)
(loop $continue|0
(if
(i32.lt_u
(i32.lt_s
(get_local $2)
(get_global $../../examples/game-of-life/assembly/game-of-life/h)
)
@ -62,29 +63,29 @@
(block
(block
(set_local $3
(select
(if (result i32)
(i32.eq
(get_local $2)
(i32.const 0)
)
(get_local $0)
(i32.sub
(get_local $2)
(i32.const 1)
)
(i32.eq
(get_local $2)
(i32.const 0)
)
)
)
(set_local $4
(select
(if (result i32)
(i32.eq
(get_local $2)
(get_local $0)
)
(i32.const 0)
(i32.add
(get_local $2)
(i32.const 1)
)
(i32.eq
(get_local $2)
(get_local $0)
)
)
)
)
@ -94,7 +95,7 @@
)
(loop $continue|1
(if
(i32.lt_u
(i32.lt_s
(get_local $5)
(get_global $../../examples/game-of-life/assembly/game-of-life/w)
)
@ -102,29 +103,29 @@
(block
(block
(set_local $6
(select
(if (result i32)
(i32.eq
(get_local $5)
(i32.const 0)
)
(get_local $1)
(i32.sub
(get_local $5)
(i32.const 1)
)
(i32.eq
(get_local $5)
(i32.const 0)
)
)
)
(set_local $7
(select
(if (result i32)
(i32.eq
(get_local $5)
(get_local $1)
)
(i32.const 0)
(i32.add
(get_local $5)
(i32.const 1)
)
(i32.eq
(get_local $5)
(get_local $1)
)
)
)
)
@ -216,7 +217,7 @@
)
)
)
(if
(set_local $9
(i32.load8_u
(i32.add
(i32.mul
@ -226,54 +227,79 @@
(get_local $5)
)
)
(if
(i32.and
(if (result i32)
(tee_local $9
(i32.lt_s
)
(if
(get_local $9)
(block $break|2
(block $case2|2
(block $case1|2
(block $case0|2
(set_local $10
(get_local $8)
(i32.const 2)
)
(br_if $case1|2
(i32.eq
(get_local $10)
(i32.const 2)
)
)
(br_if $case2|2
(i32.eq
(get_local $10)
(i32.const 3)
)
)
(br $case0|2)
)
(get_local $9)
(i32.gt_s
(get_local $8)
(i32.const 3)
(block
(i32.store8
(i32.add
(i32.add
(get_global $../../examples/game-of-life/assembly/game-of-life/s)
(i32.mul
(get_local $2)
(get_global $../../examples/game-of-life/assembly/game-of-life/w)
)
)
(get_local $5)
)
(i32.const 0)
)
(br $break|2)
)
)
(i32.const 1)
)
(i32.store8
(i32.add
(i32.add
(get_global $../../examples/game-of-life/assembly/game-of-life/s)
(i32.mul
(get_local $2)
(get_global $../../examples/game-of-life/assembly/game-of-life/w)
)
)
(get_local $5)
)
(i32.const 0)
)
)
(if
(i32.eq
(get_local $8)
(i32.const 3)
)
(i32.store8
(i32.add
(i32.add
(get_global $../../examples/game-of-life/assembly/game-of-life/s)
(i32.mul
(get_local $2)
(get_global $../../examples/game-of-life/assembly/game-of-life/w)
(block $break|3
(block $case1|3
(block $case0|3
(set_local $10
(get_local $8)
)
(br_if $case0|3
(i32.eq
(get_local $10)
(i32.const 3)
)
)
(get_local $5)
(br $case1|3)
)
(block
(i32.store8
(i32.add
(i32.add
(get_global $../../examples/game-of-life/assembly/game-of-life/s)
(i32.mul
(get_local $2)
(get_global $../../examples/game-of-life/assembly/game-of-life/w)
)
)
(get_local $5)
)
(i32.const 1)
)
(br $break|3)
)
(i32.const 1)
)
)
)

View File

@ -6,30 +6,30 @@
(export "memory" (memory $0))
(start $start)
(func $start (; 0 ;) (type $v)
(if
(i32.const 0)
(unreachable)
(drop
(i32.const 1)
)
)
(if
(i32.const 1)
(drop
(i32.const 1)
)
(unreachable)
)
(if
(drop
(if (result i32)
(i32.const 0)
(unreachable)
(i32.const 1)
)
(drop
)
(drop
(if (result i32)
(i32.const 1)
(i32.const 1)
(unreachable)
)
)
(drop
(if (result i32)
(if (result i32)
(i32.const 0)
(unreachable)
(i32.const 1)
)
(i32.const 1)
(unreachable)
)
(unreachable)
)
(set_global $ternary/a
(if (result i32)