DEV Community

Cover image for HEXAW: a tiny time machine for WebAssembly
Peter Vivo
Peter Vivo Subscriber

Posted on

HEXAW: a tiny time machine for WebAssembly

Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady Submission 🦥

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady

What I Built

I once wrote a Z80 game on a Videoton TV Computer. I still miss typing an instruction and seeing the exact bytes it becomes. As I wrote in this old post

WebAssembly brought back the possibility. WAT brought me a parenthesis jungle. My brain wanted an assembler listing.

So I started building HEXAW: a new, experimental text format for WASM, with readable mnemonics and a retro assembler feeling.

It is still totally beta. The syntax and tooling are evolving. Expect rough edges.

The CLI can assemble HEXAW into .wasm, dump binaries back into readable instructions, and step through code forwards and backwards. There is also an AI mentor you can ask when the bytes stop making sense.

Demo

HEXAW is also on npm. You’ll need Node.js 22.18 or later. Save the example below as factorial.hexaw, then:

npm install -g hexaw
hexaw -i factorial.hexaw
Enter fullscreen mode Exit fullscreen mode

The AI mentor needs a Groq API key. Put it in a .env file in your working directory:

GROQ_API_KEY=your_groq_api_key
Enter fullscreen mode Exit fullscreen mode

Load that file explicitly when starting the shell. On Linux/macOS:

node --env-file=.env "$(command -v hexaw)" -i factorial.hexaw
Enter fullscreen mode Exit fullscreen mode

Without a key, assembling, dumping, and debugging still work. Only the LLM help needs it.

or clone the repo

Clone the repository, run npm ci, and save the example below as factorial.hexaw in the repository folder. Then:

npm run shell -- factorial.hexaw
Enter fullscreen mode Exit fullscreen mode

Inside the shell:

CALL factorial 5
G
BACK
Enter fullscreen mode Exit fullscreen mode

That computes 5! = 120, then reverses the last execution step.

The shell also has an SST-inspired A mode: type an instruction, press Enter, see its hex bytes, and continue at the next address. An empty Enter applies the completed draft.

Code

Here is the factorial loop:

EXP "factorial" 0
FN 0
  PAR 0       ; n
  RES
  LOC 1       ; result

  CONST 1
  SET 1
  BLOCK
    LOOP
      GET 0
      EQZ
      BRIF 1  ; leave the outer block when n = 0

      GET 1
      GET 0
      MUL
      SET 1

      GET 0
      CONST 1
      SUB
      SET 0
      BR 0    ; repeat the loop
    END
  END
  GET 1
END
Enter fullscreen mode Exit fullscreen mode

The default numeric type is i32. Prefixes L, F, and D select i64, f32, and f64. This is still WASM: a typed stack, locals, and structured control flow.

The dump keeps the bytes beside the instructions:

00000032 : 20 00 : GET 0
00000034 : 45    : EQZ
00000035 : 0D 01 : BRIF 1
Enter fullscreen mode Exit fullscreen mode

Source: https://github.com/Pengeszikra/hexaw

How I Built It

I built it with Codex, using my TS+|> TypeScript fork for the CLI and a shared assembly/debugging engine.

The mentor uses the open-weight gpt-oss-120b model through Groq, carried over from my Terminal Is Your Friend project. Its teaching material now focuses on HEXAW and WASM, grounded in the actual opcode table and a limited snapshot of the current code, assembly draft, VM state, and recent errors.

With GROQ_API_KEY set before starting the shell, I can ask:

// What does BRIF 1 mean here?
AI ERROR
Enter fullscreen mode Exit fullscreen mode

The reply arrives while I keep working. Suggested code stays an example until I enter it myself.

Why Does Open Innovation Matter?

I can change the language, the compiler fork, and the mentor’s teaching material. Anyone else can too: HEXAW is MIT-licensed.

An open-weight model leaves a future route to self-hosting. Today the mentor uses Groq’s hosted API; the assembler and debugger work locally.

The Lazy Payoff

Less manual byte decoding. Fewer trips between code, documentation, and a separate AI chat.

Apparently I am lazy enough to want all of that in one terminal. Just not lazy enough to leave assembly alone.

Top comments (4)

Collapse
 
unitbuilds profile image
UnitBuilds •

Ngl, this is pretty cool! I've been diving deep into WASM for a while now and the idea is awesome, makes me think of the old Commodore 64 era cartridges (before my time, but my mom had an old 1 that was in a box at my grandma's house), simply slot it into a new pc and it just works. But everyone looks at it as a 'final destination' for code, never as a destination that needs a new road? I mean why write it in python if it ends up in WASM, as opposed to a language written specifically for WASM (yes, ok Rust exists, but it's not the same). I'm currently (or well my AI agent I set to the task is) working on a standalone OS, built specifically for 1 single purpose... To run WASM and to scale across multiple nodes (so it can run on a datacenter as a unified OS). It's gunna take a LOOOONG time, but I've got time... Not enough patience to wait for it, but that's fine, it's why I have a bunch of other projects to keep me busy 😂

Collapse
 
pengeszikra profile image
Peter Vivo •

Feel free to test this language maybe worth to use it. Even contribute it.

Collapse
 
unitbuilds profile image
UnitBuilds •

Will do, though atm a bit busy, I'll bookmark for now and get back to it! For now, I'm fixated on my latest experiment, I wanted to make a DB-driven LLM, it cant think, but it does show incredible promise for codebase optimizations... I ingested 5 codebases and it analyzed the functions in it and suggested parity functions between the codebases that are more effective (better error handling, more performant, simplicity, etc.), so gunna dive into that first a bit more, so I can see if I can get codebase translation working (eg. python to rust), I'll have a look whether I can ingest HEXAW and see how it compares, would be cool if it's more optimized than the rest!

Collapse
 
robertpaschal profile image
Odinaka Robert Nnamani •

rewind for wasm. tiny format, fun idea.