Future work
xtc is pre-1.0. This page tracks where it’s going, what’s known-incomplete, and what’s recently landed — sourced from the project’s doc/Issues log. Pre-1.0 software is more useful when its rough edges are visible than when they’re hidden.
The new-IR / new-xt redesign (current focus)
Section titled “The new-IR / new-xt redesign (current focus)”The largest in-progress effort is a ground-up rebuild of the back end. The shipping 0.12 compiler lowers the AST straight to 6502; the redesign inserts an architecture-neutral IR between the semantic analyser and code generation, with pluggable backends, and pairs it with a redesigned 6502 core.
- Architecture-neutral IR + multiple backends. Two backends exist today. An arm64 backend runs the lowered IR natively on the host — its job is fast, end-to-end validation (and
lldbdebugging) of the arch-neutral lowering, and it’s the first step toward genuinely native targets (an ARM microcontroller later). An xt6502 backend targets the new core below. Standard-library classes resolve by architecture × platform, so the same Foundation source serves both. See the changelog. - The new
xt6502 core. A custom FPGA 6502 with a 4 KB hidden hardware stack (12-bit stack pointer) and SP-relative addressing —LDA/STA d,SP, plus(d,SP),Yto dereference a stack-resident pointer in place andd,SP,Xfor indexed in-frame aggregates. This supersedes the old three-window bank-switchedxt(Memory models); the point is to keep locals and temporaries in a real stack frame instead of cramming everything into zero page.
This is in development — not all of it compiles and runs end-to-end yet (the xt6502 backend’s register/stack allocation is mid-flight). The 0.12 AST-codegen compiler remains the shipping toolchain for Atari xl / xe / xt in the meantime.
What’s next
Section titled “What’s next”Two roughly-equal-priority candidates:
-
Graphics library — remaining Atari modes.
Gfx+Gfx8already cover GR.8 (320×192 1bpp) with the full primitive set: plot/line, hline/vline, rect/fillRect, circle/oval/arc/pie + filled variants, bezier, drawText, floodFill, setupNative, setupSplit. Remaining modes (GR.0-GR.7, GR.15) are additionalGfxsubclasses; first deliverable per mode is line draw. -
Fuzzing. A grammar fuzzer against
grammar/xtc.bnfto generate random programs, compile through xtc + xta + xts, and flag any segfault / hang / FAIL. Up until now this has been by hand-rolled probes; a fuzzer would surface the next family of bugs before users hit it.
Planned features
Section titled “Planned features”inline:method() on banked-heap targets (xe)
Section titled “inline:method() on banked-heap targets (xe)”The xl/xt path works; xe-style banked-heap is deferred. The inlined body’s (selfPtr),Y accesses to receiver ivars need PORTB brackets so the read lands in the heap’s bank, matching what regular method dispatch already does via the call wrapper. Multi-day effort — needs care around nested inlines that may target different banks, and ARC retain/release of class-pointer params.
Bank memory via pointer
Section titled “Bank memory via pointer”Direct user-level access to bank pages, something like u8@ data = bank(4);. Gives source code an escape hatch to deliberately route reads/writes through a chosen bank when the compiler’s automatic placement isn’t what you want.
Automatic GR.0 restore on program exit
Section titled “Automatic GR.0 restore on program exit”Opt-in is already satisfied by Gfx.restoreGR0() — programs that took over the display via Gfx8.setupNative() can call it before main returns. The always-on variant (runtime exit shim does it for every program) is still open; the cost is dragging CIO into every program including console-only ones, plus a few hundred bytes of code. Could become opt-in via a compiler flag if it’s worth it.
Lots more library work
Section titled “Lots more library work”The main focus at this point, once Gfx is written for more than just GR.8, is going to be collection types (Array, Dictionary, Set,..)
Native ARM target (68k still speculative)
Section titled “Native ARM target (68k still speculative)”No longer purely speculative: the new-IR work (above) already has an arm64 backend, today used to validate the architecture-neutral lowering on the host. Turning that into a shipping native target — xtc programs running directly on, say, an RP2354 microcontroller — is the natural follow-on once the IR and its backends settle. A 68k backend remains speculative.
Accepted limitations
Section titled “Accepted limitations”These are tradeoffs in algorithm choice, not bugs — they won’t be “fixed”:
- CORDIC trig is ~14-bit accurate. Tests handle this via
APPROX_TOLERANCE. fpTanprecision degrades near ±π/2 — inherent to the identity used.- NaN compares “equal” per
fpCmp— deterministic, non-IEEE. - C64 target compiles but doesn’t run yet. Output PRG isn’t exercised under any sim in CI; VICE debugging is needed to validate. Atari targets are the focus, mainly because I don’t have much experience with the C64.
Recently shipped
Section titled “Recently shipped”A short window of “done in the last few months” so users tracking the project can see momentum:
- Array slicing in for-in.
arr[m..n]/arr[..n]/arr[m..]/arr[m...n]produce a slice the for-in loop walks element-by-element, on both fixed-size arrays and heap pointers. Bounds may be runtime expressions; the inclusive form biases the cap by +1 at loop setup so the inner compare stays a plainidx < cap. See Statements — for-in (array slice). - Range as fixed-array initialiser.
u8 buf[10] = 0..10/u8 b2[5] = 1...5fills consecutive slots with the range values. Both bounds must constant-fold and the produced count must match the declaredelementCount; sema rejects mismatches and non-literal bounds. - Extended cloaked code regions across the bank window. Multi-region
[cloaked]blocks in the layout:bank = none(banking-off region in main RAM) plus numbered-bank regions (bank = 2for canonical xe;bank = 4-12+id = ext<n>for the rambo / compy pool form). Source-level:cloaked(<id>)pins a decl; plain:cloakedauto-packs into the first declared region with an overflow-spill ladder onto subsequent regions before falling back to:main. Cross-region calls work via the_xcall_cloakedtrampoline (caller_ret + caller PORTB stored in main-RAM static slots so the bank-window switch doesn’t unmap the saved state). Same-region calls drop the PORTB bracket entirely — codegen emits a plain JSR. The shipped rambo / compy layouts expose 96 KB → 992 KB of cloaked surface depending on hardware. See Linker scripts —[cloaked]. - Free-list heap allocator with
_heap_init/_heap_alloc/_heap_freeon all four heap targets (xl-shadow, xe-nobank, xt, xe-heap).delete ptr;triggers ARCrelease()walks before block free; class arrays iterate release across every element. Banked-heap + full banked ARC end-to-end as of 2026-04-23. Gated by-falloc=heap. - Class inheritance + protocols + runtime downcasts. Single-inheritance chains (
class Dog : Animal), virtual dispatch through per-class vtables,protocol Nameinterface decls,super.method(...), runtime-checkedT@downcasts. See Inheritance & protocols. - xt region C / extended RAM. Three independent bank windows in $4000-$7FFF: $82-routed code (8 KB pages, 2 MB), $83-routed data (4 KB pages, 2 MB), $84/$85-routed region C (4 KB pages, 4-28 MB on 8/16/32 MB HyperRAM). Pay-for-what-you-use is automatic via per-function transitive analysis. See Memory models.
- Multi-bank xt-with-heap correctness. Seven distinct latent bugs fixed in one session —
$82/$83routing in helpers, allocator-Y bank capture, ivar-store / chained-ivar-read / chained-method-call / delete-via-ivar paths in method bodies. Six new fixtures pin the regressions. - xe-banked heap-class methods. Methods on heap classes can ride either
:cloakedor:bankedplacement on xe-heap. Routes ivar(self),Yaccesses through_ivar_load_byte/_ivar_store_byteso reads land in the receiver’s heap bank even when the body’s PORTB points elsewhere. Subsequent perf pass caches_ivar_target_portbonce at body prologue — ~60 cycles saved per ivar access. - Auto-cloak inference + overflow-driven placement. Sema infers cloak-safety per decl; codegen auto-promotes via
-fauto-cloak={never,auto,always}. When:mainpasses 75% of budget the compiler proactively promotes more decls into:cloaked. When a cloaked region overflows the driver first spills overflow decls to the next declared cloaked region with headroom; only when no further region has space does it demote back to:main. Two-pass banked-spill on banked targets demotes coldest methods to:bankeduntil main fits. Gfx/Gfx8graphics library. Context-based class hierarchy covering GR.8 with the full primitive set listed above.Gfx8.lineis an asm fast-path for axis-aligned + 8 octants with phase-5 draw-from-both-ends.use Klass;/#use Klass. Static-method bare-call promotion: afteruse Stdio;, bareprintf(...)resolves toStdio.printf(...). The hash form (#use Klass) is#import "Klass.xt"+use Klass;combined. Multipleusedirectives compose; ambiguity is a compile error.- xta symbol-file directory sweep. The driver auto-loads every
.symundersupport/<platform>/symbols/andsupport/generic/symbols/into the assembler’s symbol table. Drop a newpokey.symnext toatari.symand its names resolve in inline asm without touching the linker script. - Driver introspection.
--dump-placementshows per-decl placement;-du/--dump-usageshows per-bank usage maps. Useful for budget tuning when hand-placing decls.
Known issues
Section titled “Known issues”None outstanding at the time of writing. Bug reports through the feedback form feed straight into the canonical doc/Issues log.