No description
Find a file
Orkuncakilkaya ff15c4e01d
All checks were successful
docs / build-and-deploy (push) Successful in 2s
docs(types): document the fixeds and ptrs typed buffers
The type table lists fixeds (buffer of fixed values) and ptrs (buffer of
pointers) alongside words, but they had no reference pages. Add both, with
compilable examples; coverage inventory updated (types: 10 -> 12).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-29 18:50:15 +03:00
.claude Baseline: Ludic compiler + toolchain, Phase 1 syntax fixes complete 2026-08-27 15:15:35 +03:00
.forgejo/workflows ci(docs): build in a python:3.12 container, clone source directly 2026-08-29 16:33:25 +03:00
assets Baseline: Ludic compiler + toolchain, Phase 1 syntax fixes complete 2026-08-27 15:15:35 +03:00
docs docs(types): document the fixeds and ptrs typed buffers 2026-08-29 18:50:15 +03:00
examples Language: named colors, namespaced Screen/Input/Random/Map API, named args 2026-08-29 16:05:55 +03:00
runtime Language: named colors, namespaced Screen/Input/Random/Map API, named args 2026-08-29 16:05:55 +03:00
selfhost Language: named colors, namespaced Screen/Input/Random/Map API, named args 2026-08-29 16:05:55 +03:00
tools docs(types): document the fixeds and ptrs typed buffers 2026-08-29 18:50:15 +03:00
.gitignore Ignore .DS_Store 2026-08-29 15:12:49 +03:00
BOOTSTRAP.md Phase 6b: annotation DSL (@Queries, @Handles) + docs prose pass 2026-08-27 18:49:24 +03:00
build-cli.sh Baseline: Ludic compiler + toolchain, Phase 1 syntax fixes complete 2026-08-27 15:15:35 +03:00
build.sh Baseline: Ludic compiler + toolchain, Phase 1 syntax fixes complete 2026-08-27 15:15:35 +03:00
COMPILING.md Phase 6b (cont.): fix ECS-construct 'system'->'handler' in COMPILING/BOOTSTRAP prose 2026-08-27 18:52:40 +03:00
EVENTS-DESIGN.md Networking N2–N6, and a fully C-free toolchain 2026-08-29 15:08:23 +03:00
LANGUAGE.md Networking N2–N6, and a fully C-free toolchain 2026-08-29 15:08:23 +03:00
LIFECYCLE-DESIGN.md Networking N2–N6, and a fully C-free toolchain 2026-08-29 15:08:23 +03:00
LUANTI-ROADMAP.md Baseline: Ludic compiler + toolchain, Phase 1 syntax fixes complete 2026-08-27 15:15:35 +03:00
MOBILE-DESIGN.md Networking N2–N6, and a fully C-free toolchain 2026-08-29 15:08:23 +03:00
NETWORKING-DESIGN.md Networking N2–N6, and a fully C-free toolchain 2026-08-29 15:08:23 +03:00
README.md Phase 6e: unify builtin naming (loaders domain-first, set_reg) 2026-08-27 23:38:10 +03:00
SCENES-DESIGN.md Networking N2–N6, and a fully C-free toolchain 2026-08-29 15:08:23 +03:00
SYNTAX-REDESIGN.md Phase 6e: unify builtin naming (loaders domain-first, set_reg) 2026-08-27 23:38:10 +03:00
test.sh Networking N2–N6, and a fully C-free toolchain 2026-08-29 15:08:23 +03:00

Ludic

An AI-first, ahead-of-time compiled game language with an ECS core, a deterministic fixed-point runtime, and a native 2D backend. ludicc lowers Ludic to LLVM IR itself and emits a native binary — and ludicc is itself written in Ludic.

  .ludic  ──►  ludicc  ──►  LLVM IR  ──►  object  ──►  native binary
             (in Ludic)

