single-variable-algebra-compiler 0.1.3

A compiler for the minimalistic programming language single-variable-algebra.
Documentation
<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8" />
	<meta name="viewport" content="width=device-width, initial-scale=1.0" />
	<title>Single Variable Algebra Playground</title>
	<style>
	body, input, button, textarea, select { background-color: #002; color: white; }
	input:focus, textarea:focus { outline: none; }
	#sva { background-color: #134; min-height: 42vh; }
	#log, #output { background-color: #333; }
	a { color: #0ff; text-decoration: none; }
	a:hover { text-decoration: underline; }
	input[type="text"],
	textarea { min-width: 100%; max-width: 100%; font-style: Consolas; }
	</style>
</head>

<body>
	<h2>Single Variable Algebra Playground <button id="loadWasmBtn">RUN &#9654;</button>
	<select aria-label="SVA code examples" onchange="updateTextarea(this.value)">
    <option value="beaver">4-state Busy Beaver</option>
    <option value="floor">floor function</option>
    <option value="replace">Replace 1 with 7</option>
    </select>
	</h2>
	<p><input type="checkbox" id="checkbox" onclick="checkbox()"> Translate a 10-symbol space-bounded Turing machine to SVA. Syntax: <a href="https://wiki.bbchallenge.org/wiki/Turing_machine#Standard_text_format">TM standard text format</a>.</p>
	<div id="tm_area">
	  Tape length: <input id="bandLength" onchange="translate_tm_to_sva()" min="15" max="450" step="1" type="number" value="50"></p>
	  <input type="text" id="tm" onchange="translate_tm_to_sva()" value="1RB1LB_1LA0LC_1RZ1LD_1RD0RA">
    </div>
	<p><textarea id="sva" style="overflow-wrap: normal; overflow-x: scroll; white-space: pre">decimals(x) = 50
abs(x) = (x^2)^(1/2)
H(x) = (x+abs(x))/(2*x)
tiny(x) = 10^(-decimals(x))
ge0(x) = H(x+tiny(x)/10)
lt1(x) = 1-ge0(x-1)
is0(x) = ge0(x)*lt1(x)
is1(x) = is0(x-1)
is2(x) = is0(x-2)
is3(x) = is0(x-3)
is4(x) = is0(x-4)
is5(x) = is0(x-5)
is6(x) = is0(x-6)
is7(x) = is0(x-7)
is8(x) = is0(x-8)
is9(x) = is0(x-9)
floor1(x) = is1(x)+2*is2(x)+3*is3(x)+4*is4(x)+5*is5(x)+6*is6(x)+7*is7(x)+8*is8(x)+9*is9(x)
right(x) = x*10-floor1(x*10)+floor1(x*10)*tiny(x)
left(x) = right^[49](x)
tm(x) = is0(x)*x+is1(x)*(is0(10*(x-1))*(2+right(x-1+0.1))+is1(10*(x-1))*(2+left(x-1-0.1+0.1)))+is2(x)*(is0(10*(x-2))*(1+left(x-2+0.1))+is1(10*(x-2))*(3+left(x-2-0.1+0.0)))+is3(x)*(is0(10*(x-3))*(0+right(x-3+0.1))+is1(10*(x-3))*(4+left(x-3-0.1+0.1)))+is4(x)*(is0(10*(x-4))*(4+right(x-4+0.1))+is1(10*(x-4))*(1+right(x-4-0.1+0.0)))
f(x) = tm^[10000](x)
f(1)</textarea><br>
	<input id="log" type="text" disabled><br><textarea id="output" disabled></textarea></p>
    <ul>
	<li>For convenience, f(x) = g(g(g(x))) equals f(x) = g^[3](x)</li>
	<li><a href="https://github.com/772/single-variable-algebra-compiler">Git Repository</a></li>
    </ul>
	<script>
	function updateTextarea(selectedValue) {
		const textarea = document.getElementById("sva");
		switch(selectedValue) {
			case 'beaver':
				textarea.value = `decimals(x) = 50
abs(x) = (x^2)^(1/2)
H(x) = (x+abs(x))/(2*x)
tiny(x) = 10^(-decimals(x))
ge0(x) = H(x+tiny(x)/10)
lt1(x) = 1-ge0(x-1)
is0(x) = ge0(x)*lt1(x)
is1(x) = is0(x-1)
is2(x) = is0(x-2)
is3(x) = is0(x-3)
is4(x) = is0(x-4)
is5(x) = is0(x-5)
is6(x) = is0(x-6)
is7(x) = is0(x-7)
is8(x) = is0(x-8)
is9(x) = is0(x-9)
floor1(x) = is1(x)+2*is2(x)+3*is3(x)+4*is4(x)+5*is5(x)+6*is6(x)+7*is7(x)+8*is8(x)+9*is9(x)
right(x) = x*10-floor1(x*10)+floor1(x*10)*tiny(x)
left(x) = right^[49](x)
tm(x) = is0(x)*x+is1(x)*(is0(10*(x-1))*(2+right(x-1+0.1))+is1(10*(x-1))*(2+left(x-1-0.1+0.1)))+is2(x)*(is0(10*(x-2))*(1+left(x-2+0.1))+is1(10*(x-2))*(3+left(x-2-0.1+0.0)))+is3(x)*(is0(10*(x-3))*(0+right(x-3+0.1))+is1(10*(x-3))*(4+left(x-3-0.1+0.1)))+is4(x)*(is0(10*(x-4))*(4+right(x-4+0.1))+is1(10*(x-4))*(1+right(x-4-0.1+0.0)))
f(x) = tm^[10000](x)
f(1)
`;
				break;
			case 'floor':
				textarea.value = `decimals(x) = 50
abs(x) = (x^2)^(1/2)
H(x) = (x+abs(x))/(2*x)
tiny(x) = 10^(-decimals(x))
ge0(x) = H(x+tiny(x)/10)
lt1(x) = 1-ge0(x-1)
is0(x) = ge0(x)*lt1(x)
is1(x) = is0(x-1)
is2(x) = is0(x-2)
is3(x) = is0(x-3)
is4(x) = is0(x-4)
is5(x) = is0(x-5)
is6(x) = is0(x-6)
is7(x) = is0(x-7)
is8(x) = is0(x-8)
is9(x) = is0(x-9)
floor1(x) = is1(x)+2*is2(x)+3*is3(x)+4*is4(x)+5*is5(x)+6*is6(x)+7*is7(x)+8*is8(x)+9*is9(x)
floor2(x) = floor1(x/10)*10+floor1(x-floor1(x/10)*10)
floor4(x) = floor2(x/10^2)*10^2+floor2(x-floor2(x/10^2)*10^2)
floor8(x) = floor4(x/10^4)*10^4+floor4(x-floor4(x/10^4)*10^4)
floor16(x) = floor8(x/10^8)*10^8+floor8(x-floor8(x/10^8)*10^8)
floor16(1156772000123456.1772731827367126472727728)
`;
				break;
			case 'replace':
				textarea.value = `decimals(x) = 50
abs(x) = (x^2)^(1/2)
H(x) = (x+abs(x))/(2*x)
tiny(x) = 10^(-decimals(x))
ge0(x) = H(x+tiny(x)/10)
lt1(x) = 1-ge0(x-1)
is0(x) = ge0(x)*lt1(x)
is1(x) = is0(x-1)
is2(x) = is0(x-2)
is3(x) = is0(x-3)
is4(x) = is0(x-4)
is5(x) = is0(x-5)
is6(x) = is0(x-6)
is7(x) = is0(x-7)
is8(x) = is0(x-8)
is9(x) = is0(x-9)
floor1(x) = is1(x)+2*is2(x)+3*is3(x)+4*is4(x)+5*is5(x)+6*is6(x)+7*is7(x)+8*is8(x)+9*is9(x)
right(x) = x*10-floor1(x*10)+floor1(x*10)*tiny(x)
left(x) = right^[49](x)
replace_1_by_7(x) = right(x+is1(x*10)*0.6)
f(x) = replace_1_by_7^[50](x)
f(0.2821011111110111236333746311231819159841234293491)
`;
				break;
			default:
				textarea.value = '';
		}
		document.getElementById("log").value = "Loaded example '" + selectedValue + "'.";
		document.getElementById("output").value = "";
	}
		
	function turing_machine_translate(currentState, write, action, newstate, i) {
		return "+is" + i + "(10*(x-" + currentState + "))*(" + newstate + "+" + action + "(x-" + currentState +   "-0." + i + "+0." + write + "))"
	}

	function translate_tm_to_sva() {
		let tmString = document.getElementById("tm").value;
		let amount_of_states = (tmString.match(/_/g) || []).length + 1;
		let firstSegment = tmString.split('_')[0];
		let amount_of_symbols = firstSegment ? firstSegment.length / 3 : 0;
		if (amount_of_states * amount_of_symbols * 3 + amount_of_states - 1 != tmString.length) {
			document.getElementById("log").value = "Turing machine syntax error.";
			return;
		}
		if (amount_of_symbols > 10) {
			document.getElementById("log").value = "Turing machine has more than 10 symbols.";
			return;
		}
		if (amount_of_states < 2) {
			document.getElementById("log").value = "Turing machine has no states.";
			return;
		}
		let algebra = `decimals(x) = ` + Number(document.getElementById("bandLength").value) + `\n` + `abs(x) = (x^2)^(1/2)
H(x) = (x+abs(x))/(2*x)
tiny(x) = 10^(-decimals(x))
ge0(x) = H(x+tiny(x)/10)
lt1(x) = 1-ge0(x-1)
is0(x) = ge0(x)*lt1(x)
is1(x) = is0(x-1)
is2(x) = is0(x-2)
is3(x) = is0(x-3)
is4(x) = is0(x-4)
is5(x) = is0(x-5)
is6(x) = is0(x-6)
is7(x) = is0(x-7)
is8(x) = is0(x-8)
is9(x) = is0(x-9)
floor1(x) = is1(x)+2*is2(x)+3*is3(x)+4*is4(x)+5*is5(x)+6*is6(x)+7*is7(x)+8*is8(x)+9*is9(x)
right(x) = x*10-floor1(x*10)+floor1(x*10)*tiny(x)
left(x) = right^[` + (Number(document.getElementById("bandLength").value) - 1) + `](x)
tm(x) = is0(x)*x`;
		const blocks = tmString.split("_");
		blocks.forEach((block, index) => {
			const currentState = index + 1;
			algebra += "+is" + currentState + "(x)*(";
			for (let i = 0; i < amount_of_symbols; i++) {
				const trans0 = block.substring(i*3, i*3+3);
				console.log("transe " + trans0);
				const write = parseInt(trans0[0]);
				const action = trans0[1] == "L" ? "left" : "right";
				let newstate_temp = trans0[2].charCodeAt(0) - 64;
				const newstate = newstate_temp == 26 ? 0 : newstate_temp;
				algebra += turing_machine_translate(currentState, write, action, newstate, i);
			}
			algebra += ")";
		});
		document.getElementById("sva").value = algebra + "\n" + `f(x) = tm^[10000](x)\n` + `f(1)`;
		document.getElementById("log").value = "Translated Turing machine to SVA. Found " + amount_of_states + " states using " + amount_of_symbols + " symbols."; 
	}

	function checkbox() {
		let checked = document.getElementById("checkbox").checked;
		document.getElementById("tm_area").style.display = "none";
		if (checked) {
			document.getElementById("tm_area").style.display = "block";
			translate_tm_to_sva();
		}
	}
window.addEventListener("DOMContentLoaded", (event) => {
    const textarea1 = document.getElementById("tm");
    const textarea2 = document.getElementById("bandLength");
    const textarea3 = document.getElementById("sva");
    const textarea4 = document.getElementById("output");
    const savedValue1 = sessionStorage.getItem("sessionStorage1");
    const savedValue2 = sessionStorage.getItem("sessionStorage2");
    const savedValue3 = sessionStorage.getItem("sessionStorage3");
    const savedValue4 = sessionStorage.getItem("sessionStorage4");
    if(savedValue1) {
        textarea1.value = savedValue1;
    }
    if(savedValue2) {
        textarea2.value = savedValue2;
    }
    if(savedValue3) {
        textarea3.value = savedValue3;
    }
    if(savedValue4) {
        textarea4.value = savedValue4;
    }
    textarea1.addEventListener("input", function() {
        sessionStorage.setItem("sessionStorage1", textarea1.value);
    });
    textarea2.addEventListener("input", function() {
        sessionStorage.setItem("sessionStorage2", textarea2.value);
    });
    textarea3.addEventListener("input", function() {
        sessionStorage.setItem("sessionStorage3", textarea3.value);
    });
    textarea4.addEventListener("input", function() {
        sessionStorage.setItem("sessionStorage4", textarea4.value);
    });
});
checkbox();

window.addEventListener("beforeunload", function() {
    sessionStorage.setItem("sessionStorage1", document.getElementById("tm").value);
    sessionStorage.setItem("sessionStorage2", document.getElementById("bandLength").value);
    sessionStorage.setItem("sessionStorage3", document.getElementById("sva").value);
    sessionStorage.setItem("sessionStorage4", document.getElementById("output").value);
});
	</script>
  <script type="module">
  let wasmInitialized = false;
  
  document.getElementById('loadWasmBtn').addEventListener('click', async () => {
    if (wasmInitialized) {
      console.log('WASM bereits geladen');
      return;
    }
    
    try {
      const { default: init } = await import('./wasm.js');
      await init();
      wasmInitialized = true;
      console.log('WASM erfolgreich geladen');
      location.reload();
    } catch (error) {
      if (!error.message.startsWith(
        "Using exceptions for control flow, don't mind me. This isn't actually an error!"
      )) {
        console.error('Fehler beim Laden des WASM-Moduls:', error);
        throw error;
      }
    }
  });
</script>
</body>

</html>