Skip to content

Commit 5ca5df3

Browse files
committed
Restructure types; Add a use-case specific options parser; Allow (re)creation of specific parser fixtures
1 parent 82da2d1 commit 5ca5df3

29 files changed

+486
-279
lines changed

cli/asc.js

+81-115
Original file line numberDiff line numberDiff line change
@@ -11,34 +11,30 @@
1111
* @module cli/asc
1212
*/
1313

14+
// Use "." instead of "/" as cwd in browsers
15+
if (process.browser) process.cwd = function() { return "."; };
16+
1417
const fs = require("fs");
1518
const path = require("path");
1619
const utf8 = require("@protobufjs/utf8");
17-
const colors = require("./util/colors");
20+
const colorsUtil = require("./util/colors");
21+
const optionsUtil = require("./util/options");
1822
const EOL = process.platform === "win32" ? "\r\n" : "\n";
1923

2024
// Use distribution files if present, otherwise run the sources directly
21-
var assemblyscript, isDev;
25+
var assemblyscript, isDev = false;
2226
(() => {
2327
try {
2428
assemblyscript = require("../dist/assemblyscript.js");
25-
isDev = false;
2629
} catch (e) {
2730
try {
28-
require("ts-node").register({
29-
project: path.join(__dirname, "..", "src", "tsconfig.json"),
30-
files: [ // see: https://github.com/TypeStrong/ts-node/issues/620
31-
path.join(__dirname, "..", "std", "portable.d.ts"),
32-
path.join(__dirname, "..", "src", "glue", "binaryen.d.ts")
33-
]
34-
});
31+
require("ts-node").register({ project: path.join(__dirname, "..", "src", "tsconfig.json") });
3532
require("../src/glue/js");
3633
assemblyscript = require("../src");
3734
isDev = true;
3835
} catch (e) {
3936
// last resort: same directory CommonJS
4037
assemblyscript = eval("require('./assemblyscript')");
41-
isDev = false;
4238
}
4339
}
4440
})();
@@ -70,7 +66,7 @@ exports.defaultShrinkLevel = 1;
7066
/** Bundled library files. */
7167
exports.libraryFiles = exports.isBundle ? BUNDLE_LIBRARY : (() => { // set up if not a bundle
7268
const libDir = path.join(__dirname, "..", "std", "assembly");
73-
const libFiles = require("glob").sync("**/*.ts", { cwd: libDir });
69+
const libFiles = require("glob").sync("**/!(*.d).ts", { cwd: libDir });
7470
const bundled = {};
7571
libFiles.forEach(file => bundled[file.replace(/\.ts$/, "")] = fs.readFileSync(path.join(libDir, file), "utf8" ));
7672
return bundled;
@@ -80,8 +76,8 @@ exports.libraryFiles = exports.isBundle ? BUNDLE_LIBRARY : (() => { // set up if
8076
exports.definitionFiles = exports.isBundle ? BUNDLE_DEFINITIONS : (() => { // set up if not a bundle
8177
const stdDir = path.join(__dirname, "..", "std");
8278
return {
83-
"assembly": fs.readFileSync(path.join(stdDir, "assembly.d.ts"), "utf8"),
84-
"portable": fs.readFileSync(path.join(stdDir, "portable.d.ts"), "utf8")
79+
"assembly": fs.readFileSync(path.join(stdDir, "assembly", "index.d.ts"), "utf8"),
80+
"portable": fs.readFileSync(path.join(stdDir, "portable", "index.d.ts"), "utf8")
8581
};
8682
})();
8783

@@ -94,12 +90,16 @@ exports.compileString = (sources, options) => {
9490
binary: null,
9591
text: null
9692
});
97-
exports.main([
93+
var argv = [
9894
"--binaryFile", "binary",
9995
"--textFile", "text",
100-
...Object.keys(options || {}).map(arg => `--${arg}=${options[arg]}`),
101-
...Object.keys(sources),
102-
], {
96+
];
97+
Object.keys(options || {}).forEach(key => {
98+
var val = options[key];
99+
if (Array.isArray(val)) val.forEach(val => argv.push("--" + key, String(val)));
100+
else argv.push("--" + key, String(val));
101+
});
102+
exports.main(argv.concat(Object.keys(sources)), {
103103
stdout: output.stdout,
104104
stderr: output.stderr,
105105
readFile: name => sources.hasOwnProperty(name) ? sources[name] : null,
@@ -129,22 +129,34 @@ exports.main = function main(argv, options, callback) {
129129
if (!stdout) throw Error("'options.stdout' must be specified");
130130
if (!stderr) throw Error("'options.stderr' must be specified");
131131

132-
const args = parseArguments(argv);
133-
const indent = 24;
134-
132+
const opts = optionsUtil.parse(argv, exports.options);
133+
const args = opts.options;
134+
argv = opts.arguments;
135135
if (args.noColors) {
136-
colors.stdout.supported =
137-
colors.stderr.supported = false;
136+
colorsUtil.stdout.supported =
137+
colorsUtil.stderr.supported = false;
138138
} else {
139-
colors.stdout = colors.from(stdout);
140-
colors.stderr = colors.from(stderr);
139+
colorsUtil.stdout = colorsUtil.from(stdout);
140+
colorsUtil.stderr = colorsUtil.from(stderr);
141+
}
142+
143+
// Check for unknown arguments
144+
if (opts.unknown.length) {
145+
opts.unknown.forEach(arg => {
146+
stderr.write(colorsUtil.stderr.yellow("WARN: ") + "Unknown option '" + arg + "'" + EOL);
147+
});
148+
}
149+
150+
// Check for trailing arguments
151+
if (opts.trailing.length) {
152+
stderr.write(colorsUtil.stderr.yellow("WARN: ") + "Unsupported trailing arguments: " + opts.trailing.join(" ") + EOL);
141153
}
142154

143155
// Use default callback if none is provided
144156
if (!callback) callback = function defaultCallback(err) {
145157
var code = 0;
146158
if (err) {
147-
stderr.write(colors.stderr.red("ERROR: ") + err.stack.replace(/^ERROR: /i, "") + EOL);
159+
stderr.write(colorsUtil.stderr.red("ERROR: ") + err.stack.replace(/^ERROR: /i, "") + EOL);
148160
code = 1;
149161
}
150162
return code;
@@ -156,43 +168,22 @@ exports.main = function main(argv, options, callback) {
156168
return callback(null);
157169
}
158170
// Print the help message if requested or no source files are provided
159-
if (args.help || args._.length < 1) {
160-
const opts = [];
161-
Object.keys(exports.options).forEach(name => {
162-
var option = exports.options[name];
163-
var text = " ";
164-
text += "--" + name;
165-
if (option.aliases && option.aliases[0].length === 1) {
166-
text += ", -" + option.aliases[0];
167-
}
168-
while (text.length < indent) {
169-
text += " ";
170-
}
171-
if (Array.isArray(option.description)) {
172-
opts.push(text + option.description[0] + option.description.slice(1).map(line => {
173-
for (let i = 0; i < indent; ++i) {
174-
line = " " + line;
175-
}
176-
return EOL + line;
177-
}).join(""));
178-
} else {
179-
opts.push(text + option.description);
180-
}
181-
});
182-
171+
if (args.help || !argv.length) {
183172
var out = args.help ? stdout : stderr;
184-
var color = args.help ? colors.stdout : colors.stderr;
173+
var color = args.help ? colorsUtil.stdout : colorsUtil.stderr;
185174
out.write([
186-
color.white("Syntax"),
175+
color.white("SYNTAX"),
187176
" " + color.cyan("asc") + " [entryFile ...] [options]",
188177
"",
189-
color.white("Examples"),
178+
color.white("EXAMPLES"),
190179
" " + color.cyan("asc") + " hello.ts",
191180
" " + color.cyan("asc") + " hello.ts -b hello.wasm -t hello.wat",
192181
" " + color.cyan("asc") + " hello1.ts hello2.ts -b -O > hello.wasm",
193182
"",
194-
color.white("Options"),
195-
].concat(opts).join(EOL) + EOL);
183+
color.white("OPTIONS"),
184+
].concat(
185+
optionsUtil.help(exports.options, 24, EOL)
186+
).join(EOL) + EOL);
196187
return callback(null);
197188
}
198189

@@ -209,7 +200,6 @@ exports.main = function main(argv, options, callback) {
209200
// Set up transforms
210201
const transforms = [];
211202
if (args.transform) {
212-
if (typeof args.transform === "string") args.transform = args.transform.split(",");
213203
args.transform.forEach(transform =>
214204
transforms.push(
215205
require(
@@ -246,8 +236,9 @@ exports.main = function main(argv, options, callback) {
246236
}
247237
const customLibDirs = [];
248238
if (args.lib) {
249-
if (typeof args.lib === "string") args.lib = args.lib.split(",");
250-
Array.prototype.push.apply(customLibDirs, args.lib.map(lib => lib.trim()));
239+
let lib = args.lib;
240+
if (typeof lib === "string") lib = lib.split(",");
241+
Array.prototype.push.apply(customLibDirs, lib.map(lib => lib.trim()));
251242
for (let i = 0, k = customLibDirs.length; i < k; ++i) { // custom
252243
let libDir = customLibDirs[i];
253244
let libFiles;
@@ -275,10 +266,10 @@ exports.main = function main(argv, options, callback) {
275266
}
276267

277268
// Include entry files
278-
for (let i = 0, k = args._.length; i < k; ++i) {
279-
const filename = args._[i];
269+
for (let i = 0, k = argv.length; i < k; ++i) {
270+
const filename = argv[i];
280271

281-
let sourcePath = filename.replace(/\\/g, "/").replace(/(\.ts|\/)$/, "");
272+
let sourcePath = String(filename).replace(/\\/g, "/").replace(/(\.ts|\/)$/, "");
282273

283274
// Try entryPath.ts, then entryPath/index.ts
284275
let sourceText = readFile(path.join(baseDir, sourcePath) + ".ts");
@@ -385,51 +376,28 @@ exports.main = function main(argv, options, callback) {
385376
const program = assemblyscript.finishParsing(parser);
386377

387378
// Set up optimization levels
388-
var optimizeLevel = -1;
379+
var optimizeLevel = 0;
389380
var shrinkLevel = 0;
390-
var debugInfo = !args.noDebug;
391-
if (args.optimize !== false) {
392-
if (typeof args.optimize === "number") {
393-
optimizeLevel = args.optimize;
394-
} else if (args["0"]) {
395-
optimizeLevel = 0;
396-
} else if (args["1"]) {
397-
optimizeLevel = 1;
398-
} else if (args["2"]) {
399-
optimizeLevel = 2;
400-
} else if (args["3"]) {
401-
optimizeLevel = 3;
402-
} else if (args.optimize === true) {
403-
optimizeLevel = exports.defaultOptimizeLevel;
404-
shrinkLevel = exports.defaultShrinkLevel;
405-
} else
406-
optimizeLevel = 0;
407-
}
408-
if (args["s"]) {
409-
shrinkLevel = 1;
410-
} else if (args["z"]) {
411-
shrinkLevel = 2;
381+
if (args.optimize) {
382+
optimizeLevel = exports.defaultOptimizeLevel;
383+
shrinkLevel = exports.defaultShrinkLevel;
412384
}
413385
if (typeof args.optimizeLevel === "number") {
414386
optimizeLevel = args.optimizeLevel;
415387
}
416388
if (typeof args.shrinkLevel === "number") {
417389
shrinkLevel = args.shrinkLevel;
418-
} else if (args.shrinkLevel === "s") {
419-
shrinkLevel = 1;
420-
} else if (args.shrinkLevel === "z") {
421-
shrinkLevel = 2;
422390
}
423-
optimizeLevel = Math.max(optimizeLevel, 0);
424-
shrinkLevel = Math.max(shrinkLevel, 0);
391+
optimizeLevel = Math.min(Math.max(optimizeLevel, 0), 3);
392+
shrinkLevel = Math.min(Math.max(shrinkLevel, 0), 2);
425393

426394
// Begin compilation
427395
const compilerOptions = assemblyscript.createOptions();
428396
assemblyscript.setTarget(compilerOptions, 0);
429-
assemblyscript.setNoTreeShaking(compilerOptions, !!args.noTreeShaking);
430-
assemblyscript.setNoAssert(compilerOptions, !!args.noAssert);
431-
assemblyscript.setImportMemory(compilerOptions, !!args.importMemory);
432-
assemblyscript.setImportTable(compilerOptions, !!args.importTable);
397+
assemblyscript.setNoTreeShaking(compilerOptions, args.noTreeShaking);
398+
assemblyscript.setNoAssert(compilerOptions, args.noAssert);
399+
assemblyscript.setImportMemory(compilerOptions, args.importMemory);
400+
assemblyscript.setImportTable(compilerOptions, args.importTable);
433401
assemblyscript.setMemoryBase(compilerOptions, args.memoryBase >>> 0);
434402
assemblyscript.setSourceMap(compilerOptions, args.sourceMap != null);
435403
assemblyscript.setOptimizeLevelHints(compilerOptions, optimizeLevel, shrinkLevel);
@@ -515,7 +483,7 @@ exports.main = function main(argv, options, callback) {
515483

516484
module.setOptimizeLevel(optimizeLevel);
517485
module.setShrinkLevel(shrinkLevel);
518-
module.setDebugInfo(debugInfo);
486+
module.setDebugInfo(!args.noDebug);
519487

520488
var runPasses = [];
521489
if (args.runPasses) {
@@ -741,7 +709,7 @@ exports.main = function main(argv, options, callback) {
741709
var files;
742710
try {
743711
stats.readTime += measure(() => {
744-
files = require("glob").sync("*.ts", { cwd: dirname });
712+
files = require("glob").sync("!(*.d).ts", { cwd: dirname });
745713
});
746714
return files;
747715
} catch (e) {
@@ -764,25 +732,23 @@ exports.main = function main(argv, options, callback) {
764732
}
765733
}
766734

767-
/** Parses the specified command line arguments. */
768-
function parseArguments(argv) {
769-
const opts = {};
770-
Object.keys(exports.options).forEach(key => {
771-
const opt = exports.options[key];
772-
if (opt.aliases) {
773-
(opts.alias || (opts.alias = {}))[key] = opt.aliases;
774-
}
775-
if (opt.default !== undefined) {
776-
(opts.default || (opts.default = {}))[key] = opt.default;
777-
}
778-
if (opt.type === "string") {
779-
(opts.string || (opts.string = [])).push(key);
780-
} else if (opt.type === "boolean") {
781-
(opts.boolean || (opts.boolean = [])).push(key);
782-
}
783-
});
784-
return require("minimist")(argv, opts);
785-
}
735+
var argumentSubstitutions = {
736+
"-O" : [ "--optimize" ],
737+
"-Os" : [ "--optimize", "--shrinkLevel", "1" ],
738+
"-Oz" : [ "--optimize", "--shrinkLevel", "2" ],
739+
"-O0" : [ "--optimizeLevel", "0", "--shrinkLevel", "0" ],
740+
"-O0s": [ "--optimizeLevel", "0", "--shrinkLevel", "1" ],
741+
"-O0z": [ "--optimizeLevel", "0", "--shrinkLevel", "2" ],
742+
"-O1" : [ "--optimizeLevel", "1", "--shrinkLevel", "0" ],
743+
"-O1s": [ "--optimizeLevel", "1", "--shrinkLevel", "1" ],
744+
"-O1z": [ "--optimizeLevel", "1", "--shrinkLevel", "2" ],
745+
"-O2" : [ "--optimizeLevel", "2", "--shrinkLevel", "0" ],
746+
"-O2s": [ "--optimizeLevel", "2", "--shrinkLevel", "1" ],
747+
"-O2z": [ "--optimizeLevel", "2", "--shrinkLevel", "2" ],
748+
"-O3" : [ "--optimizeLevel", "3", "--shrinkLevel", "0" ],
749+
"-O3s": [ "--optimizeLevel", "3", "--shrinkLevel", "1" ],
750+
"-O3z": [ "--optimizeLevel", "3", "--shrinkLevel", "2" ],
751+
};
786752

787753
/** Checks diagnostics emitted so far for errors. */
788754
function checkDiagnostics(emitter, stderr) {

0 commit comments

Comments
 (0)