Fix asc bundle with webpack 4, see #36; Function expression progress

This commit is contained in:
dcodeIO 2018-03-03 18:38:38 +01:00
parent a5e31200d3
commit f754b24819
14 changed files with 366 additions and 244 deletions

View File

@ -19,8 +19,8 @@ The API accepts the same options as the CLI but also lets you override stdout an
const asc = require("assemblyscript/bin/asc.js"); const asc = require("assemblyscript/bin/asc.js");
asc.main([ asc.main([
"myModule.ts", "myModule.ts",
"-b", "myModule.wasm", "--binaryFile", "myModule.wasm",
"-O", "--optimize",
"--sourceMap", "--sourceMap",
"--measure" "--measure"
], { ], {

View File

@ -1,4 +1,5 @@
#!/usr/bin/env node #!/usr/bin/env node
const asc = module.exports = require("./asc.js"); const asc = module.exports = require("./asc.js");
if (/\basc$/.test(process.argv[1])) if (/\basc$/.test(process.argv[1])) {
process.exitCode = asc.main(process.argv.slice(2)); process.exitCode = asc.main(process.argv.slice(2));
}

View File

@ -1,4 +1,13 @@
//////////////////////// Compiler frontend for node.js ///////////////////////// /**
* @file Compiler frontend for node.js
*
* Uses the low-level API exported from src/index.ts so it works with the compiler compiled to
* JavaScript as well as the compiler compiled to WebAssembly (eventually). Runs the sources
* directly through ts-node if distribution files are not present (indicated by a `-dev` version).
*
* Can also be packaged as a bundle suitable for in-browser use with the standard library injected
* in the build step. See dist/asc.js for the bundle and webpack.config.js for building details.
*/
const fs = require("fs"); const fs = require("fs");
const path = require("path"); const path = require("path");
@ -6,24 +15,24 @@ const os = require("os");
// 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;
(() => {
try { try {
assemblyscript = require("../dist/assemblyscript.js"); assemblyscript = require("../dist/assemblyscript.js");
isDev = false; isDev = false;
try { require("source-map-support").install(); } catch (e) {} // optional try { require("source-map-support").install(); } catch (e) {/* optional */}
} 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")
});
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 = require("./assemblyscript"); assemblyscript = eval("require('./assemblyscript')");
isDev = false; isDev = false;
} }
} }
})();
/** Whether this is a webpack bundle or not. */ /** Whether this is a webpack bundle or not. */
exports.isBundle = typeof BUNDLE_VERSION === "string"; exports.isBundle = typeof BUNDLE_VERSION === "string";
@ -32,8 +41,7 @@ exports.isBundle = typeof BUNDLE_VERSION === "string";
exports.isDev = isDev; exports.isDev = isDev;
/** AssemblyScript veresion. */ /** AssemblyScript veresion. */
exports.version = exports.isBundle ? BUNDLE_VERSION exports.version = exports.isBundle ? BUNDLE_VERSION : require("../package.json").version;
: require("../package.json").version;
/** Available options. */ /** Available options. */
exports.options = require("./asc.json"); exports.options = require("./asc.json");
@ -61,8 +69,9 @@ exports.main = function main(argv, options, callback) {
if (typeof options === "function") { if (typeof options === "function") {
callback = options; callback = options;
options = {}; options = {};
} else if (!options) } else if (!options) {
options = {}; options = {};
}
const stdout = options.stdout || process.stdout; const stdout = options.stdout || process.stdout;
const stderr = options.stderr || process.stderr; const stderr = options.stderr || process.stderr;
@ -72,17 +81,12 @@ exports.main = function main(argv, options, callback) {
const stats = options.stats || createStats(); const stats = options.stats || createStats();
// All of the above must be specified in browser environments // All of the above must be specified in browser environments
if (!stdout) if (!stdout) throw Error("'options.stdout' must be specified");
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");
if (!fs.readFileSync) { if (!fs.readFileSync) {
if (readFile === readFileNode) if (readFile === readFileNode) throw Error("'options.readFile' must be specified");
throw Error("'options.readFile' must be specified"); if (writeFile === writeFileNode) throw Error("'options.writeFile' must be specified");
if (writeFile === writeFileNode) if (listFiles === listFilesNode) throw Error("'options.listFiles' must be specified");
throw Error("'options.writeFile' must be specified");
if (listFiles === listFilesNode)
throw Error("'options.listFiles' must be specified");
} }
const args = parseArguments(argv); const args = parseArguments(argv);
@ -110,18 +114,22 @@ exports.main = function main(argv, options, callback) {
var option = exports.options[name]; var option = exports.options[name];
var text = " "; var text = " ";
text += "--" + name; text += "--" + name;
if (option.aliases && option.aliases[0].length === 1) if (option.aliases && option.aliases[0].length === 1) {
text += ", -" + option.aliases[0]; text += ", -" + option.aliases[0];
while (text.length < indent) }
while (text.length < indent) {
text += " "; text += " ";
}
if (Array.isArray(option.desc)) { if (Array.isArray(option.desc)) {
opts.push(text + option.desc[0] + option.desc.slice(1).map(line => { opts.push(text + option.desc[0] + option.desc.slice(1).map(line => {
for (let i = 0; i < indent; ++i) for (let i = 0; i < indent; ++i) {
line = " " + line; line = " " + line;
}
return os.EOL + line; return os.EOL + line;
}).join("")); }).join(""));
} else } else {
opts.push(text + option.desc); opts.push(text + option.desc);
}
}); });
(args.help ? stdout : stderr).write([ (args.help ? stdout : stderr).write([
@ -146,8 +154,9 @@ exports.main = function main(argv, options, callback) {
// Include custom library components (with or without stdlib) // Include custom library components (with or without stdlib)
if (args.lib) { if (args.lib) {
if (typeof args.lib === "string") if (typeof args.lib === "string") {
args.lib = args.lib.split(","); args.lib = args.lib.split(",");
}
Array.prototype.push.apply(libDirs, args.lib.map(trim)); Array.prototype.push.apply(libDirs, args.lib.map(trim));
} }
@ -164,12 +173,14 @@ exports.main = function main(argv, options, callback) {
let sourceText = readFile(path.join(baseDir, sourcePath) + ".ts"); let sourceText = readFile(path.join(baseDir, sourcePath) + ".ts");
if (sourceText === null) { if (sourceText === null) {
sourceText = readFile(path.join(baseDir, sourcePath, "index.ts")); sourceText = readFile(path.join(baseDir, sourcePath, "index.ts"));
if (sourceText === null) if (sourceText === null) {
return callback(Error("Entry file '" + sourcePath + ".ts' not found.")); return callback(Error("Entry file '" + sourcePath + ".ts' not found."));
else } else {
sourcePath += "/index.ts"; sourcePath += "/index.ts";
} else }
} else {
sourcePath += ".ts"; sourcePath += ".ts";
}
stats.parseCount++; stats.parseCount++;
stats.parseTime += measure(() => { stats.parseTime += measure(() => {
@ -182,9 +193,9 @@ exports.main = function main(argv, options, callback) {
// Load library file if explicitly requested // Load library file if explicitly requested
if (sourcePath.startsWith(exports.libraryPrefix)) { if (sourcePath.startsWith(exports.libraryPrefix)) {
for (let i = 0, k = libDirs.length; i < k; ++i) { for (let i = 0, k = libDirs.length; i < k; ++i) {
if (exports.libraryFiles.hasOwnProperty(sourcePath)) if (exports.libraryFiles.hasOwnProperty(sourcePath)) {
sourceText = exports.libraryFiles[sourcePath]; sourceText = exports.libraryFiles[sourcePath];
else { } else {
sourceText = readFile(path.join( sourceText = readFile(path.join(
libDirs[i], libDirs[i],
sourcePath.substring(exports.libraryPrefix.length) + ".ts") sourcePath.substring(exports.libraryPrefix.length) + ".ts")
@ -205,9 +216,9 @@ exports.main = function main(argv, options, callback) {
for (let i = 0, k = libDirs.length; i < k; ++i) { for (let i = 0, k = libDirs.length; i < k; ++i) {
const dir = libDirs[i]; const dir = libDirs[i];
const key = exports.libraryPrefix + sourcePath; const key = exports.libraryPrefix + sourcePath;
if (exports.libraryFiles.hasOwnProperty(key)) if (exports.libraryFiles.hasOwnProperty(key)) {
sourceText = exports.libraryFiles[key]; sourceText = exports.libraryFiles[key];
else { } else {
sourceText = readFile(path.join(dir, sourcePath + ".ts")); sourceText = readFile(path.join(dir, sourcePath + ".ts"));
if (sourceText !== null) { if (sourceText !== null) {
sourcePath = exports.libraryPrefix + sourcePath + ".ts"; sourcePath = exports.libraryPrefix + sourcePath + ".ts";
@ -215,30 +226,33 @@ exports.main = function main(argv, options, callback) {
} }
} }
} }
if (sourceText === null) if (sourceText === null) {
return callback( return callback(
Error("Import file '" + sourcePath + ".ts' not found.") Error("Import file '" + sourcePath + ".ts' not found.")
); );
} else }
} else {
sourcePath += "/index.ts"; sourcePath += "/index.ts";
} else }
} else {
sourcePath += ".ts"; sourcePath += ".ts";
} }
}
stats.parseCount++; stats.parseCount++;
stats.parseTime += measure(() => { stats.parseTime += measure(() => {
assemblyscript.parseFile(sourceText, sourcePath, false, parser); assemblyscript.parseFile(sourceText, sourcePath, false, parser);
}); });
} }
if (checkDiagnostics(parser, stderr)) if (checkDiagnostics(parser, stderr)) {
return callback(Error("Parse error")); return callback(Error("Parse error"));
} }
}
// Include (other) library components // Include (other) library components
var hasBundledLibrary = false; var hasBundledLibrary = false;
if (!args.noLib) if (!args.noLib)
Object.keys(exports.libraryFiles).forEach(libPath => { Object.keys(exports.libraryFiles).forEach(libPath => {
if (libPath.lastIndexOf("/") >= exports.libraryPrefix.length) if (libPath.lastIndexOf("/") >= exports.libraryPrefix.length) return;
return;
stats.parseCount++; stats.parseCount++;
stats.parseTime += measure(() => { stats.parseTime += measure(() => {
parser = assemblyscript.parseFile( parser = assemblyscript.parseFile(
@ -257,8 +271,9 @@ exports.main = function main(argv, options, callback) {
for (let j = 0, l = libFiles.length; j < l; ++j) { for (let j = 0, l = libFiles.length; j < l; ++j) {
let libPath = libFiles[j]; let libPath = libFiles[j];
let libText = readFile(path.join(libDir, libPath)); let libText = readFile(path.join(libDir, libPath));
if (libText === null) if (libText === null) {
return callback(Error("Library file '" + libPath + "' not found.")); return callback(Error("Library file '" + libPath + "' not found."));
}
stats.parseCount++; stats.parseCount++;
stats.parseTime += measure(() => { stats.parseTime += measure(() => {
parser = assemblyscript.parseFile( parser = assemblyscript.parseFile(
@ -283,6 +298,7 @@ exports.main = function main(argv, options, callback) {
var module; var module;
stats.compileCount++; stats.compileCount++;
(() => {
try { try {
stats.compileTime += measure(() => { stats.compileTime += measure(() => {
module = assemblyscript.compile(parser, compilerOptions); module = assemblyscript.compile(parser, compilerOptions);
@ -290,6 +306,7 @@ exports.main = function main(argv, options, callback) {
} catch (e) { } catch (e) {
return callback(e); return callback(e);
} }
})();
if (checkDiagnostics(parser, stderr)) { if (checkDiagnostics(parser, stderr)) {
if (module) module.dispose(); if (module) module.dispose();
return callback(Error("Compile error")); return callback(Error("Compile error"));
@ -327,35 +344,40 @@ exports.main = function main(argv, options, callback) {
var debugInfo = !args.noDebug; var debugInfo = !args.noDebug;
if (args.optimize !== false) { if (args.optimize !== false) {
if (typeof args.optimize === "number") if (typeof args.optimize === "number") {
optimizeLevel = args.optimize; optimizeLevel = args.optimize;
else if (args["0"]) } else if (args["0"]) {
optimizeLevel = 0; optimizeLevel = 0;
else if (args["1"]) } else if (args["1"]) {
optimizeLevel = 1; optimizeLevel = 1;
else if (args["2"]) } else if (args["2"]) {
optimizeLevel = 2; optimizeLevel = 2;
else if (args["3"]) } else if (args["3"]) {
optimizeLevel = 3; optimizeLevel = 3;
else if (args.optimize === true) { } else if (args.optimize === true) {
optimizeLevel = exports.defaultOptimizeLevel; optimizeLevel = exports.defaultOptimizeLevel;
shrinkLevel = exports.defaultShrinkLevel; shrinkLevel = exports.defaultShrinkLevel;
} else } else
optimizeLevel = 0; optimizeLevel = 0;
} }
if (args["s"])
shrinkLevel = 1;
else if (args["z"])
shrinkLevel = 2;
if (typeof args.optimizeLevel === "number") if (args["s"]) {
optimizeLevel = args.optimizeLevel;
if (typeof args.shrinkLevel === "number")
shrinkLevel = args.shrinkLevel;
else if (args.shrinkLevel === "s")
shrinkLevel = 1; shrinkLevel = 1;
else if (args.shrinkLevel === "z") } else if (args["z"]) {
shrinkLevel = 2; shrinkLevel = 2;
}
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;
}
module.setOptimizeLevel(optimizeLevel > 0 ? optimizeLevel : 0); module.setOptimizeLevel(optimizeLevel > 0 ? optimizeLevel : 0);
module.setShrinkLevel(shrinkLevel); module.setShrinkLevel(shrinkLevel);
@ -363,14 +385,16 @@ exports.main = function main(argv, options, callback) {
var runPasses = []; var runPasses = [];
if (args.runPasses) { if (args.runPasses) {
if (typeof args.runPasses === "string") if (typeof args.runPasses === "string") {
args.runPasses = args.runPasses.split(","); args.runPasses = args.runPasses.split(",");
if (args.runPasses.length) }
if (args.runPasses.length) {
args.runPasses.forEach(pass => { args.runPasses.forEach(pass => {
if (runPasses.indexOf(pass) < 0) if (runPasses.indexOf(pass) < 0)
runPasses.push(pass); runPasses.push(pass);
}); });
} }
}
// Optimize the module if requested // Optimize the module if requested
if (optimizeLevel >= 0) { if (optimizeLevel >= 0) {
@ -393,13 +417,14 @@ exports.main = function main(argv, options, callback) {
let hasStdout = false; let hasStdout = false;
if (args.outFile != null) { if (args.outFile != null) {
if (/\.was?t$/.test(args.outFile) && args.textFile == null) if (/\.was?t$/.test(args.outFile) && args.textFile == null) {
args.textFile = args.outFile; args.textFile = args.outFile;
else if (/\.js$/.test(args.outFile) && args.asmjsFile == null) } else if (/\.js$/.test(args.outFile) && args.asmjsFile == null) {
args.asmjsFile = args.outFile; args.asmjsFile = args.outFile;
else if (args.binaryFile == null) } else if (args.binaryFile == null) {
args.binaryFile = args.outFile; args.binaryFile = args.outFile;
} }
}
// Write binary // Write binary
if (args.binaryFile != null) { if (args.binaryFile != null) {
@ -437,12 +462,13 @@ exports.main = function main(argv, options, callback) {
); );
if (text !== null) break; if (text !== null) break;
} }
} else } else {
text = readFile(path.join(baseDir, name)); text = readFile(path.join(baseDir, name));
if (text === null) }
if (text === null) {
return callback(Error("Source file '" + name + "' not found.")); return callback(Error("Source file '" + name + "' not found."));
if (!sourceMap.sourceContents) }
sourceMap.sourceContents = []; if (!sourceMap.sourceContents) sourceMap.sourceContents = [];
sourceMap.sourceContents[index] = text; sourceMap.sourceContents[index] = text;
}); });
writeFile(path.join( writeFile(path.join(
@ -501,8 +527,9 @@ exports.main = function main(argv, options, callback) {
} }
module.dispose(); module.dispose();
if (args.measure) if (args.measure) {
printStats(stats, stderr); printStats(stats, stderr);
}
return callback(null); return callback(null);
function readFileNode(filename) { function readFileNode(filename) {
@ -522,10 +549,11 @@ exports.main = function main(argv, options, callback) {
try { try {
stats.writeCount++; stats.writeCount++;
stats.writeTime += measure(() => { stats.writeTime += measure(() => {
if (typeof contents === "string") if (typeof contents === "string") {
fs.writeFileSync(filename, contents, { encoding: "utf8" } ); fs.writeFileSync(filename, contents, { encoding: "utf8" } );
else } else {
fs.writeFileSync(filename, contents); fs.writeFileSync(filename, contents);
}
}); });
return true; return true;
} catch (e) { } catch (e) {
@ -551,10 +579,11 @@ exports.main = function main(argv, options, callback) {
writeStdout.used = true; writeStdout.used = true;
} }
stats.writeTime += measure(() => { stats.writeTime += measure(() => {
if (typeof contents === "string") if (typeof contents === "string") {
stdout.write(contents, { encoding: "utf8" }); stdout.write(contents, { encoding: "utf8" });
else } else {
stdout.write(contents); stdout.write(contents);
}
}); });
} }
} }
@ -564,14 +593,17 @@ function parseArguments(argv) {
const opts = {}; const opts = {};
Object.keys(exports.options).forEach(key => { Object.keys(exports.options).forEach(key => {
const opt = exports.options[key]; const opt = exports.options[key];
if (opt.aliases) if (opt.aliases) {
(opts.alias || (opts.alias = {}))[key] = opt.aliases; (opts.alias || (opts.alias = {}))[key] = opt.aliases;
if (opt.default !== undefined) }
if (opt.default !== undefined) {
(opts.default || (opts.default = {}))[key] = opt.default; (opts.default || (opts.default = {}))[key] = opt.default;
if (opt.type === "string") }
if (opt.type === "string") {
(opts.string || (opts.string = [])).push(key); (opts.string || (opts.string = [])).push(key);
else if (opt.type === "boolean") } else if (opt.type === "boolean") {
(opts.boolean || (opts.boolean = [])).push(key); (opts.boolean || (opts.boolean = [])).push(key);
}
}); });
return require("minimist")(argv, opts); return require("minimist")(argv, opts);
} }
@ -587,8 +619,7 @@ function checkDiagnostics(emitter, stderr) {
assemblyscript.formatDiagnostic(diagnostic, stderr.isTTY, true) + assemblyscript.formatDiagnostic(diagnostic, stderr.isTTY, true) +
os.EOL + os.EOL os.EOL + os.EOL
); );
if (assemblyscript.isError(diagnostic)) if (assemblyscript.isError(diagnostic)) hasErrors = true;
hasErrors = true;
} }
return hasErrors; return hasErrors;
} }
@ -617,8 +648,7 @@ function createStats() {
exports.createStats = createStats; exports.createStats = createStats;
if (!process.hrtime) if (!process.hrtime) process.hrtime = require("browser-process-hrtime");
process.hrtime = require("browser-process-hrtime");
/** Measures the execution time of the specified function. */ /** Measures the execution time of the specified function. */
function measure(fn) { function measure(fn) {

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

@ -38,7 +38,7 @@
"node": ">=8" "node": ">=8"
}, },
"scripts": { "scripts": {
"build": "webpack", "build": "webpack --mode production",
"clean": "node scripts/clean", "clean": "node scripts/clean",
"lint": "npm run lint:compiler && npm run lint:library", "lint": "npm run lint:compiler && npm run lint:library",
"lint:compiler": "tslint -c tslint.json --project src --formatters-dir lib/tslint --format as", "lint:compiler": "tslint -c tslint.json --project src --formatters-dir lib/tslint --format as",

View File

@ -294,7 +294,7 @@ export class Compiler extends DiagnosticEmitter {
var pages = i64_shr_u(i64_align(memoryOffset, 0x10000), i64_new(16, 0)); var pages = i64_shr_u(i64_align(memoryOffset, 0x10000), i64_new(16, 0));
this.module.setMemory( this.module.setMemory(
i64_low(pages), i64_low(pages),
Module.MAX_MEMORY_WASM32 /* TODO: not WASM64 compatible yet */, Module.MAX_MEMORY_WASM32, // TODO: not WASM64 compatible yet
this.memorySegments, this.memorySegments,
this.options.target, this.options.target,
"memory" "memory"
@ -323,6 +323,7 @@ export class Compiler extends DiagnosticEmitter {
compileSourceByPath(normalizedPathWithoutExtension: string, reportNode: Node): void { compileSourceByPath(normalizedPathWithoutExtension: string, reportNode: Node): void {
var sources = this.program.sources; var sources = this.program.sources;
// try file.ts
var source: Source; var source: Source;
var expected = normalizedPathWithoutExtension + ".ts"; var expected = normalizedPathWithoutExtension + ".ts";
for (var i = 0, k = sources.length; i < k; ++i) { for (var i = 0, k = sources.length; i < k; ++i) {
@ -333,6 +334,7 @@ export class Compiler extends DiagnosticEmitter {
} }
} }
// try file/index.ts
expected = normalizedPathWithoutExtension + "/index.ts"; expected = normalizedPathWithoutExtension + "/index.ts";
for (i = 0, k = sources.length; i < k; ++i) { for (i = 0, k = sources.length; i < k; ++i) {
source = sources[i]; source = sources[i];
@ -342,6 +344,7 @@ export class Compiler extends DiagnosticEmitter {
} }
} }
// try (lib)/file.ts
expected = LIBRARY_PREFIX + normalizedPathWithoutExtension + ".ts"; expected = LIBRARY_PREFIX + normalizedPathWithoutExtension + ".ts";
for (i = 0, k = sources.length; i < k; ++i) { for (i = 0, k = sources.length; i < k; ++i) {
source = sources[i]; source = sources[i];
@ -362,6 +365,7 @@ export class Compiler extends DiagnosticEmitter {
if (files.has(source.normalizedPath)) return; if (files.has(source.normalizedPath)) return;
files.add(source.normalizedPath); files.add(source.normalizedPath);
// compile top-level statements
var noTreeShaking = this.options.noTreeShaking; var noTreeShaking = this.options.noTreeShaking;
var isEntry = source.isEntry; var isEntry = source.isEntry;
var startFunctionBody = this.startFunctionBody; var startFunctionBody = this.startFunctionBody;
@ -451,35 +455,36 @@ export class Compiler extends DiagnosticEmitter {
// globals // globals
compileGlobalDeclaration(declaration: VariableDeclaration): Global | null { compileGlobalDeclaration(declaration: VariableDeclaration): Global | null {
// look up the initialized program element
var element = this.program.elements.get(declaration.fileLevelInternalName); var element = this.program.elements.get(declaration.fileLevelInternalName);
if (!element || element.kind != ElementKind.GLOBAL) { if (!element || element.kind != ElementKind.GLOBAL) throw new Error("global expected");
throw new Error("global expected"); if (!this.compileGlobal(<Global>element)) return null; // reports
}
if (!this.compileGlobal(<Global>element)) { // reports
return null;
}
return <Global>element; return <Global>element;
} }
compileGlobal(global: Global): bool { compileGlobal(global: Global): bool {
if (global.is(ElementFlags.COMPILED) || global.is(ElementFlags.BUILTIN)) { if (global.is(ElementFlags.COMPILED) || global.is(ElementFlags.BUILTIN)) return true;
return true; global.set(ElementFlags.COMPILED); // ^ built-ins are compiled on use
}
var declaration = global.declaration; var declaration = global.declaration;
var initExpr: ExpressionRef = 0; var initExpr: ExpressionRef = 0;
if (global.type == Type.void) { // infer type
if (global.type == Type.void) { // type is void if not yet resolved or not annotated
// resolve now if annotated
if (declaration.type) { if (declaration.type) {
var resolvedType = this.program.resolveType(declaration.type); // reports var resolvedType = this.program.resolveType(declaration.type); // reports
if (!resolvedType) return false; if (!resolvedType) return false;
if (resolvedType == Type.void) { if (resolvedType == Type.void) {
this.error( this.error(
DiagnosticCode.Type_0_is_not_assignable_to_type_1, DiagnosticCode.Type_expected,
declaration.type.range, "*", resolvedType.toString() declaration.type.range
); );
return false; return false;
} }
global.type = resolvedType; global.type = resolvedType;
// infer from initializer if not annotated
} else if (declaration.initializer) { // infer type using void/NONE for literal inference } else if (declaration.initializer) { // infer type using void/NONE for literal inference
initExpr = this.compileExpression( // reports initExpr = this.compileExpression( // reports
declaration.initializer, declaration.initializer,
@ -494,6 +499,8 @@ export class Compiler extends DiagnosticEmitter {
return false; return false;
} }
global.type = this.currentType; global.type = this.currentType;
// must either be annotated or have an initializer
} else { } else {
this.error( this.error(
DiagnosticCode.Type_expected, DiagnosticCode.Type_expected,
@ -505,7 +512,10 @@ export class Compiler extends DiagnosticEmitter {
var nativeType = global.type.toNativeType(); var nativeType = global.type.toNativeType();
// handle imports
if (global.is(ElementFlags.DECLARED)) { if (global.is(ElementFlags.DECLARED)) {
// constant global
if (global.is(ElementFlags.CONSTANT)) { if (global.is(ElementFlags.CONSTANT)) {
this.module.addGlobalImport( this.module.addGlobalImport(
global.internalName, global.internalName,
@ -517,6 +527,8 @@ export class Compiler extends DiagnosticEmitter {
); );
global.set(ElementFlags.COMPILED); global.set(ElementFlags.COMPILED);
return true; return true;
// importing mutable globals is not supported in the MVP
} else { } else {
this.error( this.error(
DiagnosticCode.Operation_not_supported, DiagnosticCode.Operation_not_supported,
@ -526,16 +538,26 @@ export class Compiler extends DiagnosticEmitter {
return false; return false;
} }
// the MVP does not yet support initializer expressions other than constant values (and
// get_globals), hence such initializations must be performed in the start function for now.
var initializeInStart = false; var initializeInStart = false;
// inlined constant can be compiled as-is
if (global.is(ElementFlags.INLINED)) { if (global.is(ElementFlags.INLINED)) {
initExpr = this.compileInlineConstant(global, global.type, true); initExpr = this.compileInlineConstant(global, global.type, true);
} else { } else {
// evaluate initializer if present
if (declaration.initializer) { if (declaration.initializer) {
if (!initExpr) { if (!initExpr) {
initExpr = this.compileExpression(declaration.initializer, global.type); initExpr = this.compileExpression(declaration.initializer, global.type);
} }
// check if the initializer is constant
if (_BinaryenExpressionGetId(initExpr) != ExpressionId.Const) { if (_BinaryenExpressionGetId(initExpr) != ExpressionId.Const) {
// if a constant global, check if the initializer becomes constant after precompute
if (global.is(ElementFlags.CONSTANT)) { if (global.is(ElementFlags.CONSTANT)) {
initExpr = this.precomputeExpressionRef(initExpr); initExpr = this.precomputeExpressionRef(initExpr);
if (_BinaryenExpressionGetId(initExpr) != ExpressionId.Const) { if (_BinaryenExpressionGetId(initExpr) != ExpressionId.Const) {
@ -549,17 +571,22 @@ export class Compiler extends DiagnosticEmitter {
initializeInStart = true; initializeInStart = true;
} }
} }
// initialize to zero if there's no initializer
} else { } else {
initExpr = global.type.toNativeZero(this.module); initExpr = global.type.toNativeZero(this.module);
} }
} }
var internalName = global.internalName; var internalName = global.internalName;
if (initializeInStart) {
if (initializeInStart) { // initialize to mutable zero and set the actual value in start
this.module.addGlobal(internalName, nativeType, true, global.type.toNativeZero(this.module)); this.module.addGlobal(internalName, nativeType, true, global.type.toNativeZero(this.module));
var setExpr = this.module.createSetGlobal(internalName, initExpr); var setExpr = this.module.createSetGlobal(internalName, initExpr);
this.startFunctionBody.push(setExpr); this.startFunctionBody.push(setExpr);
} else {
} else { // compile as-is
if (global.is(ElementFlags.CONSTANT)) { if (global.is(ElementFlags.CONSTANT)) {
var exprType = _BinaryenExpressionGetType(initExpr); var exprType = _BinaryenExpressionGetType(initExpr);
switch (exprType) { switch (exprType) {
@ -590,18 +617,18 @@ export class Compiler extends DiagnosticEmitter {
default: default:
throw new Error("concrete type expected"); throw new Error("concrete type expected");
} }
global.set(ElementFlags.INLINED); global.set(ElementFlags.INLINED); // inline the value from now on
if (declaration.isTopLevel) { // might be re-exported if (declaration.isTopLevel) { // but keep the element if it might be re-exported
this.module.addGlobal(internalName, nativeType, !global.is(ElementFlags.CONSTANT), initExpr); this.module.addGlobal(internalName, nativeType, false, initExpr);
} }
if (declaration.range.source.isEntry && declaration.isTopLevelExport) { if (declaration.range.source.isEntry && declaration.isTopLevelExport) {
this.module.addGlobalExport(global.internalName, declaration.programLevelInternalName); this.module.addGlobalExport(global.internalName, declaration.programLevelInternalName);
} }
} else {
} else /* mutable */ {
this.module.addGlobal(internalName, nativeType, !global.is(ElementFlags.CONSTANT), initExpr); this.module.addGlobal(internalName, nativeType, !global.is(ElementFlags.CONSTANT), initExpr);
} }
} }
global.set(ElementFlags.COMPILED);
return true; return true;
} }
@ -615,8 +642,6 @@ export class Compiler extends DiagnosticEmitter {
compileEnum(element: Enum): bool { compileEnum(element: Enum): bool {
if (element.is(ElementFlags.COMPILED)) return true; if (element.is(ElementFlags.COMPILED)) return true;
// members might reference each other, triggering another compile
element.set(ElementFlags.COMPILED); element.set(ElementFlags.COMPILED);
this.currentEnum = element; this.currentEnum = element;
@ -711,6 +736,7 @@ export class Compiler extends DiagnosticEmitter {
// functions // functions
/** Compiles a function given its declaration. */
compileFunctionDeclaration( compileFunctionDeclaration(
declaration: FunctionDeclaration, declaration: FunctionDeclaration,
typeArguments: TypeNode[], typeArguments: TypeNode[],
@ -728,13 +754,14 @@ export class Compiler extends DiagnosticEmitter {
); );
} }
/** Resolves the specified type arguments prior to compiling the resulting function instance. */
compileFunctionUsingTypeArguments( compileFunctionUsingTypeArguments(
prototype: FunctionPrototype, prototype: FunctionPrototype,
typeArguments: TypeNode[], typeArguments: TypeNode[],
contextualTypeArguments: Map<string,Type> | null, contextualTypeArguments: Map<string,Type> | null,
reportNode: Node reportNode: Node
): Function | null { ): Function | null {
var instance = prototype.resolveInclTypeArguments( // reports var instance = prototype.resolveUsingTypeArguments( // reports
typeArguments, typeArguments,
contextualTypeArguments, contextualTypeArguments,
reportNode reportNode
@ -743,6 +770,7 @@ export class Compiler extends DiagnosticEmitter {
return this.compileFunction(instance) ? instance : null; return this.compileFunction(instance) ? instance : null;
} }
/** Compiles a readily resolved function instance. */
compileFunction(instance: Function): bool { compileFunction(instance: Function): bool {
if (instance.is(ElementFlags.COMPILED)) return true; if (instance.is(ElementFlags.COMPILED)) return true;
@ -1064,7 +1092,7 @@ export class Compiler extends DiagnosticEmitter {
contextualTypeArguments: Map<string,Type> | null = null, contextualTypeArguments: Map<string,Type> | null = null,
alternativeReportNode: Node | null = null alternativeReportNode: Node | null = null
): void { ): void {
var instance = prototype.resolveInclTypeArguments( // reports var instance = prototype.resolveUsingTypeArguments( // reports
typeArguments, typeArguments,
contextualTypeArguments, contextualTypeArguments,
alternativeReportNode alternativeReportNode
@ -3029,6 +3057,14 @@ export class Compiler extends DiagnosticEmitter {
); );
break; break;
case TypeKind.F32:
case TypeKind.F64:
this.error(
DiagnosticCode.The_0_operator_cannot_be_applied_to_type_1,
expression.range, Token.operatorToString(expression.operator), this.currentType.toString()
);
return this.module.createUnreachable();
case TypeKind.VOID: case TypeKind.VOID:
this.error( this.error(
DiagnosticCode.Operation_not_supported, DiagnosticCode.Operation_not_supported,
@ -3097,6 +3133,14 @@ export class Compiler extends DiagnosticEmitter {
); );
break; break;
case TypeKind.F32:
case TypeKind.F64:
this.error(
DiagnosticCode.The_0_operator_cannot_be_applied_to_type_1,
expression.range, Token.operatorToString(expression.operator), this.currentType.toString()
);
return this.module.createUnreachable();
case TypeKind.VOID: case TypeKind.VOID:
this.error( this.error(
DiagnosticCode.Operation_not_supported, DiagnosticCode.Operation_not_supported,
@ -3780,37 +3824,21 @@ export class Compiler extends DiagnosticEmitter {
if (!resolved) return this.module.createUnreachable(); if (!resolved) return this.module.createUnreachable();
var element = resolved.element; var element = resolved.element;
if (element.kind != ElementKind.FUNCTION_PROTOTYPE) { var functionPrototype: FunctionPrototype;
this.error( var functionInstance: Function | null;
DiagnosticCode.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, switch (element.kind) {
expression.range, element.internalName
);
return this.module.createUnreachable();
}
var functionPrototype = <FunctionPrototype>element; // direct function call
var functionInstance: Function | null = null; case ElementKind.FUNCTION_PROTOTYPE:
functionPrototype = <FunctionPrototype>element;
// TODO: generalize?
if (functionPrototype.is(ElementFlags.BUILTIN)) { if (functionPrototype.is(ElementFlags.BUILTIN)) {
var resolvedTypeArguments: Type[] | null = null; let expr = compileBuiltinCall( // reports
if (expression.typeArguments) {
var k = expression.typeArguments.length;
resolvedTypeArguments = new Array<Type>(k);
for (var i = 0; i < k; ++i) {
var resolvedType = this.program.resolveType( // reports
expression.typeArguments[i],
this.currentFunction.contextualTypeArguments,
true
);
if (!resolvedType) return this.module.createUnreachable();
resolvedTypeArguments[i] = resolvedType;
}
}
var expr = compileBuiltinCall(
this, this,
functionPrototype, functionPrototype,
resolvedTypeArguments, functionPrototype.resolveBuiltinTypeArguments(
expression.typeArguments,
this.currentFunction.contextualTypeArguments
),
expression.arguments, expression.arguments,
contextualType, contextualType,
expression expression
@ -3823,32 +3851,39 @@ export class Compiler extends DiagnosticEmitter {
return this.module.createUnreachable(); return this.module.createUnreachable();
} }
return expr; return expr;
} } else {
functionInstance = functionPrototype.resolveUsingTypeArguments( // reports
// TODO: infer type arguments from parameter types if omitted
functionInstance = functionPrototype.resolveInclTypeArguments( // reports
expression.typeArguments, expression.typeArguments,
this.currentFunction.contextualTypeArguments, this.currentFunction.contextualTypeArguments,
expression expression
); );
if (!functionInstance) return this.module.createUnreachable(); if (!functionInstance) return this.module.createUnreachable();
}
break;
// TODO: generalize? (see above) // indirect function call
/* if (functionInstance.is(ElementFlags.BUILTIN)) { // TODO: currently these are bound to distinct functions, not types.
var expr = compileBuiltinCall( case ElementKind.LOCAL:
this, case ElementKind.GLOBAL:
functionPrototype, case ElementKind.FIELD:
functionInstance.typeArguments, if ((<VariableLikeElement>element).type.isFunction) {
expression.arguments, functionInstance = <Function>(<VariableLikeElement>element).type.functionType;
contextualType, } else {
expression this.error(
DiagnosticCode.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures,
expression.range, (<VariableLikeElement>element).type.toString()
);
return this.module.createUnreachable();
}
break;
default:
this.error(
DiagnosticCode.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures,
expression.range, element.internalName
); );
if (!expr) {
this.error(DiagnosticCode.Operation_not_supported, expression.range);
return this.module.createUnreachable(); return this.module.createUnreachable();
} }
return expr;
} */
var numArguments = expression.arguments.length; var numArguments = expression.arguments.length;
var numArgumentsInclThis = functionInstance.instanceMethodOf var numArgumentsInclThis = functionInstance.instanceMethodOf
@ -3861,7 +3896,7 @@ export class Compiler extends DiagnosticEmitter {
assert(resolved.targetExpression != null); assert(resolved.targetExpression != null);
args[argumentIndex++] = <Expression>resolved.targetExpression; args[argumentIndex++] = <Expression>resolved.targetExpression;
} }
for (i = 0; i < numArguments; ++i) { for (var i = 0; i < numArguments; ++i) {
args[argumentIndex++] = expression.arguments[i]; args[argumentIndex++] = expression.arguments[i];
} }
return this.compileCall(functionInstance, args, expression); return this.compileCall(functionInstance, args, expression);
@ -4413,7 +4448,7 @@ export class Compiler extends DiagnosticEmitter {
if (resolved) { if (resolved) {
if (resolved.element.kind == ElementKind.CLASS_PROTOTYPE) { if (resolved.element.kind == ElementKind.CLASS_PROTOTYPE) {
var prototype = <ClassPrototype>resolved.element; var prototype = <ClassPrototype>resolved.element;
var instance = prototype.resolveInclTypeArguments( // reports var instance = prototype.resolveUsingTypeArguments( // reports
expression.typeArguments, expression.typeArguments,
null, null,
expression expression

View File

@ -1347,7 +1347,7 @@ export class Program extends DiagnosticEmitter {
if ((element = this.elements.get(localName)) || (element = this.elements.get(globalName))) { if ((element = this.elements.get(localName)) || (element = this.elements.get(globalName))) {
switch (element.kind) { switch (element.kind) {
case ElementKind.CLASS_PROTOTYPE: case ElementKind.CLASS_PROTOTYPE:
var instance = (<ClassPrototype>element).resolveInclTypeArguments( var instance = (<ClassPrototype>element).resolveUsingTypeArguments(
node.typeArguments, node.typeArguments,
contextualTypeArguments, contextualTypeArguments,
null null
@ -1402,7 +1402,7 @@ export class Program extends DiagnosticEmitter {
return null; return null;
} }
/** Resolves an array of type parameters to concrete types. */ /** Resolves an array of type arguments to concrete types. */
resolveTypeArguments( resolveTypeArguments(
typeParameters: TypeParameter[], typeParameters: TypeParameter[],
typeArgumentNodes: TypeNode[] | null, typeArgumentNodes: TypeNode[] | null,
@ -1511,7 +1511,10 @@ export class Program extends DiagnosticEmitter {
): ResolvedElement | null { ): ResolvedElement | null {
// start by resolving the lhs target (expression before the last dot) // start by resolving the lhs target (expression before the last dot)
var targetExpression = propertyAccess.expression; var targetExpression = propertyAccess.expression;
resolvedElement = this.resolveExpression(targetExpression, contextualFunction); // reports resolvedElement = this.resolveExpression( // reports
targetExpression,
contextualFunction
);
if (!resolvedElement) return null; if (!resolvedElement) return null;
var target = resolvedElement.element; var target = resolvedElement.element;
@ -1592,10 +1595,16 @@ export class Program extends DiagnosticEmitter {
return null; return null;
} }
resolveElementAccess(elementAccess: ElementAccessExpression, contextualFunction: Function): ResolvedElement | null { resolveElementAccess(
elementAccess: ElementAccessExpression,
contextualFunction: Function
): ResolvedElement | null {
// start by resolving the lhs target (expression before the last dot) // start by resolving the lhs target (expression before the last dot)
var targetExpression = elementAccess.expression; var targetExpression = elementAccess.expression;
resolvedElement = this.resolveExpression(targetExpression, contextualFunction); resolvedElement = this.resolveExpression(
targetExpression,
contextualFunction
);
if (!resolvedElement) return null; if (!resolvedElement) return null;
var target = resolvedElement.element; var target = resolvedElement.element;
switch (target.kind) { switch (target.kind) {
@ -1625,7 +1634,10 @@ export class Program extends DiagnosticEmitter {
return null; return null;
} }
resolveExpression(expression: Expression, contextualFunction: Function): ResolvedElement | null { resolveExpression(
expression: Expression,
contextualFunction: Function
): ResolvedElement | null {
var classType: Class | null; var classType: Class | null;
while (expression.kind == NodeKind.PARENTHESIZED) { while (expression.kind == NodeKind.PARENTHESIZED) {
@ -1672,17 +1684,26 @@ export class Program extends DiagnosticEmitter {
return this.resolveIdentifier(<IdentifierExpression>expression, contextualFunction); return this.resolveIdentifier(<IdentifierExpression>expression, contextualFunction);
case NodeKind.PROPERTYACCESS: case NodeKind.PROPERTYACCESS:
return this.resolvePropertyAccess(<PropertyAccessExpression>expression, contextualFunction); return this.resolvePropertyAccess(
<PropertyAccessExpression>expression,
contextualFunction
);
case NodeKind.ELEMENTACCESS: case NodeKind.ELEMENTACCESS:
return this.resolveElementAccess(<ElementAccessExpression>expression, contextualFunction); return this.resolveElementAccess(
<ElementAccessExpression>expression,
contextualFunction
);
case NodeKind.CALL: case NodeKind.CALL:
var resolved = this.resolveExpression((<CallExpression>expression).expression, contextualFunction); var resolved = this.resolveExpression(
(<CallExpression>expression).expression,
contextualFunction
);
if (resolved) { if (resolved) {
var element = resolved.element; var element = resolved.element;
if (element && element.kind == ElementKind.FUNCTION_PROTOTYPE) { if (element && element.kind == ElementKind.FUNCTION_PROTOTYPE) {
var instance = (<FunctionPrototype>element).resolveInclTypeArguments( var instance = (<FunctionPrototype>element).resolveUsingTypeArguments(
(<CallExpression>expression).typeArguments, (<CallExpression>expression).typeArguments,
null, null,
expression expression
@ -2130,6 +2151,7 @@ export class FunctionPrototype extends Element {
} }
} }
/** Resolves this prototype to an instance using the specified concrete type arguments. */
resolve( resolve(
functionTypeArguments: Type[] | null = null, functionTypeArguments: Type[] | null = null,
contextualTypeArguments: Map<string,Type> | null = null contextualTypeArguments: Map<string,Type> | null = null
@ -2226,7 +2248,28 @@ export class FunctionPrototype extends Element {
return instance; return instance;
} }
resolveInclTypeArguments( /** Resolves this prototype partially by applying the specified inherited class type arguments. */
resolvePartial(classTypeArguments: Type[] | null): FunctionPrototype | null {
if (!this.classPrototype) {
throw new Error("partially resolved instance method must reference its class prototype");
}
if (classTypeArguments && classTypeArguments.length) {
var partialPrototype = new FunctionPrototype(
this.program,
this.simpleName,
this.internalName,
this.declaration,
this.classPrototype
);
partialPrototype.flags = this.flags;
partialPrototype.classTypeArguments = classTypeArguments;
return partialPrototype;
}
return this; // no need to clone
}
/** Resolves the specified type arguments prior to resolving this prototype to an instance. */
resolveUsingTypeArguments(
typeArgumentNodes: TypeNode[] | null, typeArgumentNodes: TypeNode[] | null,
contextualTypeArguments: Map<string,Type> | null, contextualTypeArguments: Map<string,Type> | null,
reportNode: Node reportNode: Node
@ -2245,23 +2288,27 @@ export class FunctionPrototype extends Element {
return this.resolve(resolvedTypeArguments, contextualTypeArguments); return this.resolve(resolvedTypeArguments, contextualTypeArguments);
} }
resolvePartial(classTypeArguments: Type[] | null): FunctionPrototype | null { /** Resolves the type arguments to use when compiling a built-in call. Must be a built-in. */
if (!this.classPrototype) { resolveBuiltinTypeArguments(
throw new Error("partially resolved instance method must reference its class prototype"); typeArgumentNodes: TypeNode[] | null,
} contextualTypeArguments: Map<string,Type> | null
if (classTypeArguments && classTypeArguments.length) { ): Type[] | null {
var partialPrototype = new FunctionPrototype( assert(this.is(ElementFlags.BUILTIN));
this.program, var resolvedTypeArguments: Type[] | null = null;
this.simpleName, if (typeArgumentNodes) {
this.internalName, var k = typeArgumentNodes.length;
this.declaration, resolvedTypeArguments = new Array<Type>(k);
this.classPrototype for (var i = 0; i < k; ++i) {
var resolvedType = this.program.resolveType( // reports
typeArgumentNodes[i],
contextualTypeArguments,
true
); );
partialPrototype.flags = this.flags; if (!resolvedType) return null;
partialPrototype.classTypeArguments = classTypeArguments; resolvedTypeArguments[i] = resolvedType;
return partialPrototype;
} }
return this; // no need to clone }
return resolvedTypeArguments;
} }
toString(): string { return this.simpleName; } toString(): string { return this.simpleName; }
@ -2650,7 +2697,11 @@ export class ClassPrototype extends Element {
} }
} }
resolve(typeArguments: Type[] | null, contextualTypeArguments: Map<string,Type> | null = null): Class | null { /** Resolves this prototype to an instance using the specified concrete type arguments. */
resolve(
typeArguments: Type[] | null,
contextualTypeArguments: Map<string,Type> | null = null
): Class | null {
var instanceKey = typeArguments ? typesToString(typeArguments) : ""; var instanceKey = typeArguments ? typesToString(typeArguments) : "";
var instance = this.instances.get(instanceKey); var instance = this.instances.get(instanceKey);
if (instance) return instance; if (instance) return instance;
@ -2790,7 +2841,8 @@ export class ClassPrototype extends Element {
return instance; return instance;
} }
resolveInclTypeArguments( /** Resolves the specified type arguments prior to resolving this prototype to an instance. */
resolveUsingTypeArguments(
typeArgumentNodes: TypeNode[] | null, typeArgumentNodes: TypeNode[] | null,
contextualTypeArguments: Map<string,Type> | null, contextualTypeArguments: Map<string,Type> | null,
alternativeReportNode: Node | null alternativeReportNode: Node | null

View File

@ -5,11 +5,24 @@
(elem (i32.const 0) $start~anonymous|0 $start~anonymous|0 $start~someName|2) (elem (i32.const 0) $start~anonymous|0 $start~anonymous|0 $start~someName|2)
(memory $0 1) (memory $0 1)
(export "memory" (memory $0)) (export "memory" (memory $0))
(start $start~someName|2) (start $start)
(func $start~anonymous|0 (; 0 ;) (type $ii) (param $0 i32) (result i32) (func $start~anonymous|0 (; 0 ;) (type $ii) (param $0 i32) (result i32)
(get_local $0) (get_local $0)
) )
(func $start~someName|2 (; 1 ;) (type $v) (func $start~someName|2 (; 1 ;) (type $v)
(nop) (nop)
) )
(func $start (; 2 ;) (type $v)
(drop
(call $start~anonymous|0
(i32.const 1)
)
)
(drop
(call $start~anonymous|0
(i32.const 2)
)
)
(call $start~someName|2)
)
) )

View File

@ -1,11 +1,11 @@
var f1 = function(a: i32): i32 { var f1 = function(a: i32): i32 {
return a; return a;
}; };
f1; f1(1);
var f2 = (a: i32): i32 => { var f2 = (a: i32): i32 => {
return a; return a;
}; };
f2; f2(2);
var f3 = function someName(): void { var f3 = function someName(): void {
}; };
f3; f3();

View File

@ -24,13 +24,15 @@
) )
(func $start (; 3 ;) (type $v) (func $start (; 3 ;) (type $v)
(drop (drop
(get_global $function-expression/f1) (call $start~anonymous|0
(i32.const 1)
)
) )
(drop (drop
(get_global $function-expression/f2) (call $start~anonymous|1
) (i32.const 2)
(drop
(get_global $function-expression/f3)
) )
) )
(call $start~someName|2)
)
) )

View File

@ -4,7 +4,6 @@ const webpack = require("webpack");
// Build the C-like library // Build the C-like library
const lib = { const lib = {
mode: "production",
entry: [ "./src/glue/js", "./src/index.ts" ], entry: [ "./src/glue/js", "./src/index.ts" ],
module: { module: {
rules: [ rules: [
@ -23,10 +22,8 @@ const lib = {
filename: "assemblyscript.js", filename: "assemblyscript.js",
path: path.resolve(__dirname, "dist"), path: path.resolve(__dirname, "dist"),
library: "assemblyscript", library: "assemblyscript",
libraryTarget: "umd" libraryTarget: "umd",
}, globalObject: "typeof self !== 'undefined' ? self : this"
optimization: {
minimize: true
}, },
devtool: "source-map", devtool: "source-map",
performance: { performance: {
@ -36,16 +33,10 @@ const lib = {
// Build asc for browser usage // Build asc for browser usage
const bin = { const bin = {
mode: "production",
context: path.join(__dirname, "bin"), context: path.join(__dirname, "bin"),
entry: [ "./asc.js" ], entry: [ "./asc.js" ],
externals: [{ externals: [{
"../dist/assemblyscript.js": { "../dist/assemblyscript.js": "assemblyscript"
commonjs: "assemblyscript",
commonjs2: "assemblyscript",
amd: "assemblyscript",
root: "_"
}
}], }],
node: { node: {
"fs": "empty", "fs": "empty",
@ -57,10 +48,8 @@ const bin = {
filename: "asc.js", filename: "asc.js",
path: path.resolve(__dirname, "dist"), path: path.resolve(__dirname, "dist"),
library: "asc", library: "asc",
libraryTarget: "umd" libraryTarget: "umd",
}, globalObject: "typeof self !== 'undefined' ? self : this"
optimization: {
minimize: true
}, },
devtool: "source-map", devtool: "source-map",
plugins: [ plugins: [
@ -79,7 +68,7 @@ const bin = {
}, },
__dirname: JSON.stringify(".") __dirname: JSON.stringify(".")
}), }),
new webpack.IgnorePlugin(/\.\/src|package\.json|^(\.\/assemblyscript|ts\-node|glob|source\-map\-support)$/), new webpack.IgnorePlugin(/\.\/src|package\.json|^(ts\-node|glob|source\-map\-support)$/),
] ]
}; };