mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-06-17 17:01:37 +00:00
Restructure types; Add a use-case specific options parser; Allow (re)creation of specific parser fixtures
This commit is contained in:
196
cli/asc.js
196
cli/asc.js
@ -11,34 +11,30 @@
|
||||
* @module cli/asc
|
||||
*/
|
||||
|
||||
// Use "." instead of "/" as cwd in browsers
|
||||
if (process.browser) process.cwd = function() { return "."; };
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
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";
|
||||
|
||||
// Use distribution files if present, otherwise run the sources directly
|
||||
var assemblyscript, isDev;
|
||||
var assemblyscript, isDev = false;
|
||||
(() => {
|
||||
try {
|
||||
assemblyscript = require("../dist/assemblyscript.js");
|
||||
isDev = false;
|
||||
} catch (e) {
|
||||
try {
|
||||
require("ts-node").register({
|
||||
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("ts-node").register({ project: path.join(__dirname, "..", "src", "tsconfig.json") });
|
||||
require("../src/glue/js");
|
||||
assemblyscript = require("../src");
|
||||
isDev = true;
|
||||
} catch (e) {
|
||||
// last resort: same directory CommonJS
|
||||
assemblyscript = eval("require('./assemblyscript')");
|
||||
isDev = false;
|
||||
}
|
||||
}
|
||||
})();
|
||||
@ -70,7 +66,7 @@ exports.defaultShrinkLevel = 1;
|
||||
/** Bundled library files. */
|
||||
exports.libraryFiles = exports.isBundle ? BUNDLE_LIBRARY : (() => { // set up if not a bundle
|
||||
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 = {};
|
||||
libFiles.forEach(file => bundled[file.replace(/\.ts$/, "")] = fs.readFileSync(path.join(libDir, file), "utf8" ));
|
||||
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
|
||||
const stdDir = path.join(__dirname, "..", "std");
|
||||
return {
|
||||
"assembly": fs.readFileSync(path.join(stdDir, "assembly.d.ts"), "utf8"),
|
||||
"portable": fs.readFileSync(path.join(stdDir, "portable.d.ts"), "utf8")
|
||||
"assembly": fs.readFileSync(path.join(stdDir, "assembly", "index.d.ts"), "utf8"),
|
||||
"portable": fs.readFileSync(path.join(stdDir, "portable", "index.d.ts"), "utf8")
|
||||
};
|
||||
})();
|
||||
|
||||
@ -94,12 +90,16 @@ exports.compileString = (sources, options) => {
|
||||
binary: null,
|
||||
text: null
|
||||
});
|
||||
exports.main([
|
||||
var argv = [
|
||||
"--binaryFile", "binary",
|
||||
"--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,
|
||||
stderr: output.stderr,
|
||||
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 (!stderr) throw Error("'options.stderr' must be specified");
|
||||
|
||||
const args = parseArguments(argv);
|
||||
const indent = 24;
|
||||
|
||||
const opts = optionsUtil.parse(argv, exports.options);
|
||||
const args = opts.options;
|
||||
argv = opts.arguments;
|
||||
if (args.noColors) {
|
||||
colors.stdout.supported =
|
||||
colors.stderr.supported = false;
|
||||
colorsUtil.stdout.supported =
|
||||
colorsUtil.stderr.supported = false;
|
||||
} else {
|
||||
colors.stdout = colors.from(stdout);
|
||||
colors.stderr = colors.from(stderr);
|
||||
colorsUtil.stdout = colorsUtil.from(stdout);
|
||||
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
|
||||
if (!callback) callback = function defaultCallback(err) {
|
||||
var code = 0;
|
||||
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;
|
||||
}
|
||||
return code;
|
||||
@ -156,43 +168,22 @@ exports.main = function main(argv, options, callback) {
|
||||
return callback(null);
|
||||
}
|
||||
// Print the help message if requested or no source files are provided
|
||||
if (args.help || args._.length < 1) {
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
||||
if (args.help || !argv.length) {
|
||||
var out = args.help ? stdout : stderr;
|
||||
var color = args.help ? colors.stdout : colors.stderr;
|
||||
var color = args.help ? colorsUtil.stdout : colorsUtil.stderr;
|
||||
out.write([
|
||||
color.white("Syntax"),
|
||||
color.white("SYNTAX"),
|
||||
" " + color.cyan("asc") + " [entryFile ...] [options]",
|
||||
"",
|
||||
color.white("Examples"),
|
||||
color.white("EXAMPLES"),
|
||||
" " + color.cyan("asc") + " hello.ts",
|
||||
" " + color.cyan("asc") + " hello.ts -b hello.wasm -t hello.wat",
|
||||
" " + color.cyan("asc") + " hello1.ts hello2.ts -b -O > hello.wasm",
|
||||
"",
|
||||
color.white("Options"),
|
||||
].concat(opts).join(EOL) + EOL);
|
||||
color.white("OPTIONS"),
|
||||
].concat(
|
||||
optionsUtil.help(exports.options, 24, EOL)
|
||||
).join(EOL) + EOL);
|
||||
return callback(null);
|
||||
}
|
||||
|
||||
@ -209,7 +200,6 @@ exports.main = function main(argv, options, callback) {
|
||||
// Set up transforms
|
||||
const transforms = [];
|
||||
if (args.transform) {
|
||||
if (typeof args.transform === "string") args.transform = args.transform.split(",");
|
||||
args.transform.forEach(transform =>
|
||||
transforms.push(
|
||||
require(
|
||||
@ -246,8 +236,9 @@ exports.main = function main(argv, options, callback) {
|
||||
}
|
||||
const customLibDirs = [];
|
||||
if (args.lib) {
|
||||
if (typeof args.lib === "string") args.lib = args.lib.split(",");
|
||||
Array.prototype.push.apply(customLibDirs, args.lib.map(lib => lib.trim()));
|
||||
let lib = args.lib;
|
||||
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
|
||||
let libDir = customLibDirs[i];
|
||||
let libFiles;
|
||||
@ -275,10 +266,10 @@ exports.main = function main(argv, options, callback) {
|
||||
}
|
||||
|
||||
// Include entry files
|
||||
for (let i = 0, k = args._.length; i < k; ++i) {
|
||||
const filename = args._[i];
|
||||
for (let i = 0, k = argv.length; i < k; ++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
|
||||
let sourceText = readFile(path.join(baseDir, sourcePath) + ".ts");
|
||||
@ -385,51 +376,28 @@ exports.main = function main(argv, options, callback) {
|
||||
const program = assemblyscript.finishParsing(parser);
|
||||
|
||||
// Set up optimization levels
|
||||
var optimizeLevel = -1;
|
||||
var optimizeLevel = 0;
|
||||
var shrinkLevel = 0;
|
||||
var debugInfo = !args.noDebug;
|
||||
if (args.optimize !== false) {
|
||||
if (typeof args.optimize === "number") {
|
||||
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 (args.optimize) {
|
||||
optimizeLevel = exports.defaultOptimizeLevel;
|
||||
shrinkLevel = exports.defaultShrinkLevel;
|
||||
}
|
||||
if (typeof args.optimizeLevel === "number") {
|
||||
optimizeLevel = args.optimizeLevel;
|
||||
}
|
||||
if (typeof args.shrinkLevel === "number") {
|
||||
shrinkLevel = args.shrinkLevel;
|
||||
} else if (args.shrinkLevel === "s") {
|
||||
shrinkLevel = 1;
|
||||
} else if (args.shrinkLevel === "z") {
|
||||
shrinkLevel = 2;
|
||||
}
|
||||
optimizeLevel = Math.max(optimizeLevel, 0);
|
||||
shrinkLevel = Math.max(shrinkLevel, 0);
|
||||
optimizeLevel = Math.min(Math.max(optimizeLevel, 0), 3);
|
||||
shrinkLevel = Math.min(Math.max(shrinkLevel, 0), 2);
|
||||
|
||||
// Begin compilation
|
||||
const compilerOptions = assemblyscript.createOptions();
|
||||
assemblyscript.setTarget(compilerOptions, 0);
|
||||
assemblyscript.setNoTreeShaking(compilerOptions, !!args.noTreeShaking);
|
||||
assemblyscript.setNoAssert(compilerOptions, !!args.noAssert);
|
||||
assemblyscript.setImportMemory(compilerOptions, !!args.importMemory);
|
||||
assemblyscript.setImportTable(compilerOptions, !!args.importTable);
|
||||
assemblyscript.setNoTreeShaking(compilerOptions, args.noTreeShaking);
|
||||
assemblyscript.setNoAssert(compilerOptions, args.noAssert);
|
||||
assemblyscript.setImportMemory(compilerOptions, args.importMemory);
|
||||
assemblyscript.setImportTable(compilerOptions, args.importTable);
|
||||
assemblyscript.setMemoryBase(compilerOptions, args.memoryBase >>> 0);
|
||||
assemblyscript.setSourceMap(compilerOptions, args.sourceMap != null);
|
||||
assemblyscript.setOptimizeLevelHints(compilerOptions, optimizeLevel, shrinkLevel);
|
||||
@ -515,7 +483,7 @@ exports.main = function main(argv, options, callback) {
|
||||
|
||||
module.setOptimizeLevel(optimizeLevel);
|
||||
module.setShrinkLevel(shrinkLevel);
|
||||
module.setDebugInfo(debugInfo);
|
||||
module.setDebugInfo(!args.noDebug);
|
||||
|
||||
var runPasses = [];
|
||||
if (args.runPasses) {
|
||||
@ -741,7 +709,7 @@ exports.main = function main(argv, options, callback) {
|
||||
var files;
|
||||
try {
|
||||
stats.readTime += measure(() => {
|
||||
files = require("glob").sync("*.ts", { cwd: dirname });
|
||||
files = require("glob").sync("!(*.d).ts", { cwd: dirname });
|
||||
});
|
||||
return files;
|
||||
} catch (e) {
|
||||
@ -764,25 +732,23 @@ exports.main = function main(argv, options, callback) {
|
||||
}
|
||||
}
|
||||
|
||||
/** Parses the specified command line arguments. */
|
||||
function parseArguments(argv) {
|
||||
const opts = {};
|
||||
Object.keys(exports.options).forEach(key => {
|
||||
const opt = exports.options[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);
|
||||
}
|
||||
});
|
||||
return require("minimist")(argv, opts);
|
||||
}
|
||||
var argumentSubstitutions = {
|
||||
"-O" : [ "--optimize" ],
|
||||
"-Os" : [ "--optimize", "--shrinkLevel", "1" ],
|
||||
"-Oz" : [ "--optimize", "--shrinkLevel", "2" ],
|
||||
"-O0" : [ "--optimizeLevel", "0", "--shrinkLevel", "0" ],
|
||||
"-O0s": [ "--optimizeLevel", "0", "--shrinkLevel", "1" ],
|
||||
"-O0z": [ "--optimizeLevel", "0", "--shrinkLevel", "2" ],
|
||||
"-O1" : [ "--optimizeLevel", "1", "--shrinkLevel", "0" ],
|
||||
"-O1s": [ "--optimizeLevel", "1", "--shrinkLevel", "1" ],
|
||||
"-O1z": [ "--optimizeLevel", "1", "--shrinkLevel", "2" ],
|
||||
"-O2" : [ "--optimizeLevel", "2", "--shrinkLevel", "0" ],
|
||||
"-O2s": [ "--optimizeLevel", "2", "--shrinkLevel", "1" ],
|
||||
"-O2z": [ "--optimizeLevel", "2", "--shrinkLevel", "2" ],
|
||||
"-O3" : [ "--optimizeLevel", "3", "--shrinkLevel", "0" ],
|
||||
"-O3s": [ "--optimizeLevel", "3", "--shrinkLevel", "1" ],
|
||||
"-O3z": [ "--optimizeLevel", "3", "--shrinkLevel", "2" ],
|
||||
};
|
||||
|
||||
/** Checks diagnostics emitted so far for errors. */
|
||||
function checkDiagnostics(emitter, stderr) {
|
||||
|
Reference in New Issue
Block a user