Add build script and system impls

The syscaps are yanked from <https://playful-crisp-e8c688.netlify.app/>
(which is itself a remix of the triplescripts.org lines.app.htm demo)
and then modified.

This works well enough to run on the data located at tests/bs/256.bin.
This commit is contained in:
Colby Russell committed 2026-09-24 15:58:08 -05:00
1 parent 8c307c6024
commit a074211e5d
6 files changed
+5897

No files matched your search

+5685
View File
File diff suppressed because it is too large. Load diff
+13
View File
@@ -1 +1,14 @@
xxd in the browser. (Default behavior only.)
Building
========
Using `Build.app.htm` (for example, after double clicking it and then pointing
it at the project source tree), build trplkt by running the following command:
build ./main.src
(If you prefer to do the build from the terminal, you can also do so using
NodeJS; you'd type `node ./Build.app.htm $BUILDCOMMAND`, where `$BUILDCOMMAND`
is the command given above.)
+23
View File
@@ -0,0 +1,23 @@
import { XXD } from "./src/XXD.src"
import { SystemB } from "./src/SystemB.src"
import { SystemC } from "./src/SystemC.src"
void function main() {
if (!system) var system = SystemA.init(SystemB);
if (!system) var system = SystemA.init(SystemC);
if (!system) {
throw new Error("Unknown environment");
}
system.setUpForExec({
run: function(system, path) {
return system.read(path).then((contents) => {
let xxd = (new XXD(contents));
xxd.exec();
system.print(xxd.output);
});
}
});
} ()
+22
View File
@@ -0,0 +1,22 @@
export
class SystemA {
run() {
throw new Error("unimplemented!");
}
read(path) {
throw new Error("unimplemented!");
}
print(bytes) {
throw new Error("unimplemented!");
}
static init($kind) {
try {
return new $kind;
} catch (ex) {
return null;
}
}
}
+79
View File
@@ -0,0 +1,79 @@
import { SystemA } from "./SystemA.src"
export
class SystemB extends SystemA {
constructor() {
super();
if (typeof(window) == "undefined") {
throw new Error("Not a browser environment");
}
this._page = window.document.body;
this._app = null;
this._file = null;
this._fileInput = null;
}
setUpForExec(app) {
this._app = app;
this._page.onload = (() => {
this._page.innerHTML = "";
this._page.style.fontFamily = "monospace";
this._page.style.whiteSpace = "pre-wrap";
let doc = this._page.ownerDocument;
let $$ = doc.createElement.bind(doc);
let button = $$("input");
button.type = "button";
button.value = "Load\u2026";
button.style.float = "right";
button.onclick = () => void(this._fileInput.click());
this._page.appendChild(button);
let fileInput = $$("input");
fileInput.type = "file";
fileInput.style.display = "none";
fileInput.onchange = this._onFileSelected.bind(this);
this._fileInput = this._page.appendChild(fileInput);
this._page.appendChild($$("div")).id = "container";
})
}
_onFileSelected(event) {
this._file = event.target.files[0];
let path = this._file.webkitRelativePath;
this._app.run(this, path);
}
read(path) {
return new Promise((resolve, reject) => {
if (path == this._file.webkitRelativePath) {
if (typeof(FileReader) != "undefined") {
let reader = new FileReader();
reader.addEventListener("loadend", (event) => {
resolve(new Uint8Array(event.target.result));
});
return void(reader.readAsArrayBuffer(this._file));
}
return reject(Error("FileReader API not implemented"));
}
return reject(Error("Cannot read file with path: " + path));
});
}
print(output) {
var message = "";
for (let i = 0, n = output.length; i < n; i++) {
message += String.fromCharCode(output[i]);
}
this._page.textContent = message;
}
}
+75
View File
@@ -0,0 +1,75 @@
import { SystemA } from "./SystemA.src"
export
class SystemC extends SystemA {
constructor() {
super();
if (typeof(process) == "undefined") {
throw new Error("Not a NodeJS environment");
}
let [ engine, script, ...args ] = process.argv;
this.args = args;
this._nodeFS = process.mainModule.require("fs");
this._nodePath = process.mainModule.require("path");
const { FileNodeFSAdapter } = SystemC;
this._files = new FileNodeFSAdapter(this._nodeFS, this._nodePath);
}
setUpForExec(app) {
if (this.args.length == 1) {
return void(app.run(this, this.args[0]));
}
throw new Error("Expected file path");
}
read(path) {
return this._files.read(path, true);
}
print(output) {
var message = "";
for (let i = 0, n = output.length; i < n; i++) {
message += String.fromCharCode(output[i]);
}
if (typeof(console) != "undefined") {
console.log(message);
} else { // should not happen, but the typeof check is unavoidable
throw new Error("Cannot print message " + JSON.stringify(message));
}
}
}
SystemC.FileNodeFSAdapter = class FileNodeFSAdapter {
constructor(fs, path, workDir = ".") {
this._nodeFS = fs;
this._nodePath = path;
this._workDir = workDir;
}
read(path, raw) {
if (!path.startsWith("/")) {
path = this._nodePath.join(this._workDir, path);
}
if (!raw) {
var options = { encoding: "utf8" };
}
return new Promise((resolve, reject) => {
void this._nodeFS.readFile(path, options, (err, contents) => {
if (err) {
reject(err);
} else if (!raw) {
resolve(contents);
} else {
resolve(Uint8Array.from(contents));
}
});
});
}
}