From 330752908abd9deb199f88e400d3e9070b1aa9fe Mon Sep 17 00:00:00 2001 From: dcodeIO Date: Tue, 5 Dec 2017 15:06:44 +0100 Subject: [PATCH] Implement asc in js for dist --- README.md | 2 +- bin/asc.js | 139 +++++++++++++++++++++++++++++- bin/asc.ts | 126 --------------------------- package-lock.json | 48 ++++++++--- package.json | 33 +++++-- src/builtins.ts | 10 ++- src/compiler.ts | 9 +- tests/compiler/do.wast | 20 ++--- tests/compiler/for.optimized.wast | 37 ++++++++ tests/compiler/for.ts | 6 ++ tests/compiler/for.wast | 71 +++++++++++++++ tests/compiler/while.wast | 20 ++--- 12 files changed, 348 insertions(+), 173 deletions(-) delete mode 100644 bin/asc.ts create mode 100644 tests/compiler/for.optimized.wast create mode 100644 tests/compiler/for.ts create mode 100644 tests/compiler/for.wast diff --git a/README.md b/README.md index d6d4af07..b4ef32ba 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ $> npm install $> node bin\asc yourModule.ts ``` -Building a browser bundle to `dist/assemblyscript.js` (requires [binaryen.js](https://github.com/AssemblyScript/binaryen.js)): +Building a browser bundle to `dist/assemblyscript.js` (still requires [binaryen.js](https://github.com/AssemblyScript/binaryen.js)): ``` $> npm run build diff --git a/bin/asc.js b/bin/asc.js index 5a75820b..ba211179 100644 --- a/bin/asc.js +++ b/bin/asc.js @@ -1,2 +1,137 @@ -require("ts-node").register({ project: require("path").join(__dirname, "..", "src") }); -require("./asc.ts"); +var fs = require("fs"); +var path = require("path"); +var minimist = require("minimist"); + +var assemblyscript; +var isDev = true; +try { + assemblyscript = require("../dist/assemblyscript.js"); + require("source-map-support").install(); + isDev = false; +} catch (e) { + require("ts-node").register({ project: require("path").join(__dirname, "..", "src") }); + require("../src/glue/js"); + assemblyscript = require("../src"); +} + +var conf = require("./asc.json"); +var opts = {}; + +Object.keys(conf).forEach(key => { + var opt = conf[key]; + if (opt.aliases) + (opts.alias || (opts.alias = {}))[key] = opt.aliases; + if (opt.default !== undefined) + (opts.default || (opts.default = {}))[key] = opt.default; + if (opt.type === "string") + (opts.string || (opts.string = [])).push(key); + else if (opt.type === "boolean") + (opts.boolean || (opts.boolean = [])).push(key); +}); + +var args = minimist(process.argv.slice(2), opts); +var version = require("../package.json").version; +if (isDev) version += "-dev"; + +if (args.version) { + console.log([ + "Version " + version + ].join("\n")); + process.exit(0); +} + +if (args.help || args._.length < 1) { + var options = []; + Object.keys(conf).forEach(name => { + var option = conf[name]; + var text = ""; + if (option.aliases) { + option.aliases.forEach((alias, i) => { + if (i > 0) + text += ", "; + text += "-" + alias; + }); + text += ", "; + } + text += "--" + name; + while (text.length < 20) + text += " "; + options.push(text + option.desc); + }); + console.log([ + "Version " + version, + "Syntax: asc [options] [file ...]", + "", + "Examples: asc hello.ts", + "", + "Options:" + ].concat(options).join("\n")); + process.exit(args.help ? 0 : 1); +} + +var entryPath = args._[0]; +var entryText = fs.readFileSync(entryPath, { encoding: "utf8" }); + +var parser = assemblyscript.parseFile(entryText, entryPath); + +var nextPath; +var nextText; + +while ((nextPath = parser.nextFile()) != null) { + try { + nextText = fs.readFileSync(path.join(path.dirname(entryPath), nextPath + ".ts"), { encoding: "utf8" }); + } catch (e) { + nextText = fs.readFileSync(path.join(path.dirname(entryPath), nextPath, "index.ts"), { encoding: "utf8" }); + } + assemblyscript.parseFile(nextText, nextPath, parser); +} + +var diagnostic; +var hasErrors = false; + +while ((diagnostic = assemblyscript.nextDiagnostic(parser)) != null) { + console.error(assemblyscript.formatDiagnostic(diagnostic, process.stderr.isTTY, true)); + if (assemblyscript.isError(diagnostic)) + hasErrors = true; +} + +if (hasErrors) + process.exit(1); + +var module = assemblyscript.compile(parser); + +hasErrors = false; +while ((diagnostic = assemblyscript.nextDiagnostic(parser)) != null) { + console.error(assemblyscript.formatDiagnostic(diagnostic, process.stderr.isTTY, true)); + if (assemblyscript.isError(diagnostic)) + hasErrors = true; +} + +if (hasErrors) { + module.dispose(); + process.exit(1); +} + +if (args.validate) + if (!module.validate()) { + module.dispose(); + process.exit(1); + } + +if (args.optimize) + module.optimize(); + +var hasOutput = false; + +if (args.outFile != null) { + fs.writeFileSync(args.outFile, module.toBinary()); + hasOutput = true; +} +if (args.textFile != null) { + fs.writeFileSync(args.textFile, module.toText(), { encoding: "utf8" }); + hasOutput = true; +} +if (!hasOutput) + module.print(); + +module.dispose(); diff --git a/bin/asc.ts b/bin/asc.ts deleted file mode 100644 index f92e0a39..00000000 --- a/bin/asc.ts +++ /dev/null @@ -1,126 +0,0 @@ -import * as fs from "fs"; -import * as path from "path"; -import * as minimist from "minimist"; -import "../src/glue/js"; -import * as as from "../src"; - -var conf: { [key: string]: { desc: string, type: string, aliases: string[], default: any } } = require("./asc.json"); -var opts: minimist.Opts = {}; - -Object.keys(conf).forEach(key => { - var opt = conf[key]; - if (opt.aliases) - (opts.alias || (opts.alias = {}))[key] = opt.aliases; - if (opt.default !== undefined) - (opts.default || (opts.default = {}))[key] = opt.default; - if (opt.type === "string") - ((opts.string || (opts.string = []))).push(key); - else if (opt.type === "boolean") - ((opts.boolean || (opts.boolean = []))).push(key); -}); - -const args = minimist(process.argv.slice(2), opts); -const version = require("../package.json")["version"]; - -if (args["version"]) { - console.log([ - "Version " + version - ].join("\n")); - process.exit(0); -} - -if (args["help"] || args._.length < 1) { - let options: string[] = []; - Object.keys(conf).forEach(name => { - const option = conf[name]; - let text = ""; - if (option.aliases) { - option.aliases.forEach((alias, i) => { - if (i > 0) - text += ", "; - text += "-" + alias; - }); - text += ", "; - } - text += "--" + name; - while (text.length < 20) - text += " "; - options.push(text + option.desc); - }); - console.log([ - "Version " + version, - "Syntax: asc [options] [file ...]", - "", - "Examples: asc hello.ts", - "", - "Options:" - ].concat(options).join("\n")); - process.exit(args["help"] ? 0 : 1); -} - -const entryPath = args._[0]; -const entryText = fs.readFileSync(entryPath, { encoding: "utf8" }); - -const parser = as.parseFile(entryText, entryPath); - -let nextPath: string | null; -let nextText: string; - -while ((nextPath = parser.nextFile()) != null) { - try { - nextText = fs.readFileSync(path.join(path.dirname(entryPath), nextPath + ".ts"), { encoding: "utf8" }); - } catch (e) { - nextText = fs.readFileSync(path.join(path.dirname(entryPath), nextPath, "index.ts"), { encoding: "utf8" }); - } - as.parseFile(nextText, nextPath, parser); -} - -let diagnostic: as.DiagnosticMessage | null; -let hasErrors: boolean = false; - -while ((diagnostic = as.nextDiagnostic(parser)) != null) { - console.error(as.formatDiagnostic(diagnostic, process.stderr.isTTY, true)); - if (as.isError(diagnostic)) - hasErrors = true; -} - -if (hasErrors) - process.exit(1); - -const module = as.compile(parser); - -hasErrors = false; -while ((diagnostic = as.nextDiagnostic(parser)) != null) { - console.error(as.formatDiagnostic(diagnostic, process.stderr.isTTY, true)); - if (as.isError(diagnostic)) - hasErrors = true; -} - -if (hasErrors) { - module.dispose(); - process.exit(1); -} - -if (args["validate"]) - if (!module.validate()) { - module.dispose(); - process.exit(1); - } - -if (args["optimize"]) - module.optimize(); - -let hasOutput = false; - -if (args["outFile"]) { - fs.writeFileSync(args["outFile"], module.toBinary()); - hasOutput = true; -} -if (args["textFile"]) { - fs.writeFileSync(args["textFile"], module.toText(), { encoding: "utf8" }); - hasOutput = true; -} -if (!hasOutput) - module.print(); - -module.dispose(); diff --git a/package-lock.json b/package-lock.json index e64cb706..517555d3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "@assemblyscript/next", + "name": "assemblyscript", "version": "0.5.0", "lockfileVersion": 1, "requires": true, @@ -19,6 +19,11 @@ "integrity": "sha512-q3zfJvaTroV5BjAAR+peTHEGAAhGrPX0z2EzCzpt2mwFA+qzUn2nigJLqSekXRtdULKmT8am7zjvTMZSapIgHw==", "dev": true }, + "@types/events": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-1.1.0.tgz", + "integrity": "sha512-y3bR98mzYOo0pAZuiLari+cQyiKk3UXRuT45h1RjhfeCzqkjaVsfZJNaxdgtk7/3tzOm1ozLTqEqMP3VbI48jw==" + }, "@types/glob": { "version": "5.0.33", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-5.0.33.tgz", @@ -26,7 +31,7 @@ "dev": true, "requires": { "@types/minimatch": "3.0.1", - "@types/node": "8.0.53" + "@types/node": "8.0.54" } }, "@types/long": { @@ -44,12 +49,16 @@ "@types/minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=" + "integrity": "sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=", + "dev": true }, "@types/node": { - "version": "8.0.53", - "resolved": "https://registry.npmjs.org/@types/node/-/node-8.0.53.tgz", - "integrity": "sha512-54Dm6NwYeiSQmRB1BLXKr5GELi0wFapR1npi8bnZhEcu84d/yQKqnwwXQ56hZ0RUbTG6L5nqDZaN3dgByQXQRQ==" + "version": "8.0.54", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.0.54.tgz", + "integrity": "sha512-qetMdTv3Ytz9u9ESLdcYs45LPI0mczYZIbC184n7kY0jczOqPNQsabBfVCh+na3B2shAfvC459JqHV771A8Rxg==", + "requires": { + "@types/events": "1.1.0" + } }, "acorn": { "version": "4.0.13", @@ -1897,12 +1906,18 @@ "dev": true }, "source-map-support": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", - "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", - "dev": true, + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.0.tgz", + "integrity": "sha512-vUoN3I7fHQe0R/SJLKRdKYuEdRGogsviXFkHHo17AWaTGv17VLnxw+CFXvqy+y4ORZ3doWLQcxRYfwKrsd/H7Q==", "requires": { - "source-map": "0.5.7" + "source-map": "0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } } }, "spdx-correct": { @@ -2067,6 +2082,17 @@ "tsconfig": "6.0.0", "v8flags": "3.0.0", "yn": "2.0.0" + }, + "dependencies": { + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "requires": { + "source-map": "0.5.7" + } + } } }, "tsconfig": { diff --git a/package.json b/package.json index 845fef8e..da972c6e 100644 --- a/package.json +++ b/package.json @@ -1,18 +1,27 @@ { - "name": "@assemblyscript/next", + "name": "assemblyscript", "version": "0.5.0", + "author": "Daniel Wirtz ", "license": "Apache-2.0", + "repository": { + "type": "git", + "url": "https://github.com/AssemblyScript/next.git" + }, + "bugs": { + "url": "https://github.com/AssemblyScript/next/issues" + }, "dependencies": { - "@types/minimist": "^1.2.0", - "@types/node": "^8.0.53", + "@types/node": "^8.0.54", "binaryen": "39.0.0-nightly.20171116", - "minimist": "^1.2.0" + "minimist": "^1.2.0", + "source-map-support": "^0.5.0" }, "devDependencies": { "@types/chalk": "^2.2.0", "@types/diff": "^3.2.2", "@types/glob": "^5.0.33", "@types/long": "^3.0.32", + "@types/minimist": "^1.2.0", "chalk": "^2.3.0", "diff": "^3.4.0", "glob": "^7.1.2", @@ -22,13 +31,27 @@ "typescript": "^2.6.2", "webpack": "^3.10.0" }, + "main": "dist/assemblyscript.js", "bin": { "asc": "bin/asc.js" }, "scripts": { "build": "webpack", + "clean": "rm dist/assemblyscript.*", "test:parser": "ts-node -P src tests/parser", "test:compiler": "ts-node -P src tests/compiler", "test": "npm run test:parser && npm run test:compiler" - } + }, + "files": [ + "assembly.d.ts", + "bin/asc.js", + "bin/asc.json", + "dist/assemblyscript.js", + "dist/assemblyscript.js.map", + "LICENSE", + "NOTICE", + "package.json", + "package-lock.json", + "README.md" + ] } diff --git a/src/builtins.ts b/src/builtins.ts index 921c939a..78c1e9c8 100644 --- a/src/builtins.ts +++ b/src/builtins.ts @@ -32,13 +32,16 @@ export function initialize(program: Program): void { addFunction(program, "isNaN", true); addFunction(program, "isFinite", true); addFunction(program, "assert"); + // addFunction(program, "fmod", false, true); + // addFunction(program, "pow", true, true); } /** Adds a built-in function to the specified program. */ -function addFunction(program: Program, name: string, isGeneric: bool = false): void { +function addFunction(program: Program, name: string, isGeneric: bool = false, isImport: bool = false): void { let prototype: FunctionPrototype = new FunctionPrototype(program, name, null, null); - prototype.isGeneric = isGeneric; prototype.isBuiltIn = true; + prototype.isGeneric = isGeneric; + prototype.isImport = isImport; program.elements.set(name, prototype); } @@ -413,6 +416,9 @@ export function compileCall(compiler: Compiler, internalName: string, typeArgume compiler.module.createUnary(UnaryOp.EqzI32, arg0), compiler.module.createUnreachable() ); + + // case "fmod": + // case "pow": } return 0; } diff --git a/src/compiler.ts b/src/compiler.ts index 9666ae44..c2953382 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -698,7 +698,12 @@ export class Compiler extends DiagnosticEmitter { } compileBlockStatement(statement: BlockStatement): ExpressionRef { - return this.module.createBlock(null, this.compileStatements(statement.statements), NativeType.None); + const statements: Statement[] = statement.statements; + if (statements.length == 0) + return this.module.createNop(); + if (statements.length == 1) + return this.compileStatement(statements[0]); + return this.module.createBlock(null, this.compileStatements(statements), NativeType.None); } compileBreakStatement(statement: BreakStatement): ExpressionRef { @@ -962,7 +967,7 @@ export class Compiler extends DiagnosticEmitter { throw new Error("unexpected expression kind"); } - if (conversionKind != ConversionKind.NONE) { + if (conversionKind != ConversionKind.NONE && this.currentType != contextualType) { expr = this.convertExpression(expr, this.currentType, contextualType, conversionKind, expression); this.currentType = contextualType; } diff --git a/tests/compiler/do.wast b/tests/compiler/do.wast index c3f4ad1c..f29aad49 100644 --- a/tests/compiler/do.wast +++ b/tests/compiler/do.wast @@ -8,12 +8,10 @@ (func $do/loopDo (; 0 ;) (type $iv) (param $0 i32) (block $break$1.1 (loop $continue$1.1 - (block - (set_local $0 - (i32.sub - (get_local $0) - (i32.const 1) - ) + (set_local $0 + (i32.sub + (get_local $0) + (i32.const 1) ) ) (br_if $continue$1.1 @@ -34,12 +32,10 @@ ) (block $break$1.2 (loop $continue$1.2 - (block - (set_local $0 - (i32.sub - (get_local $0) - (i32.const 1) - ) + (set_local $0 + (i32.sub + (get_local $0) + (i32.const 1) ) ) (br_if $continue$1.2 diff --git a/tests/compiler/for.optimized.wast b/tests/compiler/for.optimized.wast new file mode 100644 index 00000000..e2892b45 --- /dev/null +++ b/tests/compiler/for.optimized.wast @@ -0,0 +1,37 @@ +(module + (type $v (func)) + (global $for/i (mut i32) (i32.const 0)) + (memory $0 1) + (data (i32.const 4) "\08") + (export "memory" (memory $0)) + (start $start) + (func $start (; 0 ;) (type $v) + (set_global $for/i + (i32.const 0) + ) + (loop $continue$1.1 + (if + (i32.lt_s + (get_global $for/i) + (i32.const 10) + ) + (block + (set_global $for/i + (i32.add + (get_global $for/i) + (i32.const 1) + ) + ) + (br $continue$1.1) + ) + ) + ) + (if + (i32.ne + (get_global $for/i) + (i32.const 10) + ) + (unreachable) + ) + ) +) diff --git a/tests/compiler/for.ts b/tests/compiler/for.ts new file mode 100644 index 00000000..1549178b --- /dev/null +++ b/tests/compiler/for.ts @@ -0,0 +1,6 @@ +let i: i32; +for (i = 0; i < 10; ++i) { + ; +} +if (i != 10) + unreachable(); diff --git a/tests/compiler/for.wast b/tests/compiler/for.wast new file mode 100644 index 00000000..5ab91989 --- /dev/null +++ b/tests/compiler/for.wast @@ -0,0 +1,71 @@ +(module + (type $v (func)) + (global $for/i (mut i32) (i32.const 0)) + (memory $0 1) + (data (i32.const 4) "\08\00\00\00") + (export "memory" (memory $0)) + (start $start) + (func $start (; 0 ;) (type $v) + (block $break$1.1 + (set_global $for/i + (i32.const 0) + ) + (loop $continue$1.1 + (if + (i32.lt_s + (get_global $for/i) + (i32.const 10) + ) + (block + (nop) + (set_global $for/i + (i32.add + (get_global $for/i) + (i32.const 1) + ) + ) + (br $continue$1.1) + ) + ) + ) + ) + (if + (i32.ne + (get_global $for/i) + (i32.const 10) + ) + (unreachable) + ) + ) +) +(; +[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 + isNaN + isFinite + assert + for/i +[program.exports] + +;) diff --git a/tests/compiler/while.wast b/tests/compiler/while.wast index 25863f99..767e0650 100644 --- a/tests/compiler/while.wast +++ b/tests/compiler/while.wast @@ -11,12 +11,10 @@ (if (get_local $0) (block - (block - (set_local $0 - (i32.sub - (get_local $0) - (i32.const 1) - ) + (set_local $0 + (i32.sub + (get_local $0) + (i32.const 1) ) ) (br $continue$1.1) @@ -43,12 +41,10 @@ (if (get_local $0) (block - (block - (set_local $0 - (i32.sub - (get_local $0) - (i32.const 1) - ) + (set_local $0 + (i32.sub + (get_local $0) + (i32.const 1) ) ) (br $continue$1.2)