No C is generated, compiled or linked anywhere in a build. There is no interpreter, no transpiler, and no C runtime: the framebuffer, sprites, PNG decoding, TrueType text, the retained UI, the registers and the RNG are all written in Ludic (runtime/native/*.ludic), and the macOS window is hand-written LLVM IR (runtime/native/cocoa.ll). Beneath that sits only the platform's own ABI — malloc, fwrite, objc_msgSend, CoreGraphics — reached by compiler intrinsics, the same floor Rust and Swift stand on.

The compiler is written in Ludic. selfhost/*.ludic is a Ludic compiler — lexer, parser and LLVM-IR backend — that compiles every example (including the 6-file JRPG) to the byte-exact same binary the original C compiler produced, and compiles its own source to a fixpoint. It is built from a checked-in IR seed (selfhost/ludicc.seed.ll) with clang alone; run ./selfhost/bootstrap-cfree.sh to rebuild it with no C compiler in the loop. The former C compiler is gone.

Neither the compiler nor the games are C. Beneath both sits only the platform's own ABI — malloc, fwrite, objc_msgSend, CoreGraphics — reached by intrinsics, the same floor Rust and Swift stand on. (The wasm/cross-compile/shared-library driver paths lived in the old C compiler and are not yet re-implemented on the self-hosted native toolchain.)

Layout

Path What it is
selfhost/*.ludic the compiler, written in Ludic — lexer, parser, and the LLVM-IR backend (ECS storage, queries, spawn, match/machine, UI, scenes, save/load, fixed-point). Concatenated by selfhost/build.sh; built from selfhost/ludicc.seed.ll
selfhost/bootstrap-cfree.sh rebuild the compiler from the IR seed with no C compiler, and prove it reproduces its own IR
runtime/native/core.ludic the runtime written in Ludic for the native path (framebuffer, text, registers, RNG, input)
COMPILING.md the native pipeline: ludicc → LLVM IR → exe/dylib, module/export, cross-compilation, rt_* intrinsics
runtime/native/image.ludic PNG decoding, images, sprites, alpha blending and 9-slice — in Ludic
runtime/native/inflate.ludic DEFLATE decompression (RFC 1951), so PNG needs no zlib on any target
runtime/native/truetype.ludic from-scratch TrueType loader + antialiased glyph rasterizer, in Q16.16
runtime/native/ui.ludic retained UI widget tree: layout, 9-slice, focus, events — in Ludic
runtime/native/cocoa.ll the macOS window, written in LLVM IR (Objective-C runtime + CoreGraphics via their C ABI)
runtime/web/wasm.ll the web's platform layer in LLVM IR: the allocator, bulk memory and strings, since wasm32 has no libc
runtime/web/platform.js the browser's window — the same five win_* functions cocoa.ll implements, against a <canvas>
runtime/web/index.html the page a web build is served from
tools/ludic-web/run.mjs runs a headless wasm build under Node, so native and wasm output can be diffed
examples/chronorift.ludic the JRPG written in Ludic (multi-file via import, model-based)
examples/menu.ludic a retained-UI title screen (9-slice, TrueType, focusable buttons)
examples/snake.ludic a second, unrelated game — proves the language is general (same toolchain, no engine hardcoding)
build.sh ./build.sh examples/<name>.ludic
test.sh regression suite: builds the compiler, compiles/runs all examples, checks save/load + diagnostics (./test.sh)
tools/ludic-tools/ the editor toolchain, in C: ludic-fmt (source formatter) and ludic-lsp (language server) — one lexer and one vocabulary shared by both
tools/editors/ plugins for VS Code and JetBrains, plus configuration for Neovim, Helix, Emacs, Sublime and Zed (README)
tools/test-tools.sh regression suite for the toolchain: proves formatting never changes a program, drives the language server over real LSP traffic

Build & run

ludicc compiles Ludic straight to machine code via LLVM IR. See COMPILING.md for the pipeline, shared libraries (--shared), cross-compilation and the runtime protocol.

./build.sh examples/chronorift.ludic
./build/chronorift            # opens a native window

Headless render (for testing / CI):

./build.sh examples/chronorift.ludic --headless
printf 'ddddwww' | ./build/chronorift_headless   # writes out.ppm
sips -s format png out.ppm --out frame.png

A module compiles to a shared library instead of a program:

./build.sh examples/lib/combat.ludic --lib        # -> build/libcombat.dylib

In a browser:

./build.sh examples/chronorift.ludic --web         # -> build/web/
python3 -m http.server -d build/web 8000          # open http://localhost:8000/

build/web/ is a self-contained 116 KB directory — the 42 KB module, the loader, a page, and the sprites the compiler saw the game name. Copy it to any static host and it runs; it needs no server-side anything and no special headers. Saves go to localStorage, so save()/load() survive a reload.

A wasm build needs an LLVM with the WebAssembly backend and wasm-ld — Linux clang/lld have both, Apple's clang has neither (brew install llvm lld). See COMPILING.md for the pipeline, who owns the frame loop, and how assets are bundled.

Editor support

./tools/build-tools.sh          # -> build/ludic-fmt, build/ludic-lsp

ludic-lsp speaks LSP 3.17 over stdio, so one binary serves every editor: completion that knows whether you are after a ., inside a query [...] or in a ui block; diagnostics from the compiler itself; go-to-definition and rename across imported files; comment-preserving formatting. ludic-fmt is the same formatter as a CLI, for pre-commit hooks and CI.

Plugins for VS Code and JetBrains IDEs (Community editions included) and drop-in configuration for Neovim, Helix, Emacs, Sublime and Zed are in tools/editors/. Both tools also understand ```ludic fences in Markdown, so this file and LANGUAGE.md get the same highlighting, checking and formatting as the source tree.

Language features implemented

  • property (typed fields + defaults), system (phase, @annotations, reads/writes clauses), const, fn (with requires/ensures parsed).
  • model — named entity kinds (bundles of properties); identity is one int per entity, replacing empty tag properties. Filter with {Kind}.
  • import "file" — multi-file programs (fragments spliced in, include-guarded, per-file diagnostics).
  • ECS queries: for (a, b) in query [A, B, {Tag}] where <expr> { … }.
  • spawn/despawn with entity-slot reuse; nested queries.
  • Control flow: if/else, when, while, numeric for i in a .. b.
  • Types: int, fixed (Q16.16, with correct *// lowering), bool, entity, str. Fixed-point vs int arithmetic is resolved by the typechecker.
  • Deterministic seeded RNG; save()/load() snapshot of the whole ECS World.
  • 2D primitives: clear, fill_rect, frame_rect, put_px, present, key.
  • TrueType text (font_load, text_ttf) with full Unicode + anti-aliasing; arbitrary-size images + draw_9slice.
  • ui — a retained widget tree declared as data (panels, labels, buttons, images; layout, 9-slice skins, keyboard focus + click events).
  • match / machine+state+become — dispatch and state machines.
  • scene / layer / enter — mutually-exclusive game states, each with on enter/on exit hooks and layered systems (layer order = draw order).
  • var — typed module-level state, included in save/load snapshots.
  • module + @export fn — compile a .ludic file to a shared library whose exported functions are ordinary C-ABI symbols.
  • extern fn … = "symbol" — call any C-ABI library, Ludic or otherwise.
  • --target wasm32-unknown-unknown — the same game in a browser: the runtime, the ECS and the graphics stack compiled to wasm, rendering frames identical to the native build's.

