pxx

Pxx is a Pascal and C compiler*1. Written in pascal, it self-hosts and cross-compiles — x86-64, i386, ARM (32 and 64), riscv, xtensa, down to bare-metal ESP32.

This project was vibe coded*2. It started as a proof of concept, and got out of hand — the story is below*3.

It's a full pascal + C compiler, FPC- and C99-compatible. Nilpy, our python dialect, is staged*4. Not fully optimized yet — our code is about ~2x as slow as optimized compilers.

Why pascal*5? It happened to be the language i know best. It's a middle ground between being very C-like, yet applying memory-management features for ansistring, OOP and dynarrays — and proved a golden middle ground for the nilpy experiment.

Docs: documentation · compliance overview.


Read more

The story

It began with a nuisance: to use a C library from pascal, you hand-write a wrapper. Every time. Even though the C header already declares every type. So why not import that C header directly, and be done.

So i sat down, vibe coded. Pascal, self-hosting first. Then compile C, headers included, and call straight in. An auto keyword that works out a variable's type for you — a pointer to an iterable sqlite result set, say. Then the same behind basic, then python syntax. Principle proved: we can detect types.

Then it kept working. Within a week, most of the proofs done (below). So i went down the hole. Premium anthropic account. Tickets. A test harness. Bug-driven development. Steer, babysit, grow the vibe baby.

Proofs of concept

The questions, that first week, and the answers:

Auto-typing later folded back into the pascal dialect. Async became pascal language surface. See the PXX dialect.

nilpy

Python syntax, compiled through the same backend. Not a python runtime. Staged — it works, real apps run, it maps back onto the design concepts — but still in development, because pascal and C are the primary goal and those are proven. The cpython library ecosystem is out of scope. The language is not. More under languages.

FPC compatibility

Pascal syntax is largely FPC-compatible. FPC can bootstrap pxx. Details: FPC compatibility.

Why pascal

Don't know all of it. It's the language i'm most fluent in. 25 years. Also more C-like than people remember — managed data (ansistring, dynamic arrays), OOP, about halfway to C++.

Object Pascal

Pascal mixes plain C-level code with compiler-managed data (ansistring, dynamic arrays) and OOP. About halfway to C++, different route. One thing: pxx does not use any object pascal to compile itself. Its own source is plain, linear pascal. On purpose — fewer features used, fewer ways to miscompile the compiler.

Vibe coding

Built with an AI agent. The architecture shows it. As a human i'd have organized more into folders, and reached for OOP the moment it was available. The agent went the other way: plain pascal, big per-topic include files it can grep in one pass instead of hunting for the right source file. Humans keep source files short. An agent will take a 30,000-line include over searching subfolders. Different instincts. The codebase wears them.

It shows in the decisions too. Asked what a cdecl marker should mean on a routine pxx compiles itself — three answers, all of them expensive — the reply settled it in one line:

Decorators are decoration, and the convention is the target's by definition.

— Opus 5.0, on the xtensa calling convention

A calling-convention marker does not select an ABI. The target already defines one, so the marker decorates and nothing else. That turned a feature question into a smaller and better fix: make pxx's xtensa convention be the xtensa C ABI, on both sides, unconditionally — so pxx and gcc agree and no marker is involved at all.

Bug-driven development

Point the compiler at real-world code — a C library, a pascal unit, a python script. See what breaks. File it. Fix it. Repeat. Correctness is checked against the reference tools (gcc, fpc, cpython) as oracles. Goal: compile anything, match what the established compilers already do.