Restructure types; Add a use-case specific options parser; Allow (re)creation of specific parser fixtures

This commit is contained in:
dcodeIO 2018-07-03 03:06:01 +02:00
parent 82da2d1f6d
commit 5ca5df3dc7
29 changed files with 486 additions and 279 deletions

View File

@ -11,34 +11,30 @@
* @module cli/asc * @module cli/asc
*/ */
// Use "." instead of "/" as cwd in browsers
if (process.browser) process.cwd = function() { return "."; };
const fs = require("fs"); const fs = require("fs");
const path = require("path"); const path = require("path");
const utf8 = require("@protobufjs/utf8"); const utf8 = require("@protobufjs/utf8");
const colors = require("./util/colors"); const colorsUtil = require("./util/colors");
const optionsUtil = require("./util/options");
const EOL = process.platform === "win32" ? "\r\n" : "\n"; const EOL = process.platform === "win32" ? "\r\n" : "\n";
// Use distribution files if present, otherwise run the sources directly // Use distribution files if present, otherwise run the sources directly
var assemblyscript, isDev; var assemblyscript, isDev = false;
(() => { (() => {
try { try {
assemblyscript = require("../dist/assemblyscript.js"); assemblyscript = require("../dist/assemblyscript.js");
isDev = false;
} catch (e) { } catch (e) {
try { try {
require("ts-node").register({ require("ts-node").register({ project: path.join(__dirname, "..", "src", "tsconfig.json") });
project: path.join(__dirname, "..", "src", "tsconfig.json"),
files: [ // see: https://github.com/TypeStrong/ts-node/issues/620
path.join(__dirname, "..", "std", "portable.d.ts"),
path.join(__dirname, "..", "src", "glue", "binaryen.d.ts")
]
});
require("../src/glue/js"); require("../src/glue/js");
assemblyscript = require("../src"); assemblyscript = require("../src");
isDev = true; isDev = true;
} catch (e) { } catch (e) {
// last resort: same directory CommonJS // last resort: same directory CommonJS
assemblyscript = eval("require('./assemblyscript')"); assemblyscript = eval("require('./assemblyscript')");
isDev = false;
} }
} }
})(); })();
@ -70,7 +66,7 @@ exports.defaultShrinkLevel = 1;
/** Bundled library files. */ /** Bundled library files. */
exports.libraryFiles = exports.isBundle ? BUNDLE_LIBRARY : (() => { // set up if not a bundle exports.libraryFiles = exports.isBundle ? BUNDLE_LIBRARY : (() => { // set up if not a bundle
const libDir = path.join(__dirname, "..", "std", "assembly"); const libDir = path.join(__dirname, "..", "std", "assembly");
const libFiles = require("glob").sync("**/*.ts", { cwd: libDir }); const libFiles = require("glob").sync("**/!(*.d).ts", { cwd: libDir });
const bundled = {}; const bundled = {};
libFiles.forEach(file => bundled[file.replace(/\.ts$/, "")] = fs.readFileSync(path.join(libDir, file), "utf8" )); libFiles.forEach(file => bundled[file.replace(/\.ts$/, "")] = fs.readFileSync(path.join(libDir, file), "utf8" ));
return bundled; return bundled;
@ -80,8 +76,8 @@ exports.libraryFiles = exports.isBundle ? BUNDLE_LIBRARY : (() => { // set up if
exports.definitionFiles = exports.isBundle ? BUNDLE_DEFINITIONS : (() => { // set up if not a bundle exports.definitionFiles = exports.isBundle ? BUNDLE_DEFINITIONS : (() => { // set up if not a bundle
const stdDir = path.join(__dirname, "..", "std"); const stdDir = path.join(__dirname, "..", "std");
return { return {
"assembly": fs.readFileSync(path.join(stdDir, "assembly.d.ts"), "utf8"), "assembly": fs.readFileSync(path.join(stdDir, "assembly", "index.d.ts"), "utf8"),
"portable": fs.readFileSync(path.join(stdDir, "portable.d.ts"), "utf8") "portable": fs.readFileSync(path.join(stdDir, "portable", "index.d.ts"), "utf8")
}; };
})(); })();
@ -94,12 +90,16 @@ exports.compileString = (sources, options) => {
binary: null, binary: null,
text: null text: null
}); });
exports.main([ var argv = [
"--binaryFile", "binary", "--binaryFile", "binary",
"--textFile", "text", "--textFile", "text",
...Object.keys(options || {}).map(arg => `--${arg}=${options[arg]}`), ];
...Object.keys(sources), Object.keys(options || {}).forEach(key => {
], { var val = options[key];
if (Array.isArray(val)) val.forEach(val => argv.push("--" + key, String(val)));
else argv.push("--" + key, String(val));
});
exports.main(argv.concat(Object.keys(sources)), {
stdout: output.stdout, stdout: output.stdout,
stderr: output.stderr, stderr: output.stderr,
readFile: name => sources.hasOwnProperty(name) ? sources[name] : null, readFile: name => sources.hasOwnProperty(name) ? sources[name] : null,
@ -129,22 +129,34 @@ exports.main = function main(argv, options, callback) {
if (!stdout) throw Error("'options.stdout' must be specified"); if (!stdout) throw Error("'options.stdout' must be specified");
if (!stderr) throw Error("'options.stderr' must be specified"); if (!stderr) throw Error("'options.stderr' must be specified");
const args = parseArguments(argv); const opts = optionsUtil.parse(argv, exports.options);
const indent = 24; const args = opts.options;
argv = opts.arguments;
if (args.noColors) { if (args.noColors) {
colors.stdout.supported = colorsUtil.stdout.supported =
colors.stderr.supported = false; colorsUtil.stderr.supported = false;
} else { } else {
colors.stdout = colors.from(stdout); colorsUtil.stdout = colorsUtil.from(stdout);
colors.stderr = colors.from(stderr); colorsUtil.stderr = colorsUtil.from(stderr);
}
// Check for unknown arguments
if (opts.unknown.length) {
opts.unknown.forEach(arg => {
stderr.write(colorsUtil.stderr.yellow("WARN: ") + "Unknown option '" + arg + "'" + EOL);
});
}
// Check for trailing arguments
if (opts.trailing.length) {
stderr.write(colorsUtil.stderr.yellow("WARN: ") + "Unsupported trailing arguments: " + opts.trailing.join(" ") + EOL);
} }
// Use default callback if none is provided // Use default callback if none is provided
if (!callback) callback = function defaultCallback(err) { if (!callback) callback = function defaultCallback(err) {
var code = 0; var code = 0;
if (err) { if (err) {
stderr.write(colors.stderr.red("ERROR: ") + err.stack.replace(/^ERROR: /i, "") + EOL); stderr.write(colorsUtil.stderr.red("ERROR: ") + err.stack.replace(/^ERROR: /i, "") + EOL);
code = 1; code = 1;
} }
return code; return code;
@ -156,43 +168,22 @@ exports.main = function main(argv, options, callback) {
return callback(null); return callback(null);
} }
// Print the help message if requested or no source files are provided // Print the help message if requested or no source files are provided
if (args.help || args._.length < 1) { if (args.help || !argv.length) {
const opts = [];
Object.keys(exports.options).forEach(name => {
var option = exports.options[name];
var text = " ";
text += "--" + name;
if (option.aliases && option.aliases[0].length === 1) {
text += ", -" + option.aliases[0];
}
while (text.length < indent) {
text += " ";
}
if (Array.isArray(option.description)) {
opts.push(text + option.description[0] + option.description.slice(1).map(line => {
for (let i = 0; i < indent; ++i) {
line = " " + line;
}
return EOL + line;
}).join(""));
} else {
opts.push(text + option.description);
}
});
var out = args.help ? stdout : stderr; var out = args.help ? stdout : stderr;
var color = args.help ? colors.stdout : colors.stderr; var color = args.help ? colorsUtil.stdout : colorsUtil.stderr;
out.write([ out.write([
color.white("Syntax"), color.white("SYNTAX"),
" " + color.cyan("asc") + " [entryFile ...] [options]", " " + color.cyan("asc") + " [entryFile ...] [options]",
"", "",
color.white("Examples"), color.white("EXAMPLES"),
" " + color.cyan("asc") + " hello.ts", " " + color.cyan("asc") + " hello.ts",
" " + color.cyan("asc") + " hello.ts -b hello.wasm -t hello.wat", " " + color.cyan("asc") + " hello.ts -b hello.wasm -t hello.wat",
" " + color.cyan("asc") + " hello1.ts hello2.ts -b -O > hello.wasm", " " + color.cyan("asc") + " hello1.ts hello2.ts -b -O > hello.wasm",
"", "",
color.white("Options"), color.white("OPTIONS"),
].concat(opts).join(EOL) + EOL); ].concat(
optionsUtil.help(exports.options, 24, EOL)
).join(EOL) + EOL);
return callback(null); return callback(null);
} }
@ -209,7 +200,6 @@ exports.main = function main(argv, options, callback) {
// Set up transforms // Set up transforms
const transforms = []; const transforms = [];
if (args.transform) { if (args.transform) {
if (typeof args.transform === "string") args.transform = args.transform.split(",");
args.transform.forEach(transform => args.transform.forEach(transform =>
transforms.push( transforms.push(
require( require(
@ -246,8 +236,9 @@ exports.main = function main(argv, options, callback) {
} }
const customLibDirs = []; const customLibDirs = [];
if (args.lib) { if (args.lib) {
if (typeof args.lib === "string") args.lib = args.lib.split(","); let lib = args.lib;
Array.prototype.push.apply(customLibDirs, args.lib.map(lib => lib.trim())); if (typeof lib === "string") lib = lib.split(",");
Array.prototype.push.apply(customLibDirs, lib.map(lib => lib.trim()));
for (let i = 0, k = customLibDirs.length; i < k; ++i) { // custom for (let i = 0, k = customLibDirs.length; i < k; ++i) { // custom
let libDir = customLibDirs[i]; let libDir = customLibDirs[i];
let libFiles; let libFiles;
@ -275,10 +266,10 @@ exports.main = function main(argv, options, callback) {
} }
// Include entry files // Include entry files
for (let i = 0, k = args._.length; i < k; ++i) { for (let i = 0, k = argv.length; i < k; ++i) {
const filename = args._[i]; const filename = argv[i];
let sourcePath = filename.replace(/\\/g, "/").replace(/(\.ts|\/)$/, ""); let sourcePath = String(filename).replace(/\\/g, "/").replace(/(\.ts|\/)$/, "");
// Try entryPath.ts, then entryPath/index.ts // Try entryPath.ts, then entryPath/index.ts
let sourceText = readFile(path.join(baseDir, sourcePath) + ".ts"); let sourceText = readFile(path.join(baseDir, sourcePath) + ".ts");
@ -385,51 +376,28 @@ exports.main = function main(argv, options, callback) {
const program = assemblyscript.finishParsing(parser); const program = assemblyscript.finishParsing(parser);
// Set up optimization levels // Set up optimization levels
var optimizeLevel = -1; var optimizeLevel = 0;
var shrinkLevel = 0; var shrinkLevel = 0;
var debugInfo = !args.noDebug; if (args.optimize) {
if (args.optimize !== false) { optimizeLevel = exports.defaultOptimizeLevel;
if (typeof args.optimize === "number") { shrinkLevel = exports.defaultShrinkLevel;
optimizeLevel = args.optimize;
} else if (args["0"]) {
optimizeLevel = 0;
} else if (args["1"]) {
optimizeLevel = 1;
} else if (args["2"]) {
optimizeLevel = 2;
} else if (args["3"]) {
optimizeLevel = 3;
} else if (args.optimize === true) {
optimizeLevel = exports.defaultOptimizeLevel;
shrinkLevel = exports.defaultShrinkLevel;
} else
optimizeLevel = 0;
}
if (args["s"]) {
shrinkLevel = 1;
} else if (args["z"]) {
shrinkLevel = 2;
} }
if (typeof args.optimizeLevel === "number") { if (typeof args.optimizeLevel === "number") {
optimizeLevel = args.optimizeLevel; optimizeLevel = args.optimizeLevel;
} }
if (typeof args.shrinkLevel === "number") { if (typeof args.shrinkLevel === "number") {
shrinkLevel = args.shrinkLevel; shrinkLevel = args.shrinkLevel;
} else if (args.shrinkLevel === "s") {
shrinkLevel = 1;
} else if (args.shrinkLevel === "z") {
shrinkLevel = 2;
} }
optimizeLevel = Math.max(optimizeLevel, 0); optimizeLevel = Math.min(Math.max(optimizeLevel, 0), 3);
shrinkLevel = Math.max(shrinkLevel, 0); shrinkLevel = Math.min(Math.max(shrinkLevel, 0), 2);
// Begin compilation // Begin compilation
const compilerOptions = assemblyscript.createOptions(); const compilerOptions = assemblyscript.createOptions();
assemblyscript.setTarget(compilerOptions, 0); assemblyscript.setTarget(compilerOptions, 0);
assemblyscript.setNoTreeShaking(compilerOptions, !!args.noTreeShaking); assemblyscript.setNoTreeShaking(compilerOptions, args.noTreeShaking);
assemblyscript.setNoAssert(compilerOptions, !!args.noAssert); assemblyscript.setNoAssert(compilerOptions, args.noAssert);
assemblyscript.setImportMemory(compilerOptions, !!args.importMemory); assemblyscript.setImportMemory(compilerOptions, args.importMemory);
assemblyscript.setImportTable(compilerOptions, !!args.importTable); assemblyscript.setImportTable(compilerOptions, args.importTable);
assemblyscript.setMemoryBase(compilerOptions, args.memoryBase >>> 0); assemblyscript.setMemoryBase(compilerOptions, args.memoryBase >>> 0);
assemblyscript.setSourceMap(compilerOptions, args.sourceMap != null); assemblyscript.setSourceMap(compilerOptions, args.sourceMap != null);
assemblyscript.setOptimizeLevelHints(compilerOptions, optimizeLevel, shrinkLevel); assemblyscript.setOptimizeLevelHints(compilerOptions, optimizeLevel, shrinkLevel);
@ -515,7 +483,7 @@ exports.main = function main(argv, options, callback) {
module.setOptimizeLevel(optimizeLevel); module.setOptimizeLevel(optimizeLevel);
module.setShrinkLevel(shrinkLevel); module.setShrinkLevel(shrinkLevel);
module.setDebugInfo(debugInfo); module.setDebugInfo(!args.noDebug);
var runPasses = []; var runPasses = [];
if (args.runPasses) { if (args.runPasses) {
@ -741,7 +709,7 @@ exports.main = function main(argv, options, callback) {
var files; var files;
try { try {
stats.readTime += measure(() => { stats.readTime += measure(() => {
files = require("glob").sync("*.ts", { cwd: dirname }); files = require("glob").sync("!(*.d).ts", { cwd: dirname });
}); });
return files; return files;
} catch (e) { } catch (e) {
@ -764,25 +732,23 @@ exports.main = function main(argv, options, callback) {
} }
} }
/** Parses the specified command line arguments. */ var argumentSubstitutions = {
function parseArguments(argv) { "-O" : [ "--optimize" ],
const opts = {}; "-Os" : [ "--optimize", "--shrinkLevel", "1" ],
Object.keys(exports.options).forEach(key => { "-Oz" : [ "--optimize", "--shrinkLevel", "2" ],
const opt = exports.options[key]; "-O0" : [ "--optimizeLevel", "0", "--shrinkLevel", "0" ],
if (opt.aliases) { "-O0s": [ "--optimizeLevel", "0", "--shrinkLevel", "1" ],
(opts.alias || (opts.alias = {}))[key] = opt.aliases; "-O0z": [ "--optimizeLevel", "0", "--shrinkLevel", "2" ],
} "-O1" : [ "--optimizeLevel", "1", "--shrinkLevel", "0" ],
if (opt.default !== undefined) { "-O1s": [ "--optimizeLevel", "1", "--shrinkLevel", "1" ],
(opts.default || (opts.default = {}))[key] = opt.default; "-O1z": [ "--optimizeLevel", "1", "--shrinkLevel", "2" ],
} "-O2" : [ "--optimizeLevel", "2", "--shrinkLevel", "0" ],
if (opt.type === "string") { "-O2s": [ "--optimizeLevel", "2", "--shrinkLevel", "1" ],
(opts.string || (opts.string = [])).push(key); "-O2z": [ "--optimizeLevel", "2", "--shrinkLevel", "2" ],
} else if (opt.type === "boolean") { "-O3" : [ "--optimizeLevel", "3", "--shrinkLevel", "0" ],
(opts.boolean || (opts.boolean = [])).push(key); "-O3s": [ "--optimizeLevel", "3", "--shrinkLevel", "1" ],
} "-O3z": [ "--optimizeLevel", "3", "--shrinkLevel", "2" ],
}); };
return require("minimist")(argv, opts);
}
/** Checks diagnostics emitted so far for errors. */ /** Checks diagnostics emitted so far for errors. */
function checkDiagnostics(emitter, stderr) { function checkDiagnostics(emitter, stderr) {

View File

@ -1,17 +1,17 @@
{ {
"version": { "version": {
"description": "Prints just the compiler's version and exits.", "description": "Prints just the compiler's version and exits.",
"type": "boolean", "type": "b",
"aliases": [ "v" ] "alias": "v"
}, },
"help": { "help": {
"description": "Prints this message and exits.", "description": "Prints this message and exits.",
"type": "boolean", "type": "b",
"aliases": [ "h" ] "alias": "h"
}, },
"optimize": { "optimize": {
"description": [ "description": [
"Optimizes the module. Also accepts the optimize level:", "Optimizes the module. Also has the usual shorthands:",
"", "",
" -O Uses defaults. Equivalent to -O2s", " -O Uses defaults. Equivalent to -O2s",
" -O0 Equivalent to --optimizeLevel 0", " -O0 Equivalent to --optimizeLevel 0",
@ -22,109 +22,119 @@
" -O3s Equivalent to -O3 with --shrinkLevel 1 etc.", " -O3s Equivalent to -O3 with --shrinkLevel 1 etc.",
"" ""
], ],
"type": "boolean", "type": "b",
"aliases": [ "O" ] "alias": "O"
}, },
"optimizeLevel": { "optimizeLevel": {
"description": "How much to focus on optimizing code. [0-3]", "description": "How much to focus on optimizing code. [0-3]",
"type": "number" "type": "i"
}, },
"shrinkLevel": { "shrinkLevel": {
"description": "How much to focus on shrinking code size. [0-2, s=1, z=2]", "description": "How much to focus on shrinking code size. [0-2, s=1, z=2]",
"type": "number" "type": "i"
}, },
"validate": { "validate": {
"description": "Validates the module using Binaryen. Exits if invalid.", "description": "Validates the module using Binaryen. Exits if invalid.",
"type": "boolean", "type": "b",
"aliases": [ "c", "check" ] "alias": "c",
"default": false
}, },
"baseDir": { "baseDir": {
"description": "Specifies the base directory of input and output files.", "description": "Specifies the base directory of input and output files.",
"type": "string" "type": "s",
"default": "."
}, },
"outFile": { "outFile": {
"description": "Specifies the output file. File extension indicates format.", "description": "Specifies the output file. File extension indicates format.",
"type": "string", "type": "s",
"aliases": [ "o" ] "alias": "o"
}, },
"binaryFile": { "binaryFile": {
"description": "Specifies the binary output file (.wasm).", "description": "Specifies the binary output file (.wasm).",
"type": "string", "type": "s",
"aliases": [ "b" ] "alias": "b"
}, },
"textFile": { "textFile": {
"description": "Specifies the text output file (.wat).", "description": "Specifies the text output file (.wat).",
"type": "string", "type": "s",
"aliases": [ "t" ] "alias": "t"
}, },
"asmjsFile": { "asmjsFile": {
"description": "Specifies the asm.js output file (.js).", "description": "Specifies the asm.js output file (.js).",
"type": "string", "type": "s",
"aliases": [ "a" ] "alias": "a"
}, },
"idlFile": { "idlFile": {
"description": "Specifies the WebIDL output file (.webidl).", "description": "Specifies the WebIDL output file (.webidl).",
"type": "string", "type": "s",
"aliases": [ "i" ] "alias": "i"
}, },
"tsdFile": { "tsdFile": {
"description": "Specifies the TypeScript definition output file (.d.ts).", "description": "Specifies the TypeScript definition output file (.d.ts).",
"type": "string", "type": "s",
"aliases": [ "d", "dtsFile" ] "alias": "d"
}, },
"sourceMap": { "sourceMap": {
"description": [ "description": [
"Enables source map generation. Optionally takes the URL", "Enables source map generation. Optionally takes the URL",
"used to reference the source map from the binary file." "used to reference the source map from the binary file."
], ],
"type": "string" "type": "s"
}, },
"noTreeShaking": { "noTreeShaking": {
"description": "Disables compiler-level tree-shaking, compiling everything.", "description": "Disables compiler-level tree-shaking, compiling everything.",
"type": "boolean" "type": "b",
"default": false
}, },
"noDebug": { "noDebug": {
"description": "Disables maintaining of debug information in binaries.", "description": "Disables maintaining of debug information in binaries.",
"type": "boolean" "type": "b",
"default": false
}, },
"noAssert": { "noAssert": {
"description": "Replaces assertions with just their value without trapping.", "description": "Replaces assertions with just their value without trapping.",
"type": "boolean" "type": "b",
"default": false
}, },
"noEmit": { "noEmit": {
"description": "Performs compilation as usual but does not emit code.", "description": "Performs compilation as usual but does not emit code.",
"type": "boolean" "type": "b",
"default": false
}, },
"importMemory": { "importMemory": {
"description": "Imports the memory instance provided by the embedder.", "description": "Imports the memory instance provided by the embedder.",
"type": "boolean" "type": "b",
"default": false
}, },
"memoryBase": { "memoryBase": {
"description": "Sets the start offset of compiler-generated static memory.", "description": "Sets the start offset of compiler-generated static memory.",
"type": "number" "type": "i",
"default": 0
}, },
"importTable": { "importTable": {
"description": "Imports the function table instance provided by the embedder.", "description": "Imports the function table instance provided by the embedder.",
"type": "boolean" "type": "b",
"default": false
}, },
"noLib": { "noLib": {
"description": "Does not include the shipped standard library.", "description": "Does not include the shipped standard library.",
"type": "boolean" "type": "b",
"default": false
}, },
"lib": { "lib": {
"description": [ "description": [
"Adds one or multiple paths to custom library components and", "Adds one or multiple paths to custom library components and",
"uses exports of all top-level files at this path as globals." "uses exports of all top-level files at this path as globals."
], ],
"type": "string" "type": "s"
}, },
"use": { "use": {
"description": [ "description": [
"Aliases a global object under another name, e.g., to switch", "Aliases a global object under another name, e.g., to switch",
"the default 'Math' implementation used: --use Math=JSMath" "the default 'Math' implementation used: --use Math=JSMath"
], ],
"type": "string", "type": "s",
"aliases": [ "u" ] "alias": "u"
}, },
"trapMode": { "trapMode": {
"description": [ "description": [
@ -135,7 +145,7 @@
" js Replace trapping operations with JS semantics.", " js Replace trapping operations with JS semantics.",
"" ""
], ],
"type": "string", "type": "s",
"default": "allow" "default": "allow"
}, },
"runPasses": { "runPasses": {
@ -143,7 +153,7 @@
"Specifies additional Binaryen passes to run after other", "Specifies additional Binaryen passes to run after other",
"optimizations, if any. See: Binaryen/src/passes/pass.cpp" "optimizations, if any. See: Binaryen/src/passes/pass.cpp"
], ],
"type": "string" "type": "s"
}, },
"enable": { "enable": {
"description": [ "description": [
@ -153,19 +163,34 @@
" mutable-global Enables mutable global imports and exports", " mutable-global Enables mutable global imports and exports",
"" ""
], ],
"type": "string", "type": "s"
"aliases": [ "feature" ]
}, },
"transform": { "transform": {
"description": "Specifies the path to a custom transform to 'require'.", "description": "Specifies the path to a custom transform to 'require'.",
"type": "string" "type": "S"
}, },
"measure": { "measure": {
"description": "Prints measuring information on I/O and compile times.", "description": "Prints measuring information on I/O and compile times.",
"type": "boolean" "type": "b",
"default": false
}, },
"noColors": { "noColors": {
"description": "Disables terminal colors.", "description": "Disables terminal colors.",
"type": "boolean" "type": "b",
} "default": false
},
"-Os": { "value": { "optimize": true, "shrinkLevel": 1 } },
"-Oz": { "value": { "optimize": true, "shrinkLevel": 2 } },
"-O0": { "value": { "optimizeLevel": 0, "shrinkLevel": 0 } },
"-O1": { "value": { "optimizeLevel": 1, "shrinkLevel": 0 } },
"-O2": { "value": { "optimizeLevel": 2, "shrinkLevel": 0 } },
"-O3": { "value": { "optimizeLevel": 3, "shrinkLevel": 0 } },
"-O0s": { "value": { "optimizeLevel": 0, "shrinkLevel": 1 } },
"-O1s": { "value": { "optimizeLevel": 1, "shrinkLevel": 1 } },
"-O2s": { "value": { "optimizeLevel": 2, "shrinkLevel": 1 } },
"-O3s": { "value": { "optimizeLevel": 3, "shrinkLevel": 1 } },
"-O0z": { "value": { "optimizeLevel": 0, "shrinkLevel": 2 } },
"-O1z": { "value": { "optimizeLevel": 1, "shrinkLevel": 2 } },
"-O2z": { "value": { "optimizeLevel": 2, "shrinkLevel": 2 } },
"-O3z": { "value": { "optimizeLevel": 3, "shrinkLevel": 2 } }
} }

View File

@ -1,5 +1,5 @@
var proc = typeof process !== "undefined" && process || {}; var proc = typeof process !== "undefined" && process || {};
var isCI = proc.env && "CI" in proc.env; var isCI = proc.env && "CI" in proc.env; // doesn't work when bundled because 'process' is a mock
function from(stream, base) { function from(stream, base) {
var colors = base || {}; var colors = base || {};

41
cli/util/options.d.ts vendored Normal file
View File

@ -0,0 +1,41 @@
/** Configuration object. */
interface Config {
[key: string]: {
/** Textual description. */
description?: string | string[],
/** Data type. One of (b)oolean [default], (i)nteger, (f)loat or (s)tring. Uppercase means multiple values. */
type?: "b" | "i" | "f" | "s", "I", "F", "S",
/** Substituted options, if any. */
value?: { [key: string]: number | string },
/** Short alias, if any. */
alias?: string
};
}
/** Parsing result. */
interface Result {
/** Parsed options. */
options: { [key: string]: number | string },
/** Unknown options. */
unknown: string[],
/** Normal arguments. */
arguments: string[],
/** Trailing arguments. */
trailing: string[]
}
/** Parses the specified command line arguments according to the given configuration. */
export function parse(argv: string[], config: Config): Result;
/** Help formatting options. */
interface HelpOptions {
/** Leading indent. Defaults to 2. */
indent?: number,
/** Table padding. Defaults to 24. */
padding?: number,
/** End of line character. Defaults to "\n". */
eol?: string
}
/** Generates the help text for the specified configuration. */
export function help(config: Config, options?: HelpOptions): string;

105
cli/util/options.js Normal file
View File

@ -0,0 +1,105 @@
// type | meaning
// -----|---------------
// b | boolean
// i | integer
// f | float
// s | string
// I | integer array
// F | float array
// S | string array
/** Parses the specified command line arguments according to the given configuration. */
function parse(argv, config) {
var options = {};
var unknown = [];
var arguments = [];
var trailing = [];
// make an alias map and initialize defaults
var aliases = {};
Object.keys(config).forEach(key => {
var option = config[key];
if (option.alias != null) {
if (typeof option.alias === "string") aliases[option.alias] = key;
else if (Array.isArray(option.alias)) option.alias.forEach(alias => aliases[alias] = key);
}
if (option.default != null) options[key] = option.default;
});
// iterate over argv
for (var i = 0, k = (argv = argv.slice()).length; i < k; ++i) {
let arg = argv[i];
if (arg == "--") { ++i; break; }
let match = /^(?:(\-\w)|(\-\-\w{2,})(?:=(.*))?)$/.exec(arg), option, key;
if (match) {
if (config[arg]) option = config[key = arg]; // exact
else if (match[1] != null) option = config[key = aliases[match[1].substring(1)]]; // alias
else if (match[2] != null) {
option = config[key = match[2].substring(2)]; // full
if (option && match[3] != null) argv[i--] = match[3];
}
} else {
if (arg.charCodeAt(0) == 45) option = config[key = arg]; // exact
else { arguments.push(arg); continue; } // argument
}
if (option) {
if (option.type == null || option.type === "b") options[key] = true; // flag
else {
if (i + 1 < argv.length && argv[i + 1].charCodeAt(0) != 45) { // present
switch (option.type) {
case "i": options[key] = parseInt(argv[++i], 10); break;
case "I": options[key] = (options[key] || []).concat(parseInt(argv[++i], 10)); break;
case "f": options[key] = parseFloat(argv[++i]); break;
case "F": options[key] = (options[key] || []).concat(parseFloat(argv[++i])); break;
case "s": options[key] = String(argv[++i]); break;
case "S": options[key] = (options[key] || []).concat(argv[++i].split(",")); break;
default: unknown.push(arg); --i;
}
} else { // omitted
switch (option.type) {
case "i":
case "f": options[key] = option.default || 0; break;
case "s": options[key] = option.default || ""; break;
case "I":
case "F":
case "S": options[key] = options.default || []; break;
default: unknown.push(arg);
}
}
}
if (option.value) Object.keys(option.value).forEach(k => options[k] = option.value[k]);
} else unknown.push(arg);
}
while (i < k) trailing.push(argv[i++]); // trailing
return { options, unknown, arguments, trailing };
}
exports.parse = parse;
/** Generates the help text for the specified configuration. */
function help(config, options) {
if (!options) options = {};
var indent = options.indent || 2;
var padding = options.padding || 24;
var eol = options.eol || "\n";
var sb = [];
Object.keys(config).forEach(key => {
var option = config[key];
if (option.description == null) return;
var text = "";
while (text.length < indent) text += " ";
text += "--" + key;
if (option.alias) text += ", -" + option.alias;
while (text.length < padding) text += " ";
if (Array.isArray(option.description)) {
sb.push(text + option.description[0] + option.description.slice(1).map(line => {
for (let i = 0; i < padding; ++i) line = " " + line;
return eol + line;
}).join(""));
} else sb.push(text + option.description);
});
return sb.join(eol);
}
exports.help = help;

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

62
package-lock.json generated
View File

@ -66,9 +66,9 @@
"dev": true "dev": true
}, },
"@types/node": { "@types/node": {
"version": "10.5.0", "version": "10.5.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.5.0.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.5.1.tgz",
"integrity": "sha512-baXPuqA7EVcBUpA5so2K26DTzk7NCWBc9xrPMu9PbUMwgusJRm9zJBPhiDmJVEcnTQ3aOxUZeuFHpd9qMYDNRg==", "integrity": "sha512-AFLl1IALIuyt6oK4AYZsgWVJ/5rnyzQWud7IebaZWWV3YmgtPZkQmYio9R5Ze/2pdd7XfqF5bP+hWS11mAKoOQ==",
"dev": true "dev": true
}, },
"@types/shelljs": { "@types/shelljs": {
@ -482,7 +482,8 @@
"arrify": { "arrify": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
"integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
"dev": true
}, },
"asn1.js": { "asn1.js": {
"version": "4.10.1", "version": "4.10.1",
@ -586,7 +587,8 @@
"balanced-match": { "balanced-match": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
"dev": true
}, },
"base": { "base": {
"version": "0.11.2", "version": "0.11.2",
@ -682,6 +684,7 @@
"version": "1.1.8", "version": "1.1.8",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
"integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=",
"dev": true,
"requires": { "requires": {
"balanced-match": "^1.0.0", "balanced-match": "^1.0.0",
"concat-map": "0.0.1" "concat-map": "0.0.1"
@ -812,7 +815,8 @@
"buffer-from": { "buffer-from": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz",
"integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==" "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==",
"dev": true
}, },
"buffer-xor": { "buffer-xor": {
"version": "1.0.3", "version": "1.0.3",
@ -1068,7 +1072,8 @@
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true
}, },
"concat-stream": { "concat-stream": {
"version": "1.6.2", "version": "1.6.2",
@ -1287,7 +1292,8 @@
"diff": { "diff": {
"version": "3.5.0", "version": "3.5.0",
"resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
"integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
"dev": true
}, },
"diffie-hellman": { "diffie-hellman": {
"version": "5.0.3", "version": "5.0.3",
@ -1712,7 +1718,8 @@
"fs.realpath": { "fs.realpath": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
}, },
"fsevents": { "fsevents": {
"version": "1.2.4", "version": "1.2.4",
@ -2265,6 +2272,7 @@
"version": "7.1.2", "version": "7.1.2",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
"dev": true,
"requires": { "requires": {
"fs.realpath": "^1.0.0", "fs.realpath": "^1.0.0",
"inflight": "^1.0.4", "inflight": "^1.0.4",
@ -2527,6 +2535,7 @@
"version": "1.0.6", "version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"dev": true,
"requires": { "requires": {
"once": "^1.3.0", "once": "^1.3.0",
"wrappy": "1" "wrappy": "1"
@ -2535,7 +2544,8 @@
"inherits": { "inherits": {
"version": "2.0.3", "version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
"dev": true
}, },
"inquirer": { "inquirer": {
"version": "6.0.0", "version": "6.0.0",
@ -2896,7 +2906,8 @@
"make-error": { "make-error": {
"version": "1.3.4", "version": "1.3.4",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.4.tgz", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.4.tgz",
"integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==" "integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==",
"dev": true
}, },
"mamacro": { "mamacro": {
"version": "0.0.3", "version": "0.0.3",
@ -3007,6 +3018,7 @@
"version": "3.0.4", "version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
"requires": { "requires": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
} }
@ -3014,7 +3026,8 @@
"minimist": { "minimist": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"dev": true
}, },
"mississippi": { "mississippi": {
"version": "2.0.0", "version": "2.0.0",
@ -3059,6 +3072,7 @@
"version": "0.5.1", "version": "0.5.1",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"dev": true,
"requires": { "requires": {
"minimist": "0.0.8" "minimist": "0.0.8"
}, },
@ -3066,7 +3080,8 @@
"minimist": { "minimist": {
"version": "0.0.8", "version": "0.0.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
"dev": true
} }
} }
}, },
@ -3250,6 +3265,7 @@
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
"requires": { "requires": {
"wrappy": "1" "wrappy": "1"
} }
@ -3391,7 +3407,8 @@
"path-is-absolute": { "path-is-absolute": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true
}, },
"path-key": { "path-key": {
"version": "2.0.1", "version": "2.0.1",
@ -3986,6 +4003,7 @@
"version": "0.5.6", "version": "0.5.6",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.6.tgz", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.6.tgz",
"integrity": "sha512-N4KXEz7jcKqPf2b2vZF11lQIz9W5ZMuUcIOGj243lduidkf2fjkVKJS9vNxVWn3u/uxX38AcE8U9nnH9FPcq+g==", "integrity": "sha512-N4KXEz7jcKqPf2b2vZF11lQIz9W5ZMuUcIOGj243lduidkf2fjkVKJS9vNxVWn3u/uxX38AcE8U9nnH9FPcq+g==",
"dev": true,
"requires": { "requires": {
"buffer-from": "^1.0.0", "buffer-from": "^1.0.0",
"source-map": "^0.6.0" "source-map": "^0.6.0"
@ -3994,7 +4012,8 @@
"source-map": { "source-map": {
"version": "0.6.1", "version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true
} }
} }
}, },
@ -4253,6 +4272,7 @@
"version": "7.0.0", "version": "7.0.0",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.0.tgz", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.0.tgz",
"integrity": "sha512-klJsfswHP0FuOLsvBZ/zzCfUvakOSSxds78mVeK7I+qP76YWtxf16hEZsp3U+b0kIo82R5UatGFeblYMqabb2Q==", "integrity": "sha512-klJsfswHP0FuOLsvBZ/zzCfUvakOSSxds78mVeK7I+qP76YWtxf16hEZsp3U+b0kIo82R5UatGFeblYMqabb2Q==",
"dev": true,
"requires": { "requires": {
"arrify": "^1.0.0", "arrify": "^1.0.0",
"buffer-from": "^1.1.0", "buffer-from": "^1.1.0",
@ -4600,9 +4620,9 @@
} }
}, },
"webpack": { "webpack": {
"version": "4.13.0", "version": "4.14.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-4.13.0.tgz", "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.14.0.tgz",
"integrity": "sha512-3KMX0uPjJ4cXjl9V/AY+goRQPs7jtKRQn3hhNOG6s8Sx3mmGCQUjQJvjVoGNABVo5svgujIcSLBN8g62EzqIMA==", "integrity": "sha512-CgZPUwobJbQlZqpylDNtEazZLfNnGuyFmpk1dHIP2kFchtyMWB+W2wBKPImSnSQ2rbX/WZMKiQax+SZmlUXuQQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"@webassemblyjs/ast": "1.5.12", "@webassemblyjs/ast": "1.5.12",
@ -4754,7 +4774,8 @@
"wrappy": { "wrappy": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
}, },
"xtend": { "xtend": {
"version": "4.0.1", "version": "4.0.1",
@ -4814,7 +4835,8 @@
"yn": { "yn": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz",
"integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=" "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=",
"dev": true
} }
} }
} }

View File

@ -13,21 +13,20 @@
"dependencies": { "dependencies": {
"@protobufjs/utf8": "^1.1.0", "@protobufjs/utf8": "^1.1.0",
"binaryen": "48.0.0-nightly.20180627", "binaryen": "48.0.0-nightly.20180627",
"glob": "^7.1.2", "long": "^4.0.0"
"long": "^4.0.0",
"minimist": "^1.2.0",
"ts-node": "^7.0.0"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^10.5.0", "@types/node": "^10.5.1",
"browser-process-hrtime": "^0.1.2", "browser-process-hrtime": "^0.1.2",
"diff": "^3.5.0", "diff": "^3.5.0",
"glob": "^7.1.2",
"ts-loader": "^4.4.2", "ts-loader": "^4.4.2",
"ts-node": "^7.0.0",
"tslint": "^5.10.0", "tslint": "^5.10.0",
"typedoc": "^0.11.1", "typedoc": "^0.11.1",
"typedoc-plugin-external-module-name": "^1.1.1", "typedoc-plugin-external-module-name": "^1.1.1",
"typescript": "^2.9.2", "typescript": "^2.9.2",
"webpack": "^4.13.0", "webpack": "^4.14.0",
"webpack-cli": "^3.0.8" "webpack-cli": "^3.0.8"
}, },
"main": "index.js", "main": "index.js",

View File

@ -76,12 +76,10 @@ import {
ParameterNode, ParameterNode,
ParameterKind, ParameterKind,
ExportMember, ExportMember,
SwitchCase, SwitchCase
DeclarationStatement
} from "../ast"; } from "../ast";
import { import {
Token,
operatorTokenToString operatorTokenToString
} from "../tokenizer"; } from "../tokenizer";

View File

@ -1,4 +1,6 @@
/** @module glue/js *//***/ /** @module glue/js *//***/
/// <reference path="../binaryen.d.ts" />
declare function allocate_memory(size: usize): usize; declare function allocate_memory(size: usize): usize;
declare function free_memory(ptr: usize): void; declare function free_memory(ptr: usize): void;

View File

@ -4,10 +4,12 @@
* @preferred * @preferred
*//***/ *//***/
/// <reference path="../../../std/portable.d.ts" /> /// <reference path="./binaryen.d.ts" />
/// <reference path="../binaryen.d.ts" /> /// <reference path="./float.d.ts" />
/// <reference path="./i64.d.ts" />
/// <reference path="./node.d.ts" />
import "../../../std/portable"; import "../../../std/portable/index";
import "./binaryen"; import "./binaryen";
import "./i64";
import "./float"; import "./float";
import "./i64";

View File

@ -4,5 +4,6 @@
* @preferred * @preferred
*//***/ *//***/
import "../binaryen.d";
import "./i64"; import "./i64";
import "./float"; import "./float";

View File

@ -9,7 +9,6 @@
], ],
"exclude": [ "exclude": [
"./binary.ts", "./binary.ts",
"./extra/**",
"./glue/wasm/**" "./glue/wasm/**"
] ]
} }

View File

@ -1,3 +1,3 @@
Standard library components for use with `tsc` (portable) and `asc` (assembly). Standard library components for use with `tsc` (portable) and `asc` (assembly).
Definition files (.d.ts) and base configurations (.json) are relevant to `tsc` only and not used by `asc`. Base configurations (.json) and definition files (.d.ts) are relevant to `tsc` only and not used by `asc`.

View File

@ -4,13 +4,8 @@
"target": "esnext", "target": "esnext",
"module": "commonjs", "module": "commonjs",
"noLib": true, "noLib": true,
"types": [], "allowJs": false,
"rootDirs": [ "typeRoots": [ "." ],
"./assembly" "types": [ "assembly/" ]
], }
"allowJs": false
},
"files": [
"./assembly.d.ts"
]
} }

View File

@ -3,17 +3,11 @@
"compilerOptions": { "compilerOptions": {
"target": "es5", "target": "es5",
"module": "commonjs", "module": "commonjs",
"noLib": true,
"allowJs": true,
"downlevelIteration": true, "downlevelIteration": true,
"preserveConstEnums": true, "preserveConstEnums": true,
"noLib": true, "typeRoots": [ "." ],
"types": [], "types": [ "portable/" ]
"rootDirs": [ }
"./portable"
],
"allowJs": true
},
"files": [
"./portable.d.ts",
"./portable.js"
]
} }

View File

@ -216,5 +216,6 @@ globalScope["fmodf"] = function fmodf(x, y) {
return Math.fround(x % y); return Math.fround(x % y);
}; };
require("./portable/math")(globalScope); globalScope["JSMath"] = Math;
require("./portable/memory")(globalScope);
require("./memory")(globalScope);

View File

@ -1,3 +0,0 @@
module.exports = globalScope => {
globalScope["JSMath"] = Math;
};

View File

@ -49,7 +49,11 @@ To (re-)create all fixtures:
$>npm run test:parser -- --create $>npm run test:parser -- --create
``` ```
Note that the parser suite currently can't recreate just a specific fixture. To (re-)create a specific fixture only:
```
$> npm run test:parser -- testNameWithoutTs --create
```
Compiler Compiler
-------- --------

View File

@ -1,5 +1,8 @@
const asc = require("../dist/asc.js"); const asc = require("../dist/asc.js");
if (typeof asc.definitionFiles.assembly !== "string") throw Error("missing bundled assembly.d.ts");
if (typeof asc.definitionFiles.portable !== "string") throw Error("missing bundled portable.d.ts");
const stdout = asc.createMemoryStream(); const stdout = asc.createMemoryStream();
const stderr = asc.createMemoryStream(); const stderr = asc.createMemoryStream();
const files = { "module.ts": `import "allocator/arena";` }; const files = { "module.ts": `import "allocator/arena";` };
@ -70,7 +73,7 @@ process.stdout.write(stderr.toString());
console.log("\n# asc.compileString"); console.log("\n# asc.compileString");
const output = asc.compileString(`import "allocator/arena";`, { optimize: 2 }); const output = asc.compileString(`import "allocator/arena";`, { optimizeLevel: 2 });
console.log(">>> .stdout >>>"); console.log(">>> .stdout >>>");
process.stdout.write(output.stdout.toString()); process.stdout.write(output.stdout.toString());
console.log(">>> .stderr >>>"); console.log(">>> .stderr >>>");

View File

@ -1,24 +1,37 @@
const fs = require("fs"); const fs = require("fs");
const path = require("path"); const path = require("path");
const os = require("os"); const os = require("os");
const colors = require("../cli/util/colors");
const glob = require("glob"); const glob = require("glob");
const minimist = require("minimist"); const colorsUtil = require("../cli/util/colors");
const optionsUtil = require("../cli/util/options");
const diff = require("./util/diff"); const diff = require("./util/diff");
const asc = require("../cli/asc.js"); const asc = require("../cli/asc.js");
const args = minimist(process.argv.slice(2), { const config = {
boolean: [ "create", "help" ], "create": {
alias: { h: "help" } "description": [
}); "Recreates the fixture for the specified test(s)",
"or all the fixtures if no specific test is given."
],
"type": "b"
},
"help": {
"description": "Prints this message and exits.",
"type": "b",
"alias": "h"
}
};
const opts = optionsUtil.parse(process.argv.slice(2),config);
const args = opts.options;
const argv = opts.arguments;
if (args.help) { if (args.help) {
console.log([ console.log([
"Usage: npm run test:compiler -- [test1, test2 ...] [--create]", colorsUtil.white("SYNTAX"),
" " + colorsUtil.cyan("npm run test:compiler --") + " [test1, test2 ...] [options]",
"", "",
"Runs all tests if no tests have been specified.", colorsUtil.white("OPTIONS"),
"Recreates affected fixtures if --create is specified." optionsUtil.help(config)
].join(os.EOL) + os.EOL); ].join(os.EOL) + os.EOL);
process.exit(0); process.exit(0);
} }
@ -29,13 +42,13 @@ var failedTests = [];
const basedir = path.join(__dirname, "compiler"); const basedir = path.join(__dirname, "compiler");
// Get a list of all tests // Get a list of all tests
var tests = glob.sync("**/!(_)*.ts", { cwd: basedir }); var tests = glob.sync("**/!(_*).ts", { cwd: basedir });
// Run specific tests only if arguments are provided // Run specific tests only if arguments are provided
if (args._.length) { if (argv.length) {
tests = tests.filter(filename => args._.indexOf(filename.replace(/\.ts$/, "")) >= 0); tests = tests.filter(filename => argv.indexOf(filename.replace(/\.ts$/, "")) >= 0);
if (!tests.length) { if (!tests.length) {
console.error("No matching tests: " + args._.join(" ")); console.error("No matching tests: " + argv.join(" "));
process.exit(1); process.exit(1);
} }
} }
@ -54,7 +67,7 @@ function getExpectedErrors(filePath) {
// TODO: asc's callback is synchronous here. This might change. // TODO: asc's callback is synchronous here. This might change.
tests.forEach(filename => { tests.forEach(filename => {
console.log(colors.white("Testing compiler/" + filename) + "\n"); console.log(colorsUtil.white("Testing compiler/" + filename) + "\n");
const expectedErrors = getExpectedErrors(path.join(basedir, filename)); const expectedErrors = getExpectedErrors(path.join(basedir, filename));
const basename = filename.replace(/\.ts$/, ""); const basename = filename.replace(/\.ts$/, "");
@ -85,13 +98,13 @@ tests.forEach(filename => {
for (const expectedError of expectedErrors) { for (const expectedError of expectedErrors) {
if (!stderrString.includes(expectedError)) { if (!stderrString.includes(expectedError)) {
console.log(`Expected error "${expectedError}" was not in the error output.`); console.log(`Expected error "${expectedError}" was not in the error output.`);
console.log("- " + colors.red("error check ERROR")); console.log("- " + colorsUtil.red("error check ERROR"));
failedTests.push(basename); failedTests.push(basename);
console.log(); console.log();
return; return;
} }
} }
console.log("- " + colors.green("error check OK")); console.log("- " + colorsUtil.green("error check OK"));
++successes; ++successes;
console.log(); console.log();
return; return;
@ -102,16 +115,16 @@ tests.forEach(filename => {
var actual = stdout.toString().replace(/\r\n/g, "\n"); var actual = stdout.toString().replace(/\r\n/g, "\n");
if (args.create) { if (args.create) {
fs.writeFileSync(path.join(basedir, basename + ".untouched.wat"), actual, { encoding: "utf8" }); fs.writeFileSync(path.join(basedir, basename + ".untouched.wat"), actual, { encoding: "utf8" });
console.log("- " + colors.yellow("Created fixture")); console.log("- " + colorsUtil.yellow("Created fixture"));
} else { } else {
let expected = fs.readFileSync(path.join(basedir, basename + ".untouched.wat"), { encoding: "utf8" }).replace(/\r\n/g, "\n"); let expected = fs.readFileSync(path.join(basedir, basename + ".untouched.wat"), { encoding: "utf8" }).replace(/\r\n/g, "\n");
let diffs = diff(basename + ".untouched.wat", expected, actual); let diffs = diff(basename + ".untouched.wat", expected, actual);
if (diffs !== null) { if (diffs !== null) {
console.log(diffs); console.log(diffs);
console.log("- " + colors.red("diff ERROR")); console.log("- " + colorsUtil.red("diff ERROR"));
failed = true; failed = true;
} else } else
console.log("- " + colors.green("diff OK")); console.log("- " + colorsUtil.green("diff OK"));
} }
console.log(); console.log();
@ -178,9 +191,9 @@ tests.forEach(filename => {
}, },
}); });
}); });
console.log("- " + colors.green("instantiate OK") + " (" + asc.formatTime(runTime) + ")"); console.log("- " + colorsUtil.green("instantiate OK") + " (" + asc.formatTime(runTime) + ")");
} catch (e) { } catch (e) {
console.log("- " + colors.red("instantiate ERROR: ") + e.stack); console.log("- " + colorsUtil.red("instantiate ERROR: ") + e.stack);
failed = true; failed = true;
} }
@ -193,6 +206,6 @@ tests.forEach(filename => {
if (failedTests.length) { if (failedTests.length) {
process.exitCode = 1; process.exitCode = 1;
console.log(colors.red("ERROR: ") + failedTests.length + " compiler tests failed: " + failedTests.join(", ")); console.log(colorsUtil.red("ERROR: ") + failedTests.length + " compiler tests failed: " + failedTests.join(", "));
} else } else
console.log("[ " + colors.white("SUCCESS") + " ]"); console.log("[ " + colorsUtil.white("SUCCESS") + " ]");

View File

@ -1,6 +1,6 @@
var binaryen = global.Binaryen = require("../lib/binaryen"); var binaryen = global.Binaryen = require("../lib/binaryen");
require("ts-node").register({ project: require("path").join(__dirname, "..", "src") }); require("ts-node").register({ project: require("path").join(__dirname, "..", "src", "tsconfig.json") });
require("../src/glue/js"); require("../src/glue/js");
var mod = new binaryen.Module(); var mod = new binaryen.Module();

View File

@ -1,51 +1,91 @@
var fs = require("fs"); const fs = require("fs");
var path = require("path"); const path = require("path");
var colors = require("../cli/util/colors"); const os = require("os");
var glob = require("glob"); const glob = require("glob");
var diff = require("./util/diff"); const colorsUtil = require("../cli/util/colors");
const optionsUtil = require("../cli/util/options");
const diff = require("./util/diff");
const config = {
"create": {
"description": [
"Recreates the fixture for the specified test(s)",
"or all the fixtures if no specific test is given."
],
"type": "b"
},
"help": {
"description": "Prints this message and exits.",
"type": "b",
"alias": "h"
}
};
const opts = optionsUtil.parse(process.argv.slice(2), config);
const args = opts.options;
const argv = opts.arguments;
if (args.help) {
console.log([
colorsUtil.white("SYNTAX"),
" " + colorsUtil.cyan("npm run test:parser --") + " [test1, test2 ...] [options]",
"",
colorsUtil.white("OPTIONS"),
optionsUtil.help(config)
].join(os.EOL) + os.EOL);
process.exit(0);
}
const basedir = path.join(__dirname, "parser");
// Get a list of all tests
var tests = glob.sync("**/!(_*).ts", { cwd: basedir });
// Run specific tests only if arguments are provided
if (argv.length) {
tests = tests.filter(filename => argv.indexOf(filename.replace(/\.ts$/, "")) >= 0);
if (!tests.length) {
console.error("No matching tests: " + argv.join(" "));
process.exit(1);
}
}
require("ts-node").register({ require("ts-node").register({
project: require("path").join(__dirname, "..", "src", "tsconfig.json"), project: path.join(__dirname, "..", "src", "tsconfig.json"),
files: [ // see: https://github.com/TypeStrong/ts-node/issues/620 cache: false // FIXME: for some reason, if both asc and the parser tests use caching, the one
path.join(__dirname, "..", "std", "portable.d.ts"), // invoked later cannot find some definition files.
path.join(__dirname, "..", "src", "glue", "binaryen.d.ts")
]
}); });
require("../src/glue/js"); require("../src/glue/js");
var Parser = require("../src/parser").Parser; var Parser = require("../src/parser").Parser;
var ASTBuilder = require("../src/extra/ast").ASTBuilder; var ASTBuilder = require("../src/extra/ast").ASTBuilder;
var isCreate = process.argv[2] === "--create";
var filter = process.argv.length > 2 && !isCreate ? "*" + process.argv[2] + "*.ts" : "**.ts";
var failures = 0; var failures = 0;
glob.sync(filter, { cwd: __dirname + "/parser" }).forEach(filename => { tests.forEach(filename => {
if (filename.charAt(0) == "_" || filename.endsWith(".fixture.ts")) if (filename.charAt(0) == "_" || filename.endsWith(".fixture.ts")) return;
return;
console.log(colors.white("Testing parser/" + filename)); console.log(colorsUtil.white("Testing parser/" + filename));
var failed = false; var failed = false;
var parser = new Parser(); var parser = new Parser();
var sourceText = fs.readFileSync(__dirname + "/parser/" + filename, { encoding: "utf8" }).replace(/\r?\n/g, "\n"); var sourceText = fs.readFileSync(basedir + "/" + filename, { encoding: "utf8" }).replace(/\r?\n/g, "\n");
parser.parseFile(sourceText, filename, true); parser.parseFile(sourceText, filename, true);
var serializedSourceText = ASTBuilder.build(parser.program.sources[0]); var serializedSourceText = ASTBuilder.build(parser.program.sources[0]);
var actual = serializedSourceText + parser.diagnostics.map(diagnostic => "// " + diagnostic +"\n").join(""); var actual = serializedSourceText + parser.diagnostics.map(diagnostic => "// " + diagnostic +"\n").join("");
var fixture = filename + ".fixture.ts"; var fixture = filename + ".fixture.ts";
if (isCreate) { if (args.create) {
fs.writeFileSync(__dirname + "/parser/" + fixture, actual, { encoding: "utf8" }); fs.writeFileSync(basedir + "/" + fixture, actual, { encoding: "utf8" });
console.log("Created\n"); console.log("Created\n");
} else { } else {
var expected = fs.readFileSync(__dirname + "/parser/" + fixture, { encoding: "utf8" }).replace(/\r\n/g, "\n"); var expected = fs.readFileSync(basedir + "/" + fixture, { encoding: "utf8" }).replace(/\r\n/g, "\n");
var diffs = diff("parser/" + fixture, expected, actual); var diffs = diff("parser/" + fixture, expected, actual);
if (diffs !== null) { if (diffs !== null) {
failed = true; failed = true;
console.log(diffs); console.log(diffs);
console.log(colors.red("diff ERROR")); console.log(colorsUtil.red("diff ERROR"));
} else { } else {
console.log(colors.green("diff OK")); console.log(colorsUtil.green("diff OK"));
} }
} }
@ -56,6 +96,6 @@ glob.sync(filter, { cwd: __dirname + "/parser" }).forEach(filename => {
if (failures) { if (failures) {
process.exitCode = 1; process.exitCode = 1;
console.log(colors.red("ERROR: ") + failures + " parser tests failed"); console.log(colorsUtil.red("ERROR: ") + failures + " parser tests failed");
} else } else
console.log("[ " + colors.white("SUCCESS") + " ]"); console.log("[ " + colorsUtil.white("SUCCESS") + " ]");

View File

@ -62,18 +62,18 @@ const bin = {
BUNDLE_VERSION: JSON.stringify(require("./package.json").version), BUNDLE_VERSION: JSON.stringify(require("./package.json").version),
BUNDLE_LIBRARY: (() => { BUNDLE_LIBRARY: (() => {
const libDir = path.join(__dirname, "std", "assembly"); const libDir = path.join(__dirname, "std", "assembly");
const libFiles = require("glob").sync("**/*.ts", { cwd: libDir }); const libFiles = require("glob").sync("**/!(*.d).ts", { cwd: libDir });
const lib = {}; const lib = {};
libFiles.forEach(file => lib[file.replace(/\.ts$/, "")] = bundleFile(path.join(libDir, file))); libFiles.forEach(file => lib[file.replace(/\.ts$/, "")] = bundleFile(path.join(libDir, file)));
return lib; return lib;
})(), })(),
BUNDLE_DEFINITIONS: { BUNDLE_DEFINITIONS: {
"assembly": bundleFile(path.join(__dirname, "std", "assembly.d.ts")), "assembly": bundleFile(path.join(__dirname, "std", "assembly", "index.d.ts")),
"portable": bundleFile(path.join(__dirname, "std", "portable.d.ts")) "portable": bundleFile(path.join(__dirname, "std", "portable", "index.d.ts"))
}, },
__dirname: JSON.stringify(".") __dirname: JSON.stringify(".")
}), }),
new webpack.IgnorePlugin(/\.\/src|package\.json|^(ts\-node|glob|source\-map\-support)$/) new webpack.IgnorePlugin(/\.\/src|package\.json|^(ts\-node|glob)$/)
] ]
}; };