Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

7.6KB


story: E07-S05 owner: codebuff status: done started: 2026-11-10 completed: 2026-11-10 depends-on: [E07-S01, E04-S01, E04-S06, E02-S04]

E07-S05 Claim

Intended change

A build/n128c.prg that runs on x128 and is the file prepare-disk.ps1 injects and launch-compiler.ps1 autostarts. It asks for one source name, loads that SEQ file from drive 8 through the buffered PETSCII reader, runs lexer, parser and pass-2 emission, writes NAME.PRG and NAME.MAP through output.s, and prints a one-screen summary naming the source, the output and the diagnostic count. Failures print one stable line, write NAME.ERR when they are diagnostics, and never overwrite an earlier output.

File area

  • src/compiler/main.s (new): prompt, load, compile, output, summary
  • src/compiler/output.s: exports out_prg_name/out_prg_len for the summary
  • scripts/build-driver.ps1 (new): links the compiler, output.s, src/runtime/startup.s and main.s, checks driver_entry is $1C0D, and publishes build/n128c.prg
  • scripts/verify-driver-test.ps1 (new): fresh D81, five x128 runs
  • scripts/launch-compiler.ps1, scripts/lib/Nova128Launcher.psm1, scripts/lib/Nova128Test.psm1: -Keys/-KeyDelay passthrough
  • docs/editor-workflow.md, docs/architecture.md, docs/decisions.md (D154)
  • generated files under build/driver/, build/driver-test/

Acceptance evidence

  • build/n128c.prg is produced by scripts/build-driver.ps1 and is the exact path prepare-disk.ps1 injects as n128c and launch-compiler.ps1 autostarts by default; the verifier runs prepare-disk.ps1 -RequireCompiler and compares the injected n128c byte-for-byte with build/n128c.prg, then drives the launcher. The build asserts the entry label is $1C0D.
  • On x128 the driver takes one source name (SOURCE: counter.n8), loads it from the session disk with src_load and no host conversion, runs the lexer, parser and emitter, and writes COUNTER.PRG (263 bytes) and COUNTER.MAP (95 bytes) named after the source.
  • ERR, MAP and the summary are produced for the same run: COUNTER.MAP records ENTRY 1C0D, SECTION STUB 1C01 000C, SECTION START 1C0D 004A and SECTION CODE 1C57 00AF; the screen shows SOURCE COUNTER.N8, OUTPUT COUNTER.PRG, 0 ERRORS.
  • A clean source produces a PRG that runs: a second x128 session autostarts COUNTER.PRG and its runtime startup reports MB_ST_PASS (producer 3). A source with errors (miss_end.n8) writes BAD.ERR with E024 and E227, reports COMPILE FAILED, and writes no BAD.PRG or BAD.MAP.
  • Missing source prints LOAD FAILED; an existing output prints OUTPUT EXISTS and leaves COUNTER.PRG byte-identical (checked by re-reading it from the image after both a failing compile and a refused compile); over-long names print NAME TOO LONG before any file is created.
  • scripts/verify-driver-test.ps1 drives the driver through scripts/launch-compiler.ps1 on a fresh development image and checks PRG, ERR, MAP, the summary (read from screen RAM in a monitor session), the collision path and the generated-program run.
  • docs/editor-workflow.md documents the on-machine command, every failure message and the recovery steps, so E07-S04 can be completed without an undocumented command.

Coordination notes

  • Generated print is closed as D155: emit.s calls the address held in the em_pr_* cells, src/runtime/prgprint.s is copied into a PRINT section, and an ENTRY stub calls the body, runs the startup mailbox and restores the zero page it borrows. hello.n8 compiles and displays its string from the standalone PRG. E04-S05's captured-literal convention is unchanged: the driver copies the literal into a DATA section after CODE and rewrites the emitted LDA/LDX operand pair from gen_text to that copy.
  • The code base is planned before parsing, because pass 2 emits absolute targets: PRG_ENTRY_ADDR + gen_startup_size ($1C57 with the current startup) is installed with sz_plan_code and then parse_file_base runs one emitting pass. parse_file cannot be used because it clears the base request.
  • Source names are limited to 15 characters and folded to uppercase; out_begin applies the 12-character base limit before building .PRG, .MAP and .OPEN names.
  • The whole compiler, output.s and the startup fit the existing cfg/compiler.cfg unchanged; the driver PRG is 23,767 bytes with no new memory area or linker change.

Work log

  • Assembling main.s first failed on a far BCS and on #gen_startup_size (an imported absolute value), so the driver uses ON_CARRY/ON_NONZERO macros with an absolute JMP and #<gen_startup_size.
  • The first disk run reported E227 at line 4 for hello.n8; the cause was the print-hook cells having no generated-program runtime, not a parser fault. The driver now zeroes them explicitly and the clean fixture is code-only.
  • BASIN returns the terminating RETURN without echoing it, so the driver prints the CR itself; without it the diagnostic line ran into SOURCE:.
  • The verifier's MAP checks first failed on case and then on $ anchors, because c1541 reads the CR-terminated MAP with CR gaps and no LF. The test normalises CR to LF before matching.
  • The first runtime draft patched its own operands, but those stores carried compiler-image addresses (STA $6F04), so the copied PRG printed nothing. It now keeps its state in $C0/$F2-$F4, which the ENTRY stub saves and restores.
  • The literal still pointed at the compiler's gen_text; the driver now moves it into DATA and relocates the emitted address. The PRG then printed the string (screenshot hello-run.png).
  • Screen-RAM readback did contain the text, but with bit 7 set ($88 for H, $A0 for space), so the first converter reported ? and the literal search missed it. The check now masks $80 before decoding and matches HELLO FROM NOVA128 on the real VIC-II screen.

Completion

  • Tests run: scripts/verify-driver-test.ps1 (builds the driver, checks the prepare-disk.ps1 injection, then five x128 sessions: summary monitor run, success launcher run, syntax-failure launcher run, collision launcher run, generated-PRG monitor run), and the same script through the regression harness: run-regression.ps1 -Filter driver.
  • Results: summary: SOURCE COUNTER.N8 / OUTPUT COUNTER.PRG / 0 ERRORS; success: COUNTER.PRG 419 bytes, COUNTER.MAP 143 bytes, no COUNTER.ERR (MAP: STUB, ENTRY, START, PRINT, CODE); failure: BAD.ERR E024 ... END PROGRAM EXPECTED, no BAD.PRG, COUNTER.PRG unchanged; collision: OUTPUT EXISTS and COUNTER.PRG unchanged; injection: prepare-disk.ps1 wrote build/n128c.prg byte-identically as n128c; run: generated COUNTER.PRG reported MB_ST_PASS in x128; print: HELLO.PRG carries PRINT+DATA, calls the runtime, and shows 'HELLO FROM NOVA128' on screen (the text is read back from $0400, not inferred from the screenshot), with hello-run.png as the visual record. tests/regression/harness.tests.ps1 still passes, and the suite through the harness reports driver pass 118.3s, 1 passed, 0 failed; driver remains listed in tests/regression/suites.ps1.
  • Remaining risks: text print needs the generated-program print runtime; the code buffer stays at 255 bytes, so larger programs fail with a diagnostic rather than a partial file; the summary check reads screen RAM through a monitor session and therefore depends on the 40-column screen layout the driver prints; and prepare-disk.ps1's own injection is exercised through the launcher default, not by a separate unit test.

Powered by TurnKey Linux.