mirror of
https://github.com/remko/waforth
synced 2024-12-28 10:00:06 +01:00
160 lines
4.6 KiB
JavaScript
Executable file
160 lines
4.6 KiB
JavaScript
Executable file
#!/usr/bin/env node
|
|
|
|
const fs = require("fs");
|
|
const process = require("process");
|
|
|
|
if (process.argv.length < 3) {
|
|
console.log("Expected input file");
|
|
process.exit(1);
|
|
}
|
|
const input = fs.readFileSync(process.argv[2]) + "";
|
|
|
|
const coreWasm = fs.readFileSync("../../src/waforth.wasm");
|
|
|
|
let core, table, memory, memory32;
|
|
const buffer = [];
|
|
const modules = [];
|
|
let tableSize = -1;
|
|
|
|
function run(s) {
|
|
const data = new TextEncoder().encode(s);
|
|
for (let i = data.length - 1; i >= 0; --i) {
|
|
buffer.push(data[i]);
|
|
}
|
|
return core.exports.interpret();
|
|
}
|
|
|
|
function latest() {
|
|
run("LATEST");
|
|
const result = memory32[core.exports.tos() / 4 - 1];
|
|
run("DROP");
|
|
return result;
|
|
}
|
|
|
|
function here() {
|
|
run("HERE");
|
|
const result = memory32[core.exports.tos() / 4 - 1];
|
|
run("DROP");
|
|
return result;
|
|
}
|
|
|
|
WebAssembly.instantiate(coreWasm, {
|
|
shell: {
|
|
emit: c => {
|
|
process.stdout.write(String.fromCharCode(c));
|
|
},
|
|
|
|
key: () => {
|
|
if (buffer.length === 0) {
|
|
return -1;
|
|
}
|
|
return buffer.pop();
|
|
},
|
|
|
|
debug: c => {
|
|
process.stderr.write(String.fromCharCode(c));
|
|
},
|
|
|
|
load: (offset, length, index) => {
|
|
let data = new Uint8Array(core.exports.memory.buffer, offset, length);
|
|
if (index >= table.length) {
|
|
table.grow(table.length);
|
|
}
|
|
tableSize = index + 1;
|
|
var module = new WebAssembly.Module(data);
|
|
modules.push(new Uint8Array(Array.from(data)));
|
|
new WebAssembly.Instance(module, {
|
|
env: { table, memory, tos: -1 }
|
|
});
|
|
}
|
|
}
|
|
}).then(instance => {
|
|
core = instance.instance;
|
|
table = core.exports.table;
|
|
memory = core.exports.memory;
|
|
memory32 = new Int32Array(core.exports.memory.buffer, 0, 0x30000);
|
|
const memory8 = new Uint8Array(core.exports.memory.buffer, 0, 0x30000);
|
|
|
|
const dictionaryStart = latest();
|
|
|
|
// Load prelude
|
|
core.exports.loadPrelude();
|
|
|
|
// Load code
|
|
run(input);
|
|
|
|
const savedLatest = latest();
|
|
const savedHere = here();
|
|
|
|
////////////////////////////////////////////////////////////
|
|
// Generate build files
|
|
////////////////////////////////////////////////////////////
|
|
|
|
if (!fs.existsSync("waforth.gen")) {
|
|
fs.mkdirSync("waforth.gen");
|
|
}
|
|
|
|
const make = [
|
|
"waforth.gen/waforth_module_%.c waforth.gen/waforth_module_%.h: waforth.gen/waforth_module_%.wasm",
|
|
"\twasm2c $< -o $(subst .wasm,.c,$<)",
|
|
"",
|
|
"waforth.gen/waforth_module_%.wasm: waforth.gen/waforth_module_%.in.wasm",
|
|
"\twasm-dis $< -o $(subst .wasm,.wat,$@)",
|
|
"\twasm-as $(subst .wasm,.wat,$@) -o $@",
|
|
""
|
|
];
|
|
const include = [
|
|
"#pragma once",
|
|
"",
|
|
"#define WAFORTH_LATEST " + savedLatest + "\n",
|
|
"#define WAFORTH_HERE " + savedHere + "\n",
|
|
"#define WAFORTH_TABLE_SIZE " + tableSize + "\n",
|
|
"void waforth_modules_init();",
|
|
"#undef WASM_RT_MODULE_PREFIX"
|
|
];
|
|
const init = [
|
|
'#include "waforth_modules.h"',
|
|
"void waforth_modules_init() {"
|
|
];
|
|
for (let i = dictionaryStart; i < savedHere; ++i) {
|
|
init.push("Z_envZ_memory->data[" + i + "] = " + memory8[i] + ";\n");
|
|
}
|
|
const objects = ["waforth.gen/waforth_modules.o"];
|
|
const moduleHeaders = [];
|
|
const moduleSources = [];
|
|
for (let i = 0; i < modules.length; ++i) {
|
|
fs.writeFileSync(
|
|
"waforth.gen/waforth_module_" + i + ".in.wasm",
|
|
modules[i]
|
|
);
|
|
make.push(
|
|
"waforth.gen/waforth_module_" +
|
|
i +
|
|
".o: waforth.gen/waforth_module_" +
|
|
i +
|
|
".c"
|
|
);
|
|
make.push(
|
|
"\t$(CC) $(CPPFLAGS) $(CFLAGS) -DWASM_RT_MODULE_PREFIX=waforth_module_" +
|
|
i +
|
|
"_ -c $< -o $@"
|
|
);
|
|
make.push("");
|
|
include.push("#define WASM_RT_MODULE_PREFIX waforth_module_" + i + "_");
|
|
include.push('#include "waforth.gen/waforth_module_' + i + '.h"');
|
|
include.push("#undef WASM_RT_MODULE_PREFIX");
|
|
init.push("waforth_module_" + i + "_init();");
|
|
objects.push("waforth.gen/waforth_module_" + i + ".o");
|
|
moduleHeaders.push("waforth.gen/waforth_module_" + i + ".h");
|
|
moduleSources.push("waforth.gen/waforth_module_" + i + ".c");
|
|
}
|
|
include.push("#define WASM_RT_MODULE_PREFIX");
|
|
make.push("WAFORTH_MODULE_OBJECTS = " + objects.join(" ") + "\n");
|
|
make.push("WAFORTH_MODULE_HEADERS = " + moduleHeaders.join(" ") + "\n");
|
|
make.push("WAFORTH_MODULE_SOURCES = " + moduleSources.join(" ") + "\n");
|
|
make.push("waforth.gen/waforth_modules.h: $(WAFORTH_MODULE_HEADERS)");
|
|
init.push("}");
|
|
fs.writeFileSync("waforth.gen/Makefile.inc", make.join("\n") + "\n");
|
|
fs.writeFileSync("waforth.gen/waforth_modules.h", include.join("\n") + "\n");
|
|
fs.writeFileSync("waforth.gen/waforth_modules.c", init.join("\n") + "\n");
|
|
});
|