pwlp 1.0.0

Control LED strips wirelessly by sending them short animation programs
Documentation
<!DOCTYPE html>
<html style="display: block; width: 100%; height: 100%; box-sizing: border-box;">
	<head>
		<style type="text/css">
		body {
			display: flex;
			flex-direction: column;
			width: 100%;
			height: 100%;
			box-sizing: border-box;
			align-items: stretch;
			justify-items: stretch;
			margin: 0px;
		}

		#editor {
			display: flex;
			flex-direction: row;
			width: 100%;
			height: 100%;
			box-sizing: border-box;
			align-items: stretch;
			justify-items: stretch;
			margin: 0px;
		}

		textarea {
			margin: 5px;
			font-family: monospace;
		}

		div#output td {
			height: 6px;
			width: 6px;
		}

		div#output tr, div#output td, div#output table {
			margin: 0px;
			padding: 0px;
			border-collapse: collapse;
		}
		</style>
	</head>

	<body>
		<div id="editor">
			<textarea id="source" onkeyup="run()" style="flex-grow: 1;">
tail = 9;

loop {
	for(n = get_length) {
		set_pixel(n-1, 0, 0, 0);
	};
	t = get_precise_time;

		for(i = tail) {
	set_pixel((t + i) % get_length, 255 - (i * (255 / tail)), 0 ,0);
	};


	for(i=tail) {
		set_pixel((t - i) % get_length, 255 - (i * (255 / tail)), 0 ,0);
	};

	set_pixel(t % get_length, 255, 100, 50);

	blit;
	yield;
}
			</textarea>

			<textarea readonly id="binary" style="flex-grow: 1;"></textarea>
			<textarea readonly id="assembly" style="flex-grow: 1;"></textarea>
			<div id="output" style="flex-grow: 1;"></div>
		</div>
		<button onclick="benchmark()">Benchmark</button>
	</body>
</html>

<script type="module">
import init, { compile, assemble, run as runProgram } from './pkg/pwlp.js';
let initialized = false;

if(window.localStorage.getItem("source")) {
	document.getElementById("source").value = window.localStorage.getItem("source");
}

// Use tab key for indent in source view
// See https://stackoverflow.com/questions/6637341/use-tab-to-indent-in-textarea
document.getElementById('source').addEventListener('keydown', function(e) {
	if (e.key == 'Tab') {
		e.preventDefault();
		var start = this.selectionStart;
		var end = this.selectionEnd;

		// set textarea value to: text before caret + tab + text after caret
		this.value = this.value.substring(0, start) +
			"\t" + this.value.substring(end);

		// put caret at right position again
		this.selectionStart =
			this.selectionEnd = start + 1;
	}
});

window.benchmark = function() {
	const source = document.getElementById("source").value;

	// Warming up
	for(let x = 0; x<100; x++) {
		compile(source);
	}

	const start = performance.now();
	const iterations = 100000;
	let a = 0;
	for(;a<iterations; a++) {
		compile(source);
		if(a % 1000 === 0) {
			if((performance.now() - start) > 10000) {
				break;
			}
		}
	}
	const elapsed = performance.now() - start;
	alert("Time elapsed: " + elapsed + "ms, " + (elapsed / a).toFixed(2) + "ms/iteration, " + (a / elapsed * 1000).toFixed(0)+ " iterations/sec");
};

window.run = async function() {
	if(window.event) {
		window.event.preventDefault();
		window.event.stopPropagation();
	}

	if(!initialized) {
		initialized = true;
		await init();
	}
	const source = document.getElementById("source").value;
	window.localStorage.setItem("source", source);

	let res = "";
	try {
		const outputDiv = document.getElementById("output");
		outputDiv.innerHTML = "";
		const res = compile(source);
		console.log({res});
		document.getElementById("binary").value = [...res].map(x => x.toString(16).toUpperCase()).join(" ");

		const ass = assemble(source);
		document.getElementById("assembly").value = ass;

		const out = runProgram(res, 25, 10000);
		const colors = out.split("\n").slice(0, 50).map(x => x.split(" "));

		// Create a table
		const table = document.createElement("TABLE");
		colors.forEach(row => {
			const tr = document.createElement("TR");
			row.forEach(color => {
				if(color !== "") {
					const td = document.createElement("TD");
					td.style = "background-color: #" + color;
					td.title = color;
					tr.appendChild(td);
				}
			});
			table.appendChild(tr);
		});

		// Remove everyting in out
		outputDiv.appendChild(table);
	}
	catch(e) {
		console.error(e);
		document.getElementById("output").innerHTML = "";
		document.getElementById("assembly").value = "";
	}
};

window.run();
</script>