The game: Chrono Rift

A playable co-op JRPG in examples/chronorift.ludic, using CC0 Kenney sprites (Tiny Town + Tiny Dungeon), decoded from PNG at runtime by the Ludic-written PNG/DEFLATE decoder — no zlib, no external dependency on any target.

Controls:

  • Overworld: WASD move, K save, L load.
  • Battle (local co-op): Player 1 / Knight — W/S select, Space confirm. Player 2 / Mage — I/K select, J confirm. Each player takes their own turn each round (Attack / Defend / Run; Mage has Attack / Heal / Defend).

Status

  • Compiler pipeline: Ludic → LLVM IR → native binary / shared library
  • No C generated, compiled or linked in a build; runtime written in Ludic
  • Cross-compilation to ELF (x86-64, aarch64) and Windows COFF
  • ECS runtime (properties, systems, phases, queries, entity pooling)
  • Windowed 2D rendering (Cocoa driven from LLVM IR) + headless PPM verification
  • CC0 Kenney PNG sprites (png_load, decoder written in Ludic) + scrolling camera
  • Overworld: tilemap, movement, collision
  • Random encounters + turn-based battle (HP/MP, seeded-RNG damage)
  • Party + local co-op (P1 Knight, P2 Mage, per-player turns)
  • Leveling (XP → stat growth) and game-over / respawn
  • Self-hosting: a Ludic-written compiler compiles its own source to a byte-exact fixpoint, and rebuilds itself from a checked-in IR seed with no C compiler in the loop (selfhost/, ./selfhost/bootstrap-cfree.sh)
  • Snapshot save / load (full ECS World)
  • Two maps (overworld + dungeon) with map switching via the arch
  • Boss encounter (Rift Warden) + victory condition
  • Item shop (gold → potions) at the house; potions usable in battle (Knight ITEM)
  • More skills / enemy variety (future)