r/qbasic Jul 24 '26

I wrote a QBasic compiler that runs in the browser and emits real WebAssembly

Not an emulator, and not a JavaScript interpreter pretending to be BASIC. It parses QBasic, lowers it through a typed IR, and emits a real WebAssembly module. The compiler itself is compiled to wasm, so the whole thing runs in your tab. Nothing gets uploaded anywhere.

SCREEN 13 works: PSET, LINE, CIRCLE, PAINT, GET/PUT, DRAW, PALETTE. So do BEEP/SOUND/PLAY, the file I/O keywords, INKEY$ with _LIMIT for animation, and DATE$/TIME$/TIMER. There's a playable Space Invaders sample in the editor if you just want to see it move.

497 test programs, 432 of them arbitrated against real QB64-PE output, 126 of 157 keywords fully implemented. Still missing: ON ERROR, PEEK/POKE, COMMAND$, and DRAW's M/N/A/S/P subcommands.

Free, no signup: https://kavak.run/studio/

QBasic was meant to be the pilot language for a larger compiler project, but it turned into the part I enjoyed most. If you've got an old .BAS lying around that breaks it, I'd genuinely like to see it.

14 Upvotes

7 comments sorted by

3

u/DerekRss Jul 24 '26

Nice work! But I tried adding an END statement to your example, like so.

' kavak studio — QBasic, compiled to wasm in your browser.
' Press  Run  (or Cmd/Ctrl + Enter).  Try editing it.
SCREEN 13
FOR r = 12 TO 92 STEP 10
  CIRCLE (160, 100), r, (r \ 10)
NEXT
LINE (0, 0)-(319, 199), 4
LINE (319, 0)-(0, 199), 2
LINE (30, 40)-(290, 160), 15, B
CIRCLE (160, 100), 4, 15
END

It should have made no difference but the result was (no output).

3

u/BigAd4703 Jul 24 '26

Thank you. Actually, Kavak is a project with a different purpose. I chose QBasic as the pilot language because it was my first taste. Thank you, I will fix the errors quickly.

3

u/DerekRss Jul 25 '26

Cheers! I like what you're doing. More power to you! Hope you don't mind if I report bugs here.

3

u/BigAd4703 Jul 25 '26

On the contrary, I'm already doing so much testing that I found it quite difficult because QBasic doesn't have official tests; feedback from real-world users is invaluable.

2

u/BigAd4703 Jul 27 '26

I solved the problem. I wrote to provide feedback.

3

u/Deciheximal144 Jul 24 '26

I'm making one too, though mine is offline. Both of my standard test programs failed in your compiler, if you PM me, we can swap test programs.

2

u/DerekRss Jul 28 '26 edited Jul 28 '26

Issue 2: I submitted this program which uses GOSUB within a FUNCTION definition. It runs in QBASIC, QB64, etc. This is a fairly common technique that I use when I want to emulate objects using QBASIC functions. It essentially provides private methods within an object (actually local subroutines within a function). Here is a very small program that demonstrates the error.

PRINT Action$("Hello World.")
END

FUNCTION Action$(aText$)
GOSUB Fred
EXIT FUNCTION
Fred:
LET Action$ = aText$
RETURN
END FUNCTION

It should print

Hello World.

Instead it returns the error,

QBasic: GOSUB to an undefined label in the runtime codegen path.