diff --git a/README.md b/README.md index 5f96ff79..0a4cd0cd 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,9 @@ AssemblyScript NEXT **AssemblyScript** is a new compiler targeting [WebAssembly](http://webassembly.org) while utilizing [TypeScript](http://www.typescriptlang.org)'s syntax and [node](https://nodejs.org)'s vibrant ecosystem. Instead of requiring complex toolchains to set up, you can simply `npm install` it - or run it in a browser. -By compiling a variant of TypeScript to [Binaryen](https://github.com/WebAssembly/binaryen) IR, the resulting module can be validated, optimized, emitted in WebAssembly text or binary format and converted to [asm.js](http://asmjs.org) as a polyfill. +By compiling syntactially but not necessarily semantically valid TypeScript to [Binaryen](https://github.com/WebAssembly/binaryen) IR, the resulting module can be validated, optimized, emitted in WebAssembly text or binary format and converted to [asm.js](http://asmjs.org) as a polyfill. -The compiler itself is written in "portable AssemblyScript" so it can be compiled to both JavaScript using `tsc` and, eventually, to WebAssembly using `asc`. +The compiler itself utilizies "portable definitions" so it can be compiled to both JavaScript using `tsc` and, eventually, to WebAssembly using `asc`. Development status ------------------ @@ -16,12 +16,10 @@ This version of the compiler (0.5.0, NEXT) is relatively new and does not yet su A few early examples to get an idea: -* **memcpy** using load/store derived from [musl](http://www.musl-libc.org)
- [source](./tests/compiler/memcpy.ts) - [wast](./tests/compiler/memcpy.optimized.wast) * **Conway's Game of Life** as seen on [dcode.io](http://dcode.io)
- [source](./tests/compiler/game-of-life.ts) - [wast](./tests/compiler/game-of-life.optimized.wast) - [html](./tests/compiler/game-of-life.html) + [source](./examples/game-of-life/assembly/game-of-life.ts) - [wast](./examples/game-of-life/assembly/game-of-life.optimized.wast) - [html](./examples/game-of-life/game-of-life.html) * **i64 polyfill** using 32-bit integers
- [source](./tests/compiler/i64.ts) - [wast](./tests/compiler/i64.optimized.wast) + [source](./examples/i64-polyfill/assembly/i64.ts) - [wast](./examples/i64-polyfill/assembly/i64.optimized.wast) - [js](./examples/i64-polyfill/index.js) Getting started --------------- @@ -34,7 +32,12 @@ $> cd next $> npm install ``` -Author your module in AssemblyScript ([definitions](./std/assembly.d.ts), [base config](./std/assembly.json)) or portable AssemblyScript ([definitions](./std/portable.d.ts), [base config](./std/portable.json)) and run: +Author your module either using + +* the [assembly definitions](./std/assembly.d.ts) ([base config](./std/assembly.json)) if all you care about is targeting WebAssembly/asm.js or +* the [portable definitions](./std/portable.d.ts) ([base config](./std/portable.json)) if you also want to compile to JavaScript using `tsc` + +and run: ``` $> node bin/asc yourModule.ts @@ -67,7 +70,7 @@ Options: js Replace trapping operations with JS semantics. ``` -Unless a bundle has been built to `dist/`, `asc` runs the TypeScript sources on the fly via [ts-node](https://www.npmjs.com/package/ts-node). Useful for development. +Unless a bundle has been built to `dist/`, `asc` runs the (portable) TypeScript sources on the fly via [ts-node](https://www.npmjs.com/package/ts-node). Useful for development. Building -------- diff --git a/bin/asc b/bin/asc new file mode 100644 index 00000000..250a511a --- /dev/null +++ b/bin/asc @@ -0,0 +1,2 @@ +#!/usr/bin/env node +require("./asc.js"); diff --git a/examples/.gitignore b/examples/.gitignore new file mode 100644 index 00000000..5b26ccf0 --- /dev/null +++ b/examples/.gitignore @@ -0,0 +1,2 @@ +*.wasm +node_modules/ diff --git a/examples/game-of-life/README.md b/examples/game-of-life/README.md new file mode 100644 index 00000000..636a3dd4 --- /dev/null +++ b/examples/game-of-life/README.md @@ -0,0 +1,15 @@ +Conway's Game of Life +===================== + +An AssemblyScript example. + +Instructions +------------ + +To build `assembly/game-of-life.ts` to `game-of-life.wasm`, run: + +``` +$> npm run build +``` + +Afterwards, open `game-of-life.html` in a browser (ideally one that allows `fetch`ing the `.wasm` from the local filesystem). diff --git a/tests/compiler/game-of-life.optimized.wast b/examples/game-of-life/assembly/game-of-life.optimized.wast similarity index 76% rename from tests/compiler/game-of-life.optimized.wast rename to examples/game-of-life/assembly/game-of-life.optimized.wast index d1cd8963..b5820efc 100644 --- a/tests/compiler/game-of-life.optimized.wast +++ b/examples/game-of-life/assembly/game-of-life.optimized.wast @@ -1,28 +1,28 @@ (module (type $iiv (func (param i32 i32))) (type $v (func)) - (global $game-of-life/w (mut i32) (i32.const 0)) - (global $game-of-life/h (mut i32) (i32.const 0)) - (global $game-of-life/s (mut i32) (i32.const 0)) + (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 $game-of-life/init)) - (export "step" (func $game-of-life/step)) + (export "init" (func $assembly/game-of-life/init)) + (export "step" (func $assembly/game-of-life/step)) (export "memory" (memory $0)) - (func $game-of-life/init (; 0 ;) (type $iiv) (param $0 i32) (param $1 i32) - (set_global $game-of-life/w + (func $assembly/game-of-life/init (; 0 ;) (type $iiv) (param $0 i32) (param $1 i32) + (set_global $assembly/game-of-life/w (get_local $0) ) - (set_global $game-of-life/h + (set_global $assembly/game-of-life/h (get_local $1) ) - (set_global $game-of-life/s + (set_global $assembly/game-of-life/s (i32.mul - (get_global $game-of-life/w) - (get_global $game-of-life/h) + (get_global $assembly/game-of-life/w) + (get_global $assembly/game-of-life/h) ) ) ) - (func $game-of-life/step (; 1 ;) (type $v) + (func $assembly/game-of-life/step (; 1 ;) (type $v) (local $0 i32) (local $1 i32) (local $2 i32) @@ -33,13 +33,13 @@ (local $7 i32) (set_local $6 (i32.sub - (get_global $game-of-life/h) + (get_global $assembly/game-of-life/h) (i32.const 1) ) ) (set_local $7 (i32.sub - (get_global $game-of-life/w) + (get_global $assembly/game-of-life/w) (i32.const 1) ) ) @@ -50,7 +50,7 @@ (if (i32.lt_u (get_local $0) - (get_global $game-of-life/h) + (get_global $assembly/game-of-life/h) ) (block (set_local $4 @@ -83,7 +83,7 @@ (if (i32.lt_u (get_local $1) - (get_global $game-of-life/w) + (get_global $assembly/game-of-life/w) ) (block (set_local $2 @@ -98,7 +98,7 @@ (i32.add (i32.mul (get_local $4) - (get_global $game-of-life/w) + (get_global $assembly/game-of-life/w) ) (tee_local $2 (select @@ -116,7 +116,7 @@ (i32.add (i32.mul (get_local $4) - (get_global $game-of-life/w) + (get_global $assembly/game-of-life/w) ) (get_local $1) ) @@ -126,7 +126,7 @@ (i32.add (i32.mul (get_local $4) - (get_global $game-of-life/w) + (get_global $assembly/game-of-life/w) ) (tee_local $3 (select @@ -148,7 +148,7 @@ (i32.add (i32.mul (get_local $0) - (get_global $game-of-life/w) + (get_global $assembly/game-of-life/w) ) (get_local $2) ) @@ -158,7 +158,7 @@ (i32.add (i32.mul (get_local $0) - (get_global $game-of-life/w) + (get_global $assembly/game-of-life/w) ) (get_local $3) ) @@ -168,7 +168,7 @@ (i32.add (i32.mul (get_local $5) - (get_global $game-of-life/w) + (get_global $assembly/game-of-life/w) ) (get_local $2) ) @@ -178,7 +178,7 @@ (i32.add (i32.mul (get_local $5) - (get_global $game-of-life/w) + (get_global $assembly/game-of-life/w) ) (get_local $1) ) @@ -188,7 +188,7 @@ (i32.add (i32.mul (get_local $5) - (get_global $game-of-life/w) + (get_global $assembly/game-of-life/w) ) (get_local $3) ) @@ -200,7 +200,7 @@ (i32.add (i32.mul (get_local $0) - (get_global $game-of-life/w) + (get_global $assembly/game-of-life/w) ) (get_local $1) ) @@ -222,10 +222,10 @@ (i32.store8 (i32.add (i32.add - (get_global $game-of-life/s) + (get_global $assembly/game-of-life/s) (i32.mul (get_local $0) - (get_global $game-of-life/w) + (get_global $assembly/game-of-life/w) ) ) (get_local $1) @@ -241,10 +241,10 @@ (i32.store8 (i32.add (i32.add - (get_global $game-of-life/s) + (get_global $assembly/game-of-life/s) (i32.mul (get_local $0) - (get_global $game-of-life/w) + (get_global $assembly/game-of-life/w) ) ) (get_local $1) diff --git a/tests/compiler/game-of-life.ts b/examples/game-of-life/assembly/game-of-life.ts similarity index 100% rename from tests/compiler/game-of-life.ts rename to examples/game-of-life/assembly/game-of-life.ts diff --git a/tests/compiler/game-of-life.wast b/examples/game-of-life/assembly/game-of-life.wast similarity index 77% rename from tests/compiler/game-of-life.wast rename to examples/game-of-life/assembly/game-of-life.wast index 74ce6de2..4e599c2d 100644 --- a/tests/compiler/game-of-life.wast +++ b/examples/game-of-life/assembly/game-of-life.wast @@ -1,29 +1,29 @@ (module (type $iiv (func (param i32 i32))) (type $v (func)) - (global $game-of-life/w (mut i32) (i32.const 0)) - (global $game-of-life/h (mut i32) (i32.const 0)) - (global $game-of-life/s (mut i32) (i32.const 0)) + (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_START i32 (i32.const 4)) (memory $0 1) - (export "init" (func $game-of-life/init)) - (export "step" (func $game-of-life/step)) + (export "init" (func $assembly/game-of-life/init)) + (export "step" (func $assembly/game-of-life/step)) (export "memory" (memory $0)) - (func $game-of-life/init (; 0 ;) (type $iiv) (param $0 i32) (param $1 i32) - (set_global $game-of-life/w + (func $assembly/game-of-life/init (; 0 ;) (type $iiv) (param $0 i32) (param $1 i32) + (set_global $assembly/game-of-life/w (get_local $0) ) - (set_global $game-of-life/h + (set_global $assembly/game-of-life/h (get_local $1) ) - (set_global $game-of-life/s + (set_global $assembly/game-of-life/s (i32.mul - (get_global $game-of-life/w) - (get_global $game-of-life/h) + (get_global $assembly/game-of-life/w) + (get_global $assembly/game-of-life/h) ) ) ) - (func $game-of-life/step (; 1 ;) (type $v) + (func $assembly/game-of-life/step (; 1 ;) (type $v) (local $0 i32) (local $1 i32) (local $2 i32) @@ -41,13 +41,13 @@ (block (set_local $6 (i32.sub - (get_global $game-of-life/h) + (get_global $assembly/game-of-life/h) (i32.const 1) ) ) (set_local $7 (i32.sub - (get_global $game-of-life/w) + (get_global $assembly/game-of-life/w) (i32.const 1) ) ) @@ -65,7 +65,7 @@ (if (i32.lt_u (get_local $0) - (get_global $game-of-life/h) + (get_global $assembly/game-of-life/h) ) (block (block @@ -103,7 +103,7 @@ (if (i32.lt_u (get_local $3) - (get_global $game-of-life/w) + (get_global $assembly/game-of-life/w) ) (block (block @@ -145,7 +145,7 @@ (i32.add (i32.mul (get_local $1) - (get_global $game-of-life/w) + (get_global $assembly/game-of-life/w) ) (get_local $4) ) @@ -154,7 +154,7 @@ (i32.add (i32.mul (get_local $1) - (get_global $game-of-life/w) + (get_global $assembly/game-of-life/w) ) (get_local $3) ) @@ -164,7 +164,7 @@ (i32.add (i32.mul (get_local $1) - (get_global $game-of-life/w) + (get_global $assembly/game-of-life/w) ) (get_local $5) ) @@ -174,7 +174,7 @@ (i32.add (i32.mul (get_local $0) - (get_global $game-of-life/w) + (get_global $assembly/game-of-life/w) ) (get_local $4) ) @@ -184,7 +184,7 @@ (i32.add (i32.mul (get_local $0) - (get_global $game-of-life/w) + (get_global $assembly/game-of-life/w) ) (get_local $5) ) @@ -194,7 +194,7 @@ (i32.add (i32.mul (get_local $2) - (get_global $game-of-life/w) + (get_global $assembly/game-of-life/w) ) (get_local $4) ) @@ -204,7 +204,7 @@ (i32.add (i32.mul (get_local $2) - (get_global $game-of-life/w) + (get_global $assembly/game-of-life/w) ) (get_local $3) ) @@ -214,7 +214,7 @@ (i32.add (i32.mul (get_local $2) - (get_global $game-of-life/w) + (get_global $assembly/game-of-life/w) ) (get_local $5) ) @@ -226,7 +226,7 @@ (i32.add (i32.mul (get_local $0) - (get_global $game-of-life/w) + (get_global $assembly/game-of-life/w) ) (get_local $3) ) @@ -251,10 +251,10 @@ (i32.store8 (i32.add (i32.add - (get_global $game-of-life/s) + (get_global $assembly/game-of-life/s) (i32.mul (get_local $0) - (get_global $game-of-life/w) + (get_global $assembly/game-of-life/w) ) ) (get_local $3) @@ -270,10 +270,10 @@ (i32.store8 (i32.add (i32.add - (get_global $game-of-life/s) + (get_global $assembly/game-of-life/s) (i32.mul (get_local $0) - (get_global $game-of-life/w) + (get_global $assembly/game-of-life/w) ) ) (get_local $3) @@ -308,42 +308,3 @@ ) ) ) -(; -[program.elements] - clz - ctz - popcnt - rotl - rotr - abs - ceil - copysign - floor - max - min - nearest - sqrt - trunc - current_memory - grow_memory - unreachable - load - store - reinterpret - select - sizeof - changetype - isNaN - isFinite - assert - parseInt - parseFloat - game-of-life/w - game-of-life/h - game-of-life/s - game-of-life/init - game-of-life/step -[program.exports] - game-of-life/init - game-of-life/step -;) diff --git a/examples/game-of-life/assembly/tsconfig.json b/examples/game-of-life/assembly/tsconfig.json new file mode 100644 index 00000000..6e52b21c --- /dev/null +++ b/examples/game-of-life/assembly/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "../../../std/assembly.json", + "include": [ + "./**/*.ts" + ] +} diff --git a/tests/compiler/game-of-life.html b/examples/game-of-life/game-of-life.html similarity index 80% rename from tests/compiler/game-of-life.html rename to examples/game-of-life/game-of-life.html index d874e912..a7c8486d 100644 --- a/tests/compiler/game-of-life.html +++ b/examples/game-of-life/game-of-life.html @@ -1,11 +1,7 @@ - -