← back 0x0, Technically Jun 21, 2026Technically as I see it.
The language looks like a Lisp:
;;; A source contract plus a pure effect boundary. (⊙ examples.add) (ƒ add (∷ (→ I64 I64 I64)) (cap pure) (doc "Return the sum of two integers.") (a b) (+ a b)) (ƒ main (∷ (→ Unit I64)) (cap pure) (_) (add 20 22))The colors here follow the same token families as the project's editor support: comments, strings, numbers, delimiters, keywords, constants, types, functions, and operators.
0x0 is a small symbolic functional kernel whose compiler is written in 0x0 from the beginning. The assembly seed is kept around as a recovery/audit path. The normal point of gravity is
compiler/main.0x0.The project:
compiler/main.0x0 -> stage1.oisa stage1.oisa -> stage2.oisa stage2.oisa -> stage3.oisa stage2.oisa == stage3.oisaThat comparison is the self-hosting gate. If stage 2 and stage 3 disagree, the compiler is not actually preserving itself.
That is the part I like.
0x0 starts with the parts almost aggressively: bootstrap boundary, compiler succession, ABI notes, object metadata, linker diagnostics, release hashes, and compatibility gates.
A file is a sequence of parenthesized forms.
(⊙ name)declares the module.(ƒ name ...)declares a function.∷declares a checked source contract.capdeclares what kind of effects the function is allowed to reach.docis source metadata for generated API docs.≔introduces local bindings.ifanddoare the control surface.The current value world is:
I64TextBoolUnit- cons-style lists
The current builtin world is useful but still small:
arithmetic, comparison, list operations,
text operations, stdin/stdout, argv/env,
file read/write, print, and panic.
The type checker rejects malformed function shapes,
duplicate declarations, unbound symbols,
call arity errors, builtin arity errors,
obvious concrete type mismatches, bad if
conditions when known, and pure/effect boundary
violations.
- unannotated functions default to
io (cap pure)functions may call pure functions and pure builtins- pure functions cannot call
read-file,write-file,read-stdin,argv,env,print,panic, or non-pure user functions
Local packages are manifest and lockfile backed:
;;; Local package imports resolve through 0x0.lock.
(⊙ examples.core_data)
(↥ "pkg:core-map")
(↥ "pkg:core-json")
(↥ "pkg:core-result")
(ƒ main
(∷ (→ Unit I64))
(_)
(≔ ((m (map-put (map-empty Unit) "base" 35))
(base (option-value-or (map-get m "base") 0))
(from-json (option-value-or (json-get-int "{\"n\":7}" "n") 0)))
(+ base from-json)))
The package layer is a local manifest plus a checked lockfile. That is still useful because it gives imports a stable name before the project grows a registry around them.
The direct ELF ABI uses a payload plus a tag:
rax = value payload
r15 = value tag
0 = Unit / nil
1 = I64 or Bool
2 = NUL-terminated UTF-8 Text pointer
3 = cons/list pointer
Direct ELF output is Linux x86-64 today. It can emit integer/control-flow code, calls, recursion, locals, text operations, list operations, file/stdin/stdout operations, and compiler artifacts. There is also a C compatibility path, a GAS/object compatibility path, a direct object writer slice, an archive writer, a linker, and an optimizer with small verified passes.
It owns enough of the pipeline to make release engineering part of the language design:
- source parser and semantic validator
- OISA backend for self-hosting
- C compatibility backend
- direct ELF64/x86-64 executable backend
- object/archive/linker slices
- ABI marker checks
- optimizer pass registry
- diagnostics classes
- generated API docs from source annotations
- independent compiler work for cross-checking
So what is 0x0, technically?
It is a self-hosting language kernel where the compiler trust path is the main feature. It is a small source language wrapped around an auditable native toolchain experiment. It is not yet mature enough yet to be your batteries included app stack.
That is the kind of weird I respect.