Skip to content
Tech News
← Back to articles

Commodore 64 Basic for PostgreSQL

read original more articles
Why This Matters

The article introduces PL/CBMBASIC, a PostgreSQL extension that allows running actual Commodore 64 BASIC V2 code within a modern database environment. By reimplementing the original interpreter in C and embedding it into PostgreSQL, this innovation bridges nostalgic programming with contemporary data management, enabling retro-style coding inside advanced systems. This development highlights how legacy programming languages can be revitalized for modern applications, offering both educational value and unique integration possibilities for developers and enthusiasts.

Key Takeaways

If you are of a certain age, the words 38911 BASIC BYTES FREE will do something to you that no amount of therapy can undo. You remember the blue screen. You remember typing in three pages of a listing from a magazine, getting ?SYNTAX ERROR IN 2340 , and not knowing which of the three pages contained the typo. You remember that the disk drive was device 8, and that it was slower than continental drift.

I have some news. All of that now runs inside PostgreSQL.

PL/CBMBASIC is a procedural language extension that executes function bodies on Commodore 64 BASIC V2. Not a lookalike, not a tribute act: the actual Microsoft/Commodore interpreter from 1982, by way of Michael Steil's cbmbasic project, which statically recompiled the 6502 ROM into C. That C is compiled straight into the extension's shared library, so the interpreter lives inside your backend process. Every function call is an in-memory power cycle: zero the 64KB RAM array, reset the CPU registers, and re-enter the ROM at $E394. The whole ceremony costs about 15 to 20 microseconds, which is roughly a thousand times faster than the hardware ever managed, and quick enough to call per row over a large table without feeling guilty.

CREATE EXTENSION plcbmbasic; CREATE FUNCTION hello(who text) RETURNS text AS $$ 10 PRINT "HELLO, ";WHO$;"!" $$ LANGUAGE plcbmbasic; SELECT hello('WORLD'); -- HELLO, WORLD!

Yes, those are line numbers. Yes, they are mandatory. User code starts at line 10, like nature intended, because lines 0 to 9 are reserved: the extension injects your function arguments there as ordinary BASIC assignments before your code runs. A text parameter named who arrives as WHO$ , a smallint named lives becomes a genuine 16-bit LIVES% , and everything numeric otherwise lands in a 40-bit CBM float, all nine glorious significant digits of it.

The validator has opinions, because BASIC V2 had opinions

Anyone who programmed a C64 for more than an hour discovered that you could not have a variable called TOTAL . The tokeniser crunched keywords anywhere, including inside identifiers, so TOTAL contained TO and became garbage. SCORE contained OR . BUDGET contained GET . Only the first two characters of a name were significant, so USERNAME and USERID ... actually those were fine, US$ and US are different variables, but ALPHA and ALPS silently became the same string. And TI and ST were taken by the system.

The extension ships a validator, so PostgreSQL now delivers these opinions at CREATE FUNCTION time instead of leaving you to rediscover them at runtime:

ERROR: parameter name "total" contains the BASIC keyword TO HINT: This is why nobody could ever have a variable called TOTAL on the Commodore 64.

Some traumas deserve better error messages than we got the first time round.

... continue reading