all repos — hex @ c070ca5e13090819004773fae89119eceb0aa6d4

A tiny, minimalist, slightly-esoteric concatenative programming lannguage.

Implementing wasm playground.
h3rald h3rald@h3rald.com
Mon, 02 Dec 2024 05:27:33 +0000
commit

c070ca5e13090819004773fae89119eceb0aa6d4

parent

6a2089c3ab044375a42c7699fd458af166e9f0c9

3 files changed, 88 insertions(+), 55 deletions(-)

jump to
M MakefileMakefile

@@ -7,7 +7,8 @@ hex: hex.c

$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ wasm: hex.c - emcc hex.c -o web/assets/hex.js --pre-js web/assets/hex-playground.js + emcc -sASYNCIFY -sEXPORTED_RUNTIME_METHODS=stringToUTF8 hex.c -o web/assets/hex.js --pre-js web/assets/hex-playground.js + .PHONY: clean clean:
M hex.chex.c

@@ -1,5 +1,30 @@

#include "hex.h" +#ifdef EMSCRIPTEN +#include <emscripten.h> + +EM_ASYNC_JS(char *, em_fgets, (const char* buf, size_t bufsize), { + return await new Promise((resolve, reject) => { + if (Module.pending_lines.length > 0) { + resolve(Module.pending_lines.shift()); + } else { + Module.pending_fgets.push(resolve); + } + }).then((s) => { + // convert JS string to WASM string + let l = s.length + 1; + if (l >= bufsize) { + // truncate + l = bufsize - 1; + } + Module.stringToUTF8(s.slice(0, l), buf, l); + return buf; + }); +}); + +#endif + + // Common operations #define POP(ctx, x) hex_item_t x = hex_pop(ctx) #define FREE(ctx, x) hex_free_item(ctx, x)

@@ -3814,26 +3839,25 @@ fclose(file);

return content; } -// REPL implementation -void hex_repl(hex_context_t *ctx) +static void do_repl(void *v_ctx) { - - char line[1024]; - - printf(" _*_ _\n"); - printf(" / \\hex\\*\n"); - printf(" *\\_/_/_/ v%s - Press Ctrl+C to exit.\n", HEX_VERSION); - printf(" *\n"); - - while (1) - { + hex_context_t *ctx = (hex_context_t *)v_ctx; + char line[1024]; +#ifdef EMSCRIPTEN + char *p = line; + p = em_fgets(line, 1024); + if (!p) + { + printf("Error reading output"); + } +#else printf("> "); // Prompt if (fgets(line, sizeof(line), stdin) == NULL) { printf("\n"); // Handle EOF (Ctrl+D) - break; + return; } - +#endif // Normalize line endings (remove trailing \r\n or \n) line[strcspn(line, "\r\n")] = '\0';

@@ -3846,7 +3870,32 @@ hex_print_item(stdout, ctx->stack.entries[ctx->stack.top]);

// hex_print_item(stdout, HEX_STACK[HEX_TOP]); printf("\n"); } + return; + + +} + +// REPL implementation +void hex_repl(hex_context_t *ctx) +{ + + + printf(" _*_ _\n"); + printf(" / \\hex\\*\n"); + printf(" *\\_/_/_/ v%s - Press Ctrl+C to exit.\n", HEX_VERSION); + printf(" *\n"); + +#ifdef __EMSCRIPTEN__ + int fps = 0; + int simulate_infinite_loop = 1; + emscripten_set_main_loop_arg(do_repl, ctx, fps, simulate_infinite_loop); +#else + + while (1) + { + do_repl(ctx); } +#endif } void hex_handle_sigint(int sig)
M web/assets/hex-playground.jsweb/assets/hex-playground.js

@@ -1,44 +1,27 @@

-Module.preRun = () => { - let stdinBuffer = []; - const inputBox = document.querySelector("article input") - const input = inputBox.value; - inputBox.addEventListener("keydown", (event) => { - if (event.key === "Enter" && !event.shiftKey) { - event.preventDefault(); - inputBox.value = ""; // Clear the textarea - stdinBuffer.push(...input + "\n"); // Add input to the buffer - } - }); - function stdin() { - if (i < input.length) { - var code = input.charCodeAt(i); - ++i; - return code; - } else { - return null; - } - }; - let stdoutBuffer = ""; - function stdout(code) { - if (code === "\n".charCodeAt(0) && stdoutBuffer !== "") { - document.querySelector("article section").textContent += stdoutBuffer + "\n"; - stdoutBuffer = ""; - } else { - stdoutBuffer += String.fromCharCode(code); - } - } + +Module.pending_fgets = []; +Module.pending_chars = []; +Module.pending_lines = []; +Module.print = (text) => { + document.querySelector("article section").textContent += text + '\n'; +}; + +const inputBox = document.querySelector("article input"); - let stderrBuffer = ""; - function stderr(code) { - if (code === "\n".charCodeAt(0) && stderrBuffer !== "") { - document.querySelector("article section").textContent += stderrBuffer + "\n"; - stderrBuffer = ""; - } else { - stderrBuffer += String.fromCharCode(code); - } - } - FS.init(stdin, stdout, stderr); -} +inputBox.addEventListener("keydown", (e) => { + if (e.key === 'Enter') { + e.preventDefault(); + Module.pending_lines.push(Module.pending_chars.join('')); + Module.pending_chars = []; + inputBox.value = ''; + } else { + Module.pending_chars.push(e.key); + } + if (Module.pending_fgets.length > 0 && Module.pending_lines.length > 0) { + let resolver = Module.pending_fgets.shift(); + resolver(Module.pending_lines.shift()); + } +});