Skip to content

Commit

Permalink
Merge branch 'master' into parser
Browse files Browse the repository at this point in the history
  • Loading branch information
willemneal committed Jan 2, 2019
2 parents c823422 + d5f72e3 commit f0477ba
Show file tree
Hide file tree
Showing 76 changed files with 13,728 additions and 4,809 deletions.
1 change: 1 addition & 0 deletions NOTICE
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ under the licensing terms detailed in LICENSE:
* Alan Pierce <alangpierce@gmail.com>
* Palmer <pengliao@live.cn>
* Linus Unnebäck <linus@folkdatorn.se>
* Joshua Tenner <tenner.joshua@gmail.com>

Portions of this software are derived from third-party works licensed under
the following terms:
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@ $> npm link
Examples
--------

* **[Conway's Game of Life](./examples/game-of-life)** [ [demo](https://rawgit.com/AssemblyScript/assemblyscript/master/examples/game-of-life/index.html) | [fiddle](https://webassembly.studio/?f=gvuw4enb3qk) ]<br />
* **[Conway's Game of Life](./examples/game-of-life)** [ [demo](https://assemblyscript.github.io/assemblyscript/examples/game-of-life) | [fiddle](https://webassembly.studio/?f=gvuw4enb3qk) ]<br />
Continuously updates the cellular automaton and visualizes its state on a canvas.

* **[Mandelbrot Set](./examples/mandelbrot)** [ [demo](https://rawgit.com/AssemblyScript/assemblyscript/master/examples/mandelbrot/index.html) | [fiddle](https://webassembly.studio/?f=m6hbiw9wyq) ]<br />
* **[Mandelbrot Set](./examples/mandelbrot)** [ [demo](https://assemblyscript.github.io/assemblyscript/examples/mandelbrot) | [fiddle](https://webassembly.studio/?f=m6hbiw9wyq) ]<br />
Renders the Mandelbrot set to a canvas.

* **[i64 polyfill](./examples/i64-polyfill)**<br />
Expand All @@ -72,7 +72,7 @@ Examples
* **[WASM parser](./lib/parse)**<br />
A WebAssembly binary parser in WebAssembly.

* **[N-body system](./examples/n-body)** [ [demo](https://rawgit.com/AssemblyScript/assemblyscript/master/examples/n-body/index.html) ]<br />
* **[N-body system](./examples/n-body)** [ [demo](https://assemblyscript.github.io/assemblyscript/examples/n-body) ]<br />
An implementation of the N-body system from the [Computer Language Benchmarks Game](https://benchmarksgame-team.pages.debian.net/benchmarksgame/).

Building
Expand Down
6 changes: 3 additions & 3 deletions cli/asc.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,11 @@ interface CompilerOptions {
/** Standard error stream to use. */
stderr?: OutputStream;
/** Reads a file from disk (or memory). */
readFile?: (name: string) => string | null;
readFile?: (filename: string, baseDir: string) => string | null;
/** Writes a file to disk (or memory). */
writeFile?: (name: string, contents: Uint8Array) => void;
writeFile?: (filename: string, contents: Uint8Array, baseDir: string) => void;
/** Lists all files within a directory. */
listFiles?: (dir: string) => string[] | null;
listFiles?: (dirname: string, baseDir: string) => string[] | null;
}

/** Convenience function that parses and compiles source strings directly. */
Expand Down
119 changes: 59 additions & 60 deletions cli/asc.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,7 @@ exports.compileString = async (sources, options) => {
if (typeof sources === "string") sources = { "input.ts": sources };
const output = Object.create({
stdout: createMemoryStream(),
stderr: createMemoryStream(),
binary: null,
text: null
stderr: createMemoryStream()
});
debugger;
var argv = [];
Expand Down Expand Up @@ -278,7 +276,7 @@ exports.main = async function main(argv, options, callback) {
}
for (let j = 0, l = libFiles.length; j < l; ++j) {
let libPath = libFiles[j];
let libText = await readFile(path.join(libDir, libPath));
let libText = readFile(libPath, libDir);
if (libText === null) return callback(Error("Library file '" + libPath + "' not found."));
stats.parseCount++;
stats.parseTime += measure(() => {
Expand All @@ -293,35 +291,10 @@ exports.main = async function main(argv, options, callback) {
}
}

// Include entry files
for (let i = 0, k = argv.length; i < k; ++i) {
const filename = argv[i];
if (filename == "undefined") continue;

let sourcePath = String(filename).replace(/\\/g, "/").replace(/(\.ts|\/)$/, "");

// Try entryPath.ts, then entryPath/index.ts
let sourceText = await readFile(path.join(baseDir, sourcePath) + ".ts");
if (sourceText === null) {
sourceText = await readFile(path.join(baseDir, sourcePath, "index.ts"));
if (sourceText === null) {
return callback(Error("Entry file '" + sourcePath + ".ts' not found."));
} else {
sourcePath += "/index.ts";
}
} else {
sourcePath += ".ts";
}
debugger;

stats.parseCount++;
stats.parseTime += measure(() => {
parser = assemblyscript.parseFile(sourceText, sourcePath, true, parser);
});

// Process backlog
// Parses the backlog of imported files after including entry files
function parseBacklog() {
var sourcePath, sourceText;
while ((sourcePath = parser.nextFile()) != null) {
let found = false;

// Load library file if explicitly requested
if (sourcePath.startsWith(exports.libraryPrefix)) {
Expand All @@ -335,13 +308,12 @@ exports.main = async function main(argv, options, callback) {
sourcePath = exports.libraryPrefix + indexName + ".ts";
} else {
for (let i = 0, k = customLibDirs.length; i < k; ++i) {
const dir = customLibDirs[i];
sourceText = await readFile(path.join(dir, plainName + ".ts"));
sourceText = readFile(plainName + ".ts", customLibDirs[i]);
if (sourceText !== null) {
sourcePath = exports.libraryPrefix + plainName + ".ts";
break;
} else {
sourceText = await readFile(path.join(dir, indexName + ".ts"));
sourceText = readFile(indexName + ".ts", customLibDirs[i]);
if (sourceText !== null) {
sourcePath = exports.libraryPrefix + indexName + ".ts";
break;
Expand All @@ -354,11 +326,11 @@ exports.main = async function main(argv, options, callback) {
} else {
const plainName = sourcePath;
const indexName = sourcePath + "/index";
sourceText = await readFile(path.join(baseDir, plainName + ".ts"));
sourceText = readFile(plainName + ".ts", baseDir);
if (sourceText !== null) {
sourcePath = plainName + ".ts";
} else {
sourceText = await readFile(path.join(baseDir, indexName + ".ts"));
sourceText = readFile(indexName + ".ts", baseDir);
if (sourceText !== null) {
sourcePath = indexName + ".ts";
} else if (!plainName.startsWith(".")) {
Expand All @@ -371,12 +343,12 @@ exports.main = async function main(argv, options, callback) {
} else {
for (let i = 0, k = customLibDirs.length; i < k; ++i) {
const dir = customLibDirs[i];
sourceText = await readFile(path.join(dir, plainName + ".ts"));
sourceText = readFile(plainName + ".ts", customLibDirs[i]);
if (sourceText !== null) {
sourcePath = exports.libraryPrefix + plainName + ".ts";
break;
} else {
sourceText = await readFile(path.join(dir, indexName + ".ts"));
sourceText = readFile(indexName + ".ts", customLibDirs[i]);
if (sourceText !== null) {
sourcePath = exports.libraryPrefix + indexName + ".ts";
break;
Expand All @@ -400,7 +372,38 @@ exports.main = async function main(argv, options, callback) {
}
}

// Include entry files
for (let i = 0, k = argv.length; i < k; ++i) {
const filename = argv[i];

let sourcePath = String(filename).replace(/\\/g, "/").replace(/(\.ts|\/)$/, "");

// Try entryPath.ts, then entryPath/index.ts
let sourceText = readFile(sourcePath + ".ts", baseDir);
if (sourceText === null) {
sourceText = readFile(sourcePath + "/index.ts", baseDir);
if (sourceText === null) {
return callback(Error("Entry file '" + sourcePath + ".ts' not found."));
} else {
sourcePath += "/index.ts";
}
} else {
sourcePath += ".ts";
}

stats.parseCount++;
stats.parseTime += measure(() => {
parser = assemblyscript.parseFile(sourceText, sourcePath, true, parser);
});
let code = parseBacklog();
if (code) return code;
}

applyTransform("afterParse", parser);
{
let code = parseBacklog();
if (code) return code;
}

// Finish parsing
const program = assemblyscript.finishParsing(parser);
Expand Down Expand Up @@ -578,7 +581,7 @@ exports.main = async function main(argv, options, callback) {
});

if (args.binaryFile.length) {
await writeFile(path.join(baseDir, args.binaryFile), wasm.output);
writeFile(args.binaryFile, wasm.output, baseDir);
} else {
writeStdout(wasm.output);
hasStdout = true;
Expand All @@ -598,27 +601,23 @@ exports.main = async function main(argv, options, callback) {
text = exports.libraryFiles[stdName];
} else {
for (let i = 0, k = customLibDirs.length; i < k; ++i) {
text = await readFile(path.join(
customLibDirs[i],
name.substring(exports.libraryPrefix.length))
);
text = readFile(name.substring(exports.libraryPrefix.length), customLibDirs[i]);
if (text !== null) break;
}
}
} else {
text = await readFile(path.join(baseDir, name));
text = readFile(name, baseDir);
}
if (text === null) {
return callback(Error("Source file '" + name + "' not found."));
}
if (!sourceMap.sourceContents) sourceMap.sourceContents = [];
sourceMap.sourceContents[index] = text;
});
await writeFile(path.join(
baseDir,
writeFile(path.join(
path.dirname(args.binaryFile),
path.basename(sourceMapURL)
), JSON.stringify(sourceMap));
).replace(/^\.\//, ""), JSON.stringify(sourceMap), baseDir);
} else {
stderr.write("Skipped source map (stdout already occupied)" + EOL);
}
Expand All @@ -633,7 +632,7 @@ exports.main = async function main(argv, options, callback) {
stats.emitTime += measure(() => {
asm = module.toAsmjs();
});
await writeFile(path.join(baseDir, args.asmjsFile), asm);
writeFile(args.asmjsFile, asm, baseDir);
} else if (!hasStdout) {
stats.emitCount++;
stats.emitTime += measure(() => {
Expand All @@ -653,7 +652,7 @@ exports.main = async function main(argv, options, callback) {
stats.emitTime += measure(() => {
idl = assemblyscript.buildIDL(program);
});
await writeFile(path.join(baseDir, args.idlFile), idl);
writeFile(args.idlFile, idl, baseDir);
} else if (!hasStdout) {
stats.emitCount++;
stats.emitTime += measure(() => {
Expand All @@ -673,7 +672,7 @@ exports.main = async function main(argv, options, callback) {
stats.emitTime += measure(() => {
tsd = assemblyscript.buildTSD(program);
});
await writeFile(path.join(baseDir, args.tsdFile), tsd);
writeFile(args.tsdFile, tsd, baseDir);
} else if (!hasStdout) {
stats.emitCount++;
stats.emitTime += measure(() => {
Expand All @@ -693,7 +692,7 @@ exports.main = async function main(argv, options, callback) {
stats.emitTime += measure(() => {
wat = module.toText();
});
await writeFile(path.join(baseDir, args.textFile), wat);
writeFile(args.textFile, wat, baseDir);
} else if (!hasStdout) {
stats.emitCount++;
stats.emitTime += measure(() => {
Expand All @@ -710,28 +709,28 @@ exports.main = async function main(argv, options, callback) {
}
return callback(null);

function readFileNode(filename) {
function readFileNode(filename, baseDir) {
try {
let text;
stats.readCount++;
stats.readTime += measure(() => {
text = fs.readFileSync(filename, { encoding: "utf8" });
text = fs.readFileSync(path.join(baseDir, filename), { encoding: "utf8" });
});
return text;
} catch (e) {
return null;
}
}

function writeFileNode(filename, contents) {
function writeFileNode(filename, contents, baseDir) {
try {
stats.writeCount++;
stats.writeTime += measure(() => {
mkdirp(path.dirname(filename));
mkdirp(path.join(baseDir, path.dirname(filename)));
if (typeof contents === "string") {
fs.writeFileSync(filename, contents, { encoding: "utf8" } );
fs.writeFileSync(path.join(baseDir, filename), contents, { encoding: "utf8" } );
} else {
fs.writeFileSync(filename, contents);
fs.writeFileSync(path.join(baseDir, filename), contents);
}
});
return true;
Expand All @@ -740,11 +739,11 @@ exports.main = async function main(argv, options, callback) {
}
}

function listFilesNode(dirname) {
function listFilesNode(dirname, baseDir) {
var files;
try {
stats.readTime += measure(() => {
files = fs.readdirSync(dirname).filter(file => /^(?!.*\.d\.ts$).*\.ts$/.test(file));
files = fs.readdirSync(path.join(baseDir, dirname)).filter(file => /^(?!.*\.d\.ts$).*\.ts$/.test(file));
});
return files;
} catch (e) {
Expand Down
2 changes: 1 addition & 1 deletion dist/asc.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/asc.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/assemblyscript.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/assemblyscript.js.map

Large diffs are not rendered by default.

20 changes: 15 additions & 5 deletions lib/loader/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"use strict";

const hasBigInt64 = typeof BigUint64Array !== "undefined";
const thisPtr = Symbol();

/** Gets a string from an U32 and an U16 view on a memory. */
function getStringImpl(U32, U16, ptr) {
Expand Down Expand Up @@ -265,11 +266,11 @@ function demangle(exports, baseModule) {
let classElem = curr[className];
if (typeof classElem === "undefined" || !classElem.prototype) {
let ctor = function(...args) {
return ctor.wrap(ctor.prototype.constructor(...args));
return ctor.wrap(ctor.prototype.constructor(0, ...args));
};
ctor.prototype = {};
ctor.wrap = function(thisValue) {
return Object.create(ctor.prototype, { "this": { value: thisValue, writable: false } });
return Object.create(ctor.prototype, { [thisPtr]: { value: thisValue, writable: false } });
};
if (classElem) Object.getOwnPropertyNames(classElem).forEach(name =>
Object.defineProperty(ctor, name, Object.getOwnPropertyDescriptor(classElem, name))
Expand All @@ -283,13 +284,22 @@ function demangle(exports, baseModule) {
let getter = exports[internalName.replace("set:", "get:")];
let setter = exports[internalName.replace("get:", "set:")];
Object.defineProperty(curr, name, {
get: function() { return getter(this.this); },
set: function(value) { setter(this.this, value); },
get: function() { return getter(this[thisPtr]); },
set: function(value) { setter(this[thisPtr], value); },
enumerable: true
});
}
} else {
curr[name] = wrapFunction(elem, setargc);
if (name === 'constructor') {
curr[name] = wrapFunction(elem, setargc);
} else { // for methods
Object.defineProperty(curr, name, {
value: function (...args) {
setargc(args.length);
return elem(this[thisPtr], ...args);
}
});
}
}
} else {
if (/^(get|set):/.test(name)) {
Expand Down
11 changes: 10 additions & 1 deletion lib/loader/tests/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,14 @@ assert.strictEqual(fn(2), 4);
ptr = module.newFunction(module.varadd);
assert.strictEqual(module.calladd(ptr, 2, 3), 5);

// should be able to use a class
var car = new module.Car(5);
assert.strictEqual(car.numDoors, 5);
assert.strictEqual(car.isDoorsOpen, 0);
car.openDoors();
assert.strictEqual(car.isDoorsOpen, 1);
car.closeDoors();
assert.strictEqual(car.isDoorsOpen, 0);

// should be able to use trace
module.dotrace(42);
module.dotrace(42);
3 changes: 1 addition & 2 deletions src/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@ Portable compiler sources that compile to both JavaScript using `tsc` and, event

Architecture
------------

![](https://rawgit.com/AssemblyScript/assemblyscript/master/media/architecture.svg)
![](https://assemblyscript.github.io/assemblyscript/media/architecture.svg)
Loading

0 comments on commit f0477ba

Please sign in to comment.