diff options
Diffstat (limited to 'godel/js/main.js')
-rw-r--r-- | godel/js/main.js | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/godel/js/main.js b/godel/js/main.js new file mode 100644 index 0000000..9092d2c --- /dev/null +++ b/godel/js/main.js @@ -0,0 +1,175 @@ +const MESSAGES = { + COMPILE: "COMPILE", + COMPILE_RESULT: "COMPILE_RESULT", + EVAL: "EVAL", + EVAL_STATUS: "EVAL_RESULT", +}; + +// -- the "real" code -- + +const state = new Observable(); + +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); + + try { + const ast = parser.parse(source); + const { js, godelSequence } = compile(ast); + + state.notify({ + type: MESSAGES.COMPILE_RESULT, + success: true, + js, + godelSequence, + }); + } catch (e) { + console.error(e); + 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, + success: true, + value: result, + }); + } catch (e) { + state.notify({ + type: MESSAGES.EVAL_RESULT, + error: e.toString(), + }); + } + } + }); +}; +main(); + +// -- a bit of some hacky ui code -- + +const codeMirrorConfig = { + lineNumbers: true, +}; +const instructionsEl = document.getElementById("instructions"); +const instructionsEditorEl = CodeMirror.fromTextArea( + instructionsEl, + codeMirrorConfig +); + +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"); +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"); +const copyStateButton = document.getElementById("copy"); + +// hackily copy the program state and put it in the clipboard +copyStateButton.addEventListener("click", () => { + const instructions = btoa(instructionsEditorEl.getValue()); + + navigator.clipboard + .writeText( + window.location.href.split("?")[0] + `?instructions=${instructions}` + ) + .then(() => alert("copied to clipboard")); +}); + +state.subscribe((msg) => { + if (msg.type == MESSAGES.COMPILE_RESULT) { + evalStatusEl.classList.remove("error"); + evalStatusEl.classList.remove("success"); + evalStatusEl.innerHTML = ""; + + if (msg.success) { + const { js, godelSequence } = msg; + compiledEditorEl.setValue(js); + + godelSequenceEl.innerHTML = `[${godelSequence.join(", ")}]`; + godelNumberComputeBtn.style.display = "inline"; + + compileStatusEl.classList.add("success"); + compileStatusEl.classList.remove("error"); + compileStatusEl.innerHTML = `Successful compile at ${new Date().toLocaleString()}!`; + } else if (msg.error) { + compiledEditorEl.setValue(""); + godelSequenceEl.innerHTML = ""; + godelNumberEl.innerHTML = ""; + godelNumberComputeBtn.style.display = "none"; + + compileStatusEl.classList.remove("success"); + compileStatusEl.classList.add("error"); + compileStatusEl.innerHTML = msg.error; + } + } +}); + +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 = () => {}; + } + } +}); + +state.subscribe((msg) => { + if (msg.type == MESSAGES.EVAL_RESULT) { + if (msg.success) { + 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")) { + instructionsEditorEl.setValue(atob(urlParams.get("instructions"))); +} + +compileButton.addEventListener("click", () => { + state.notify({ + type: MESSAGES.COMPILE, + value: instructionsEditorEl.getValue(), + }); +}); + +evalButton.addEventListener("click", () => { + state.notify({ + type: MESSAGES.EVAL, + }); +}); |