simponic.xyz/godel/js/main.js

164 lines
4.4 KiB
JavaScript
Raw Normal View History

2023-11-16 21:06:35 -05:00
const MESSAGES = {
COMPILE: "COMPILE",
COMPILE_RESULT: "COMPILE_RESULT",
EVAL: "EVAL",
EVAL_STATUS: "EVAL_RESULT",
};
2023-11-16 16:56:56 -05:00
2023-11-16 21:06:35 -05:00
// -- the "real" code --
2023-11-16 16:56:56 -05:00
const state = new Observable();
2023-11-16 21:06:35 -05:00
const prepareSource = (text) => text.replaceAll(/\/\/.*/g, "").trim();
const main = () => {
let program;
state.subscribe((msg) => {
if (msg.type == MESSAGES.COMPILE) {
const { value } = msg;
const source = prepareSource(value);
2023-11-17 14:09:44 -05:00
2023-11-16 21:06:35 -05:00
try {
const ast = parser.parse(source);
2023-11-17 14:09:44 -05:00
const { js, godelSequence } = compile(ast);
2023-11-16 21:06:35 -05:00
state.notify({
type: MESSAGES.COMPILE_RESULT,
2023-11-17 14:09:44 -05:00
success: true,
js,
godelSequence,
2023-11-16 21:06:35 -05:00
});
} catch (e) {
2023-11-17 14:09:44 -05:00
console.error(e);
2023-11-16 21:06:35 -05:00
state.notify({
type: MESSAGES.COMPILE_RESULT,
error: e.toString(),
});
}
}
if (msg.type == MESSAGES.EVAL) {
const source = compiledEditorEl.getValue();
try {
const result = eval(source);
state.notify({
type: MESSAGES.EVAL_RESULT,
2023-11-17 14:09:44 -05:00
success: true,
2023-11-16 21:06:35 -05:00
value: result,
});
} catch (e) {
state.notify({
type: MESSAGES.EVAL_RESULT,
error: e.toString(),
});
}
}
});
};
main();
// -- a bit of some hacky ui code --
2023-11-17 14:09:44 -05:00
const codeMirrorConfig = {
2023-11-16 21:06:35 -05:00
lineNumbers: true,
2023-11-17 14:09:44 -05:00
};
const instructionsEl = document.getElementById("instructions");
const instructionsEditorEl = CodeMirror.fromTextArea(
instructionsEl,
codeMirrorConfig
);
2023-11-16 21:06:35 -05:00
const compileButton = document.getElementById("compile");
const evalButton = document.getElementById("eval");
const evalStatusEl = document.getElementById("eval_status");
const compileStatusEl = document.getElementById("compile_status");
const compiledEl = document.getElementById("compiled");
2023-11-17 14:09:44 -05:00
const compiledEditorEl = CodeMirror.fromTextArea(compiledEl, codeMirrorConfig);
const godelSequenceEl = document.getElementById("godel_sequence");
const godelNumberEl = document.getElementById("godel_number");
const godelNumberComputeBtn = document.getElementById("godel_number_comp");
2023-11-16 21:06:35 -05:00
state.subscribe((msg) => {
if (msg.type == MESSAGES.COMPILE_RESULT) {
evalStatusEl.classList.remove("error");
evalStatusEl.classList.remove("success");
evalStatusEl.innerHTML = "";
2023-11-17 14:09:44 -05:00
if (msg.success) {
const { js, godelSequence } = msg;
compiledEditorEl.setValue(js);
godelSequenceEl.innerHTML = `[${godelSequence.join(", ")}]`;
godelNumberComputeBtn.style.display = "inline";
2023-11-16 21:06:35 -05:00
compileStatusEl.classList.add("success");
compileStatusEl.classList.remove("error");
compileStatusEl.innerHTML = `Successful compile at ${new Date().toLocaleString()}!`;
} else if (msg.error) {
compiledEditorEl.setValue("");
2023-11-17 14:09:44 -05:00
godelSequenceEl.innerHTML = "";
godelNumberEl.innerHTML = "";
godelNumberComputeBtn.style.display = "none";
2023-11-16 21:06:35 -05:00
compileStatusEl.classList.remove("success");
compileStatusEl.classList.add("error");
compileStatusEl.innerHTML = msg.error;
}
}
});
2023-11-17 14:09:44 -05:00
state.subscribe((msg) => {
if (msg.type == MESSAGES.COMPILE_RESULT) {
if (msg.success) {
const { godelSequence } = msg;
godelNumberComputeBtn.onclick = () => {
godelNumberEl.innerHTML = "working...";
const worker = new Worker("js/godelWorker.js");
worker.addEventListener("message", (e) => {
const godelNumber = e.data;
godelNumberEl.innerHTML = godelNumber.toString();
});
worker.postMessage(godelSequence);
};
} else if (msg.error) {
godelNumberComputeBtn.onclick = () => {};
}
}
});
2023-11-16 21:06:35 -05:00
state.subscribe((msg) => {
if (msg.type == MESSAGES.EVAL_RESULT) {
2023-11-17 14:09:44 -05:00
if (msg.success) {
2023-11-16 21:06:35 -05:00
evalStatusEl.classList.add("success");
evalStatusEl.classList.remove("error");
evalStatusEl.innerHTML = `Result: ${msg.value}`;
} else if (msg.error) {
evalStatusEl.classList.remove("success");
evalStatusEl.classList.add("error");
evalStatusEl.innerHTML = msg.error;
}
}
});
const urlParams = new URLSearchParams(window.location.search);
if (urlParams.get("instructions")) {
editorEl.setValue(atob(urlParams.get("instructions")));
}
compileButton.addEventListener("click", () => {
state.notify({
type: MESSAGES.COMPILE,
value: instructionsEditorEl.getValue(),
});
});
evalButton.addEventListener("click", () => {
state.notify({
type: MESSAGES.EVAL,
});
});