Status: approved version 1 baseline. The compiler memory map is frozen by
E01-S05 (section 4.4, docs/memory-map.md). Generated-program addresses are
still deliberately absent until the E04 stories validate them.
The deliverable compiler is an 8502 program that runs on a Commodore 128 in native mode. Host-side tools may:
ca65 and ld65;c1541;Host tools must not perform Nova128 parsing, type checking, or code generation in the release workflow. The C128 compiler performs those functions.
Generated version 1 programs target C128 native 8502 mode. They do not target C64 mode or the Z80.
src/cfg/examples/build/| Artifact | Purpose |
|---|---|
N128C.PRG |
On-machine compiler executable |
NAME.N8 |
PETSCII SEQ input source |
NAME.PRG |
Generated application |
NAME.ERR |
Complete stable-code diagnostics |
NAME.MAP |
Symbols, addresses, class layouts, interface slots, and section sizes |
Output replacement must be explicit. The compiler must not silently overwrite an existing PRG after a failed compilation.
src/
compiler/
main.s command loop and phase orchestration
mmu.s all MMU transitions and bank-safe copies
diskio.s KERNAL file and command-channel wrappers
source.s buffered source stream and positions
lexer.s PETSCII normalization and tokenization
parser.s recursive-descent declarations/statements
expr.s precedence expression parser
names.s interning and identifier comparison
symbols.s scopes, symbols, and lookups
types.s type representation and compatibility
classes.s field/method layout and access checks
interfaces.s conformance and interface slot assignment
sizing.s dry-run code sizing and address assignment
codegen.s documented 8502 instruction emission
output.s PRG, ERR, and MAP writers
diagnostics.s stable error catalog and recovery
runtime/
startup.s generated-program entry and initialization
frames.s software argument/local-frame support
objects.s object construction and destruction
interfaces.s interface conversion and indirect call trampoline
heap.s deterministic allocator and free list
arithmetic.s non-inline arithmetic helpers
print.s scalar and literal output
faults.s null, bounds, divide, stack, and heap failures
common/
c128.inc hardware and KERNAL symbols
formats.inc compiler record and output constants
tokens.inc token numbers
errors.inc stable diagnostic numbers
Files are introduced by stories; this tree is a target, not permission to add empty placeholders.
The design uses the two 64K RAM banks and a verified common-RAM window.
No module other than mmu.s directly changes the MMU. Banked data is accessed
through handles or explicit copy routines; ordinary pointers must not escape
the bank in which they are valid.
Story E01-S02 must prove:
Only then may linker addresses and zero-page allocations become normative.
E01-S02 evidence is in docs/mmu-probe.md. In VICE x128 3.10, distinct banks,
8K bottom+top common RAM, bank-switched JSR/RTS, and full MMU restoration
pass. Page pointers aimed at bank 1 while bottom common is active resolve to
bank 0 at the translated page, so Nova128 keeps P0/P1 in bank 0. Non-default
mappings run with IRQs masked; an IRQ path under bank 1 is not yet proven.
E01-S03 evidence is in docs/kernal-wrapper.md. A common-RAM wrapper enters
the KERNAL in BASIC's mapping and restores the exact compiler MMU state. From
bank 0 and bank 1 compiler mappings, CHROUT, a drive-8 status read, and a
device-not-present failure all work, with A/X/Y/C/ST preserved and no channels
left open.
The gate above is closed for the compiler. cfg/compiler.cfg is authoritative
and docs/memory-map.md explains it and gives the evidence. In summary:
$0E (bank 0) or $4E (bank 1), 8K bottom common
RAM, P0 relocated to bank 0 page $1A, IRQs masked.$1300-$18FF (copied at init), DISKBUF $1900, private
zero page $1A00, SCRATCH $1B00-$1BEF, MAILBOX $1BF0-$1BFF, MAIN
$1C0D-$B7FF (STARTUP first), SWSTACK $B800-$BFFF.$2000-$6AFF (D118), compiler tables
$6B00-$BFFF (21,760 bytes).$02-$FF via P0; KERNAL calls run
on the system zero page.mmu_nmi_guard through $0318; RESTORE is ignored
during compilation.$1BF0, shared by platform tests, the
compiler, and generated programs.The generated-program memory map remains open (E04-S01/E04-S02).
Compiler text uses KERNAL-compatible character output on the display already
selected by the user; it does not force 80-column mode. E01-S04 verified the
editor's $00D7 mode flag in x128: 40-column uses a deterministic 1 MHz
fallback, while 80-column may set $D030 bit 0 for 2 MHz KERNAL output. The
speed bit is cleared before returning to BASIC, and any uncertain mode falls
back to 1 MHz. Direct VDC screen memory is display-only and is not compiler
semantic storage. See docs/platform-display-clock.md for evidence.
The compiler reparses a buffered/streamed source rather than retaining a large pointer-rich abstract syntax tree.
Repeated passes re-read the source, not the disk. src_load (source.s)
reads the file once into the bank-1 cache and enforces the editor-profile
limits. Each pass calls src_rewind, then src_next_line delivers one logical
line at a time into a common-RAM buffer (D118, E02-S01).
Final byte layouts are story outputs, but records require these logical fields:
Use compact fixed-width records where practical. Every table has an explicit capacity and produces a resource diagnostic rather than corrupting adjacent memory.
boolean, byte, and char occupy one byte.integer, word, concrete references, and addresses occupy two bytes.The final register-clobber table is part of story E02-S02.
self is held in a reserved two-byte ABI pointer during an instance call.JSR.Every heap object begins with a two-byte class-descriptor pointer, followed by fields in declaration order with no hidden alignment padding:
+0 class descriptor pointer (2)
+2 first declared field
... remaining fields
The class descriptor contains the instance size, optional destructor address, and a directory of implemented interfaces. Its final packed format is frozen by E05 and E06 stories.
An interface value is a fat reference:
+0 object pointer (2)
+2 interface method-table pointer (2)
Each interface defines a slot order from its source declaration. For every implemented interface, a class emits a table of two-byte method addresses in that order.
Converting a concrete reference to an interface reference:
An interface call:
self;The 8502 has no JSR (address) instruction, so the trampoline must establish a
synthetic return path safely. It is tested independently before interface code
generation relies on it.
delete through an interface uses the object pointer and its class descriptor,
not the interface table, to find the optional destructor and object size.
new requests the class instance size, zeroes the allocation, stores the
descriptor pointer, and invokes init.delete invokes destroy at most once for that call and returns the entire
block to a coalescing free list.The compiler uses documented KERNAL entry points through diskio.s wrappers.
Each wrapper:
The command channel must be opened before source/output files when status is needed and closed last, matching the proven editor workflow.
The existing Vim clone is treated as an external producer/consumer of SEQ files. Version 1 does not link the editor and compiler in memory.
The development image workflow is strictly sequential:
../vim/work.d81 to build/newlang-dev.d81;N128C.PRG, examples, and fixtures;x64sc and autostart VIM for editing;x128 and autostart N128C.PRG for compilation;Scripts must refuse obvious concurrent use where detectable. Tests create a fresh image per run.
Compile-time diagnostics use stable IDs such as E014. Runtime faults use a
separate stable namespace such as R003. Numeric assignments live in
src/common/errors.inc once story E02-S03 freezes the catalog.
Compiler errors include source name, line, column, and compact message. Runtime faults always include a stable fault code and the best available program address that can be resolved through the MAP file. Rich stack traces are deferred.
Testing is layered:
$1BF0 (src/common/mailbox.inc, docs/memory-map.md).Each emulator test has a cycle/time limit and captures enough output to explain failure without relying only on a screenshot.
The story order makes each high-risk mechanism prove itself before downstream features depend on it.
Powered by TurnKey Linux.