/* Copyright (C) 2025 filifa This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ import { tokenize } from "./modules/lexer.js"; import { shunt } from "./modules/parser.js"; function evaluate() { const expr = document.querySelector("#expr"); const modulus = document.querySelector("#modulus"); const result = document.querySelector("#result"); const m = BigInt(modulus.value); if (m <= 0n) { const e = Error("invalid modulus") result.value = e; console.log(e); return; } const tokens = tokenize(expr.value); console.log(tokens); let queue = []; try { queue = shunt(tokens); } catch(e) { result.value = e; console.log(e); return; } console.log(queue); worker.postMessage({command: "compute", queue, m}); result.value = "calculating..."; } const expr = document.querySelector("#expr"); let selectionStart = 0; let selectionEnd = 0; function setupExprInput() { selectionStart = expr.selectionStart; selectionEnd = expr.selectionEnd; switchButtons(true); } function clear() { expr.value = ""; expr.focus(); } function keyPress(c) { expr.focus(); const begin = expr.value.slice(0, selectionStart); const end = expr.value.slice(selectionEnd); expr.value = begin + c + end; expr.setSelectionRange(selectionStart+c.length, selectionStart+c.length); } function backspace() { expr.focus(); if (selectionEnd === 0) { return; } let begin = null; if (selectionStart === selectionEnd) { begin = expr.value.slice(0, selectionStart-1); } else { begin = expr.value.slice(0, selectionStart); } const end = expr.value.slice(selectionEnd); expr.value = begin + end; if (selectionStart === 0) { expr.setSelectionRange(0, 0); } else if (selectionStart === selectionEnd) { expr.setSelectionRange(selectionStart-1, selectionStart-1); } else { expr.setSelectionRange(selectionStart, selectionStart); } } function evalOnEnter(e) { if (e.key === "Enter") { evaluate(); } } function switchButtons(enabled) { for (const btn of document.querySelectorAll("#main-buttons button")) { btn.disabled = !enabled; } for (const btn of document.querySelectorAll("#extra-buttons button")) { btn.disabled = !enabled; } } const worker = new Worker("./workers/compute.js"); worker.addEventListener("message", (message) => { document.querySelector("#result").value = message.data; }); document.querySelector("#expr").addEventListener("focus", setupExprInput); document.querySelector("#expr").addEventListener("keyup", (e) => evalOnEnter(e)); document.querySelector("#modulus").addEventListener("focus", () => switchButtons(false)); document.querySelector("#modulus").addEventListener("keyup", (e) => evalOnEnter(e)); document.querySelector("#zero").addEventListener("click", () => keyPress("0")); document.querySelector("#one").addEventListener("click", () => keyPress("1")); document.querySelector("#two").addEventListener("click", () => keyPress("2")); document.querySelector("#three").addEventListener("click", () => keyPress("3")); document.querySelector("#four").addEventListener("click", () => keyPress("4")); document.querySelector("#five").addEventListener("click", () => keyPress("5")); document.querySelector("#six").addEventListener("click", () => keyPress("6")); document.querySelector("#seven").addEventListener("click", () => keyPress("7")); document.querySelector("#eight").addEventListener("click", () => keyPress("8")); document.querySelector("#nine").addEventListener("click", () => keyPress("9")); document.querySelector("#plus").addEventListener("click", () => keyPress("+")); document.querySelector("#minus").addEventListener("click", () => keyPress("-")); document.querySelector("#times").addEventListener("click", () => keyPress("*")); document.querySelector("#divide").addEventListener("click", () => keyPress("/")); document.querySelector("#lparen").addEventListener("click", () => keyPress("(")); document.querySelector("#rparen").addEventListener("click", () => keyPress(")")); document.querySelector("#pow").addEventListener("click", () => keyPress("^")); document.querySelector("#inv").addEventListener("click", () => keyPress("^-1")); document.querySelector("#sqrt").addEventListener("click", () => keyPress("sqrt(")); document.querySelector("#ord").addEventListener("click", () => keyPress("ord(")); document.querySelector("#clear").addEventListener("click", clear); document.querySelector("#enter").addEventListener("click", evaluate); document.querySelector("#backspace").addEventListener("click", backspace);