Minor CLI and README cleanup

This commit is contained in:
dcodeIO 2018-06-14 15:57:04 +02:00
parent e18165bbbc
commit c102fc9848
13 changed files with 208 additions and 113 deletions

View File

@ -1,7 +1,6 @@
![](https://avatars1.githubusercontent.com/u/28916798?s=64) AssemblyScript
=================
[![npm](https://img.shields.io/npm/v/assemblyscript.svg)](https://www.npmjs.com/package/assemblyscript)
[![Build Status](https://travis-ci.org/AssemblyScript/assemblyscript.svg?branch=master)](https://travis-ci.org/AssemblyScript/assemblyscript)
[![Snap Status](https://build.snapcraft.io/badge/AssemblyScript/assemblyscript.svg)](https://build.snapcraft.io/user/AssemblyScript/assemblyscript)

View File

@ -8,11 +8,7 @@ if (process.argv.length < 3) printHelp();
function printHelp() {
console.log([
"Version " + version,
"Syntax: " + colors.cyan("asinit") + " [project directory]",
"",
colors.white("Sets up a new AssemblyScript project or updates an existing one."),
"",
"Sets up a new AssemblyScript project or updates an existing one.",
"For example, to create a new project in the current directory:",
"",
" " + colors.cyan("asinit") + " .",

View File

@ -14,6 +14,7 @@
const fs = require("fs");
const path = require("path");
const utf8 = require("@protobufjs/utf8");
const colors = require("./util/colors");
const EOL = process.platform === "win32" ? "\r\n" : "\n";
// Use distribution files if present, otherwise run the sources directly
@ -119,23 +120,26 @@ exports.main = function main(argv, options, callback) {
const listFiles = options.listFiles || listFilesNode;
const stats = options.stats || createStats();
// All of the above must be specified in browser environments
// Output must be specified if not present in the environment
if (!stdout) throw Error("'options.stdout' must be specified");
if (!stderr) throw Error("'options.stderr' must be specified");
if (!fs.readFileSync) {
if (readFile === readFileNode) throw Error("'options.readFile' must be specified");
if (writeFile === writeFileNode) throw Error("'options.writeFile' must be specified");
if (listFiles === listFilesNode) throw Error("'options.listFiles' must be specified");
}
const args = parseArguments(argv);
const indent = 24;
if (args.noColors) {
colors.stdout.supported =
colors.stderr.supported = false;
} else {
colors.stdout = colors.from(stdout);
colors.stderr = colors.from(stderr);
}
// Use default callback if none is provided
if (!callback) callback = function defaultCallback(err) {
var code = 0;
if (err) {
stderr.write(err.stack + EOL);
stderr.write(colors.stderr.red("ERROR: ") + err.stack.replace(/^ERROR: /i, "") + EOL);
code = 1;
}
return code;
@ -171,19 +175,29 @@ exports.main = function main(argv, options, callback) {
}
});
(args.help ? stdout : stderr).write([
"Version " + exports.version + (isDev ? "-dev" : ""),
"Syntax: asc [entryFile ...] [options]",
var out = args.help ? stdout : stderr;
var color = args.help ? colors.stdout : colors.stderr;
out.write([
color.white("Syntax"),
" " + color.cyan("asc") + " [entryFile ...] [options]",
"",
"Examples: asc hello.ts",
" asc hello.ts -b hello.wasm -t hello.wat",
" asc hello1.ts hello2.ts -b -O > hello.wasm",
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",
"",
"Options:"
color.white("Options"),
].concat(opts).join(EOL) + EOL);
return callback(null);
}
// I/O must be specified if not present in the environment
if (!fs.readFileSync) {
if (readFile === readFileNode) throw Error("'options.readFile' must be specified");
if (writeFile === writeFileNode) throw Error("'options.writeFile' must be specified");
if (listFiles === listFilesNode) throw Error("'options.listFiles' must be specified");
}
// Set up base directory
const baseDir = args.baseDir ? path.resolve(args.baseDir) : ".";
@ -859,6 +873,9 @@ function createMemoryStream(fn) {
}
this.push(chunk);
};
stream.reset = function() {
stream.length = 0;
};
stream.toBuffer = function() {
var offset = 0, i = 0, k = this.length;
while (i < k) offset += this[i++].length;

View File

@ -167,5 +167,9 @@
"measure": {
"description": "Prints measuring information on I/O and compile times.",
"type": "boolean"
},
"noColors": {
"description": "Disables terminal colors.",
"type": "boolean"
}
}

50
cli/util/colors.d.ts vendored Normal file
View File

@ -0,0 +1,50 @@
interface Colors {
/** Whether terminal colors are supported. */
supported: boolean;
/** Colors a string in gray if {@link supported}. */
gray(text: string): string;
/** Colors a string in red if {@link supported}. */
red(text: string): string;
/** Colors a string in green if {@link supported}. */
green(text: string): string;
/** Colors a string in yellow if {@link supported}. */
yellow(text: string): string;
/** Colors a string in blue if {@link supported}. */
blue(text: string): string;
/** Colors a string in magenta if {@link supported}. */
magenta(text: string): string;
/** Colors a string in cyan if {@link supported}. */
cyan(text: string): string;
/** Colors a string in white if {@link supported}. */
white(text: string): string;
}
interface Exports extends Colors {
/** Standard output wrapper. */
stdout: Colors;
/** Standard error wrapper. */
stderr: Colors;
/** Creates an instance for the specified stream. */
from(stream: any, base?: {}): Colors;
/** Gray color escape sequence. */
GRAY: string;
/** Red color escape sequence. */
RED: string;
/** Green color escape sequence. */
GREEN: string;
/** Yellow color escape sequence. */
YELLOW: string;
/** Blue color escape sequence. */
BLUE: string;
/** Magenta color escape sequence. */
MAGENTA: string;
/** Cyan color escape sequence. */
CYAN: string;
/** White color escape sequence. */
WHITE: string;
/** Reset color escape sequence. */
RESET: string;
}
declare const colors: Exports;
export = colors;

View File

@ -1,39 +1,30 @@
var hasColor = typeof process !== "undefined" && process && process.stdout && !!process.stdout.isTTY
|| typeof env !== "undefined" && env && "TRAVIS" in env;
var proc = typeof process !== "undefined" && process || {};
var isCI = proc.env && "CI" in proc.env;
function from(stream, base) {
var colors = base || {};
colors.supported = (stream && !!stream.isTTY) || isCI;
colors.gray = text => colors.supported ? exports.GRAY + text + exports.RESET : text;
colors.red = text => colors.supported ? exports.RED + text + exports.RESET : text;
colors.green = text => colors.supported ? exports.GREEN + text + exports.RESET : text;
colors.yellow = text => colors.supported ? exports.YELLOW + text + exports.RESET : text;
colors.blue = text => colors.supported ? exports.BLUE + text + exports.RESET : text;
colors.magenta = text => colors.supported ? exports.MAGENTA + text + exports.RESET : text;
colors.cyan = text => colors.supported ? exports.CYAN + text + exports.RESET : text;
colors.white = text => colors.supported ? exports.WHITE + text + exports.RESET : text;
return colors;
}
exports.stdout = from(proc.stdout, exports);
exports.stderr = from(proc.stderr);
exports.from = from;
exports.GRAY = "\u001b[90m";
exports.RED = "\u001b[91m";
exports.red = function(text) {
return hasColor ? exports.RED + text + exports.RESET : text;
};
exports.GREEN = "\u001b[92m";
exports.green = function(text) {
return hasColor ? exports.GREEN + text + exports.RESET : text;
};
exports.YELLOW = "\u001b[93m";
exports.yellow = function(text) {
return hasColor ? exports.YELLOW + text + exports.RESET : text;
};
exports.BLUE = "\u001b[94m";
exports.blue = function(text) {
return hasColor ? exports.BLUE + text + exports.RESET : text;
};
exports.MAGENTA = "\u001b[95m";
exports.magenta = function(text) {
return hasColor ? exports.MAGENTA + text + exports.RESET : text;
};
exports.CYAN = "\u001b[96m";
exports.cyan = function(text) {
return hasColor ? exports.CYAN + text + exports.RESET : text;
};
exports.WHITE = "\u001b[97m";
exports.white = function(text) {
return hasColor ? exports.WHITE + text + exports.RESET : text;
};
exports.RESET = "\u001b[0m";

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

View File

@ -46,7 +46,7 @@ export function diagnosticCategoryToString(category: DiagnosticCategory): string
}
/** ANSI escape sequence for blue foreground. */
export const COLOR_BLUE: string = "\u001b[94m";
export const COLOR_BLUE: string = "\u001b[96m";
/** ANSI escape sequence for yellow foreground. */
export const COLOR_YELLOW: string = "\u001b[93m";
/** ANSI escape sequence for red foreground. */

View File

@ -100,7 +100,10 @@ import {
getConstValueF64,
getConstValueI64Low
} from "./module";
import { CharCode } from "./util";
import {
CharCode
} from "./util";
/** Path delimiter inserted between file system levels. */
export const PATH_DELIMITER = "/";
@ -123,21 +126,21 @@ export const LIBRARY_PREFIX = LIBRARY_SUBST + PATH_DELIMITER;
/** Prefix used to indicate a filespace element. */
export const FILESPACE_PREFIX = "file:";
/** Represents a yet unresolved export. */
class QueuedExport {
isReExport: bool;
referencedName: string;
member: ExportMember;
}
/** Represents a yet unresolved import. */
class QueuedImport {
internalName: string;
referencedName: string;
referencedNameAlt: string;
localName: string;
externalName: string;
externalNameAlt: string;
declaration: ImportDeclaration | null; // not set if a filespace
}
/** Represents a yet unresolved export. */
class QueuedExport {
externalName: string;
isReExport: bool;
member: ExportMember;
}
/** Represents a type alias. */
class TypeAlias {
typeParameters: TypeParameterNode[] | null;
@ -317,6 +320,7 @@ export class Program extends DiagnosticEmitter {
diagnosticsOffset: i32 = 0;
/** Compiler options. */
options: Options;
/** Elements by internal name. */
elementsLookup: Map<string,Element> = new Map();
/** Class and function instances by internal name. */
@ -329,6 +333,7 @@ export class Program extends DiagnosticEmitter {
fileLevelExports: Map<string,Element> = new Map();
/** Module-level exports by exported name. */
moduleLevelExports: Map<string,Element> = new Map();
/** Array prototype reference. */
arrayPrototype: ClassPrototype | null = null;
/** ArrayBufferView prototype reference. */
@ -392,8 +397,8 @@ export class Program extends DiagnosticEmitter {
["boolean", Type.bool]
]);
var queuedExports = new Map<string,QueuedExport>();
var queuedImports = new Array<QueuedImport>();
var queuedExports = new Map<string,QueuedExport>();
var queuedExtends = new Array<ClassPrototype>();
var queuedImplements = new Array<ClassPrototype>();
@ -456,13 +461,13 @@ export class Program extends DiagnosticEmitter {
let queuedImport = queuedImports[i];
let declaration = queuedImport.declaration;
if (declaration) { // named
let element = this.tryResolveImport(queuedImport.referencedName, queuedExports);
let element = this.tryResolveImport(queuedImport.externalName, queuedExports);
if (element) {
this.elementsLookup.set(queuedImport.internalName, element);
this.elementsLookup.set(queuedImport.localName, element);
queuedImports.splice(i, 1);
} else {
if (element = this.tryResolveImport(queuedImport.referencedNameAlt, queuedExports)) {
this.elementsLookup.set(queuedImport.internalName, element);
if (element = this.tryResolveImport(queuedImport.externalNameAlt, queuedExports)) {
this.elementsLookup.set(queuedImport.localName, element);
queuedImports.splice(i, 1);
} else {
this.error(
@ -475,13 +480,13 @@ export class Program extends DiagnosticEmitter {
}
}
} else { // filespace
let element = this.elementsLookup.get(queuedImport.referencedName);
let element = this.elementsLookup.get(queuedImport.externalName);
if (element) {
this.elementsLookup.set(queuedImport.internalName, element);
this.elementsLookup.set(queuedImport.localName, element);
queuedImports.splice(i, 1);
} else {
if (element = this.elementsLookup.get(queuedImport.referencedNameAlt)) {
this.elementsLookup.set(queuedImport.internalName, element);
if (element = this.elementsLookup.get(queuedImport.externalNameAlt)) {
this.elementsLookup.set(queuedImport.localName, element);
queuedImports.splice(i, 1);
} else {
assert(false); // already reported by the parser not finding the file
@ -497,7 +502,7 @@ export class Program extends DiagnosticEmitter {
let element: Element | null;
do {
if (currentExport.isReExport) {
if (element = this.fileLevelExports.get(currentExport.referencedName)) {
if (element = this.fileLevelExports.get(currentExport.externalName)) {
this.setExportAndCheckLibrary(
exportName,
element,
@ -505,7 +510,7 @@ export class Program extends DiagnosticEmitter {
);
break;
}
currentExport = queuedExports.get(currentExport.referencedName);
currentExport = queuedExports.get(currentExport.externalName);
if (!currentExport) {
this.error(
DiagnosticCode.Module_0_has_no_exported_member_1,
@ -517,7 +522,7 @@ export class Program extends DiagnosticEmitter {
} else {
if (
// normal export
(element = this.elementsLookup.get(currentExport.referencedName)) ||
(element = this.elementsLookup.get(currentExport.externalName)) ||
// library re-export
(element = this.elementsLookup.get(currentExport.member.name.text))
) {
@ -602,21 +607,22 @@ export class Program extends DiagnosticEmitter {
/** Tries to resolve an import by traversing exports and queued exports. */
private tryResolveImport(
referencedName: string,
queuedExports: Map<string,QueuedExport>
externalName: string,
queuedNamedExports: Map<string,QueuedExport>
): Element | null {
var element: Element | null;
var fileLevelExports = this.fileLevelExports;
do {
if (element = fileLevelExports.get(referencedName)) return element;
let queuedExport = queuedExports.get(referencedName);
if (!queuedExport) return null;
if (element = fileLevelExports.get(externalName)) return element;
let queuedExport = queuedNamedExports.get(externalName);
if (!queuedExport) break;
if (queuedExport.isReExport) {
referencedName = queuedExport.referencedName;
externalName = queuedExport.externalName;
continue;
}
return this.elementsLookup.get(queuedExport.referencedName);
return this.elementsLookup.get(queuedExport.externalName);
} while (true);
return null;
}
private filterDecorators(decorators: DecoratorNode[], acceptedFlags: DecoratorFlags): DecoratorFlags {
@ -1330,7 +1336,7 @@ export class Program extends DiagnosticEmitter {
}
queuedExport = new QueuedExport();
queuedExport.isReExport = false;
queuedExport.referencedName = referencedName; // -> internal name
queuedExport.externalName = referencedName; // -> here: local name
queuedExport.member = member;
queuedExports.set(externalName, queuedExport);
@ -1353,7 +1359,7 @@ export class Program extends DiagnosticEmitter {
let seen = new Set<QueuedExport>();
while (queuedExport = queuedExports.get(referencedName)) {
if (queuedExport.isReExport) {
referencedElement = this.fileLevelExports.get(queuedExport.referencedName);
referencedElement = this.fileLevelExports.get(queuedExport.externalName);
if (referencedElement) {
this.setExportAndCheckLibrary(
externalName,
@ -1362,11 +1368,11 @@ export class Program extends DiagnosticEmitter {
);
return;
}
referencedName = queuedExport.referencedName;
referencedName = queuedExport.externalName;
if (seen.has(queuedExport)) break;
seen.add(queuedExport);
} else {
referencedElement = this.elementsLookup.get(queuedExport.referencedName);
referencedElement = this.elementsLookup.get(queuedExport.externalName);
if (referencedElement) {
this.setExportAndCheckLibrary(
externalName,
@ -1389,7 +1395,7 @@ export class Program extends DiagnosticEmitter {
}
queuedExport = new QueuedExport();
queuedExport.isReExport = true;
queuedExport.referencedName = referencedName; // -> export name
queuedExport.externalName = referencedName; // -> here: external name
queuedExport.member = member;
queuedExports.set(externalName, queuedExport);
}
@ -1507,11 +1513,11 @@ export class Program extends DiagnosticEmitter {
// otherwise queue it
let queuedImport = new QueuedImport();
queuedImport.internalName = internalName;
let prefix = FILESPACE_PREFIX + statement.internalPath;
queuedImport.referencedName = prefix;
queuedImport.referencedNameAlt = prefix + PATH_DELIMITER + "index";
queuedImport.declaration = null;
queuedImport.localName = internalName;
let externalName = FILESPACE_PREFIX + statement.internalPath;
queuedImport.externalName = externalName;
queuedImport.externalNameAlt = externalName + PATH_DELIMITER + "index";
queuedImport.declaration = null; // filespace
queuedImports.push(queuedImport);
}
}
@ -1519,47 +1525,47 @@ export class Program extends DiagnosticEmitter {
private initializeImport(
declaration: ImportDeclaration,
internalPath: string,
queuedExports: Map<string,QueuedExport>,
queuedNamedExports: Map<string,QueuedExport>,
queuedImports: QueuedImport[]
): void {
var internalName = declaration.fileLevelInternalName;
if (this.elementsLookup.has(internalName)) {
var localName = declaration.fileLevelInternalName;
if (this.elementsLookup.has(localName)) {
this.error(
DiagnosticCode.Duplicate_identifier_0,
declaration.name.range, internalName
declaration.name.range, localName
);
return;
}
var referencedName = internalPath + PATH_DELIMITER + declaration.externalName.text;
var externalName = internalPath + PATH_DELIMITER + declaration.externalName.text;
// resolve right away if the exact export exists
var element: Element | null;
if (element = this.fileLevelExports.get(referencedName)) {
this.elementsLookup.set(internalName, element);
if (element = this.fileLevelExports.get(externalName)) {
this.elementsLookup.set(localName, element);
return;
}
// otherwise queue it
const indexPart = PATH_DELIMITER + "index";
var queuedImport = new QueuedImport();
queuedImport.internalName = internalName;
queuedImport.localName = localName;
if (internalPath.endsWith(indexPart)) {
queuedImport.referencedName = referencedName; // try exact first
queuedImport.referencedNameAlt = (
queuedImport.externalName = externalName; // try exact first
queuedImport.externalNameAlt = (
internalPath.substring(0, internalPath.length - indexPart.length + 1) +
declaration.externalName.text
);
} else {
queuedImport.referencedName = referencedName; // try exact first
queuedImport.referencedNameAlt = (
queuedImport.externalName = externalName; // try exact first
queuedImport.externalNameAlt = (
internalPath +
indexPart +
PATH_DELIMITER +
declaration.externalName.text
);
}
queuedImport.declaration = declaration;
queuedImport.declaration = declaration; // named
queuedImports.push(queuedImport);
}

View File

@ -1,11 +1,43 @@
const asc = require("../dist/asc.js");
console.log("# asc.main");
const stdout = asc.createMemoryStream(arg => console.log("out:", arg));
const stderr = asc.createMemoryStream(arg => console.log("err:", arg));
const stdout = asc.createMemoryStream();
const stderr = asc.createMemoryStream();
const files = { "module.ts": `import "allocator/arena";` };
console.log("# asc --version");
asc.main([
"--version"
], {
stdout: stdout,
stderr: stderr
}, err => {
console.log(">>> STDOUT >>>");
process.stdout.write(stdout.toString());
stdout.reset();
console.log(">>> STDERR >>>");
process.stdout.write(stderr.toString());
stderr.reset();
});
console.log("\n# asc --help");
asc.main([
"--help"
], {
stdout: stdout,
stderr: stderr
}, err => {
console.log(">>> STDOUT >>>");
process.stdout.write(stdout.toString());
stdout.reset();
console.log(">>> STDERR >>>");
process.stdout.write(stderr.toString());
stderr.reset();
});
console.log("\n# asc module.ts --textFile");
asc.main([
"module.ts",
"--textFile"