summaryrefslogtreecommitdiff
path: root/godel/js/main.js
diff options
context:
space:
mode:
authorElizabeth (Lizzy) Hunt <elizabeth.hunt@simponic.xyz>2023-11-17 12:13:30 -0700
committerGitHub <noreply@github.com>2023-11-17 12:13:30 -0700
commiteaca9073ebf8a438ec8474f15171a62082fa141b (patch)
tree371b06e288a85c14fccd785008c7abfe586a6471 /godel/js/main.js
parent1aefa0f9b1da1c7bb99f7605c334eaf691ba2fda (diff)
parent57a4d439847bf3d63513b2443dfdf1eca5ecbb02 (diff)
downloadsimponic.xyz-eaca9073ebf8a438ec8474f15171a62082fa141b.tar.gz
simponic.xyz-eaca9073ebf8a438ec8474f15171a62082fa141b.zip
Merge pull request #3 from Simponic/godel
L-Program and Godel Numbers
Diffstat (limited to 'godel/js/main.js')
-rw-r--r--godel/js/main.js175
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,
+ });
+});