You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5.2KB


story: E06-S01 owner: codebuff status: done started: 2026-11-10 completed: 2026-11-10 depends-on: [E01-S05, E03-S06, E05-S02]

E06-S01 Claim

Intended change

Freeze the four-byte interface value ABI in src/common/interfaces.inc, add the layout and transfer runtime in src/runtime/interfaces.s, and prove the layout, canonical null, invalid conversion, four-byte copy, slot order, four-byte result area, and pushed argument order with a new x128 fixture. Dispatch, method-table emission, and interface lifetime remain E06-S02/E06-S03/E06-S06.

File area

  • src/common/interfaces.inc, src/runtime/interfaces.s (new)
  • tests/runtime/interface-test.s (new)
  • scripts/build-interface-test.ps1, scripts/verify-interface-test.ps1 (new)
  • docs/decisions.md (D142), docs/architecture.md (7.2, 7.5, open questions), docs/memory-map.md (Interface Values)
  • planning/claims/E06-S01.md
  • generated files under build/

Acceptance evidence

  • Four-byte interface value layout is documented and tested little-endian: src/common/interfaces.inc fixes IF_OBJECT at +0 and IF_TABLE at +2; phase 1 of the fixture converts object $1234 with table $5678 and checks the raw bytes 34 12 78 56 at the destination. All four bytes zero is the canonical null: phase 2 checks that a null object writes four zeros and ignores a non-zero table pointer.
  • Interface slot and per-class table layouts are frozen: slots are two-byte entries at table+2*n in interface declaration order with no header (IF_SLOT_SIZE); phase 4 reads slot 0 as $BEEF and slot 1 as $CAFE from a data table, and refuses a null value (IF_ERR_NULL) and a zero table (IF_ERR_TABLE).
  • Conversion, parameter, return, local, field, and array storage rules are specified in architecture 7.5, docs/memory-map.md, and D142: four bytes with no padding, callers push all four bytes right-to-left, the four-byte result uses a fixed area. Phase 3 copies values without reading through a null source pointer; phase 5 moves a value through IF_RESULT ($C6-$C9) and shows a failed store leaves the previous result intact; phase 6 pushes four bytes, reads them back at FP+2..FP+5, and confirms the caller discards exactly IF_VALUE_SIZE bytes.
  • Register clobbers and the four-byte return convention are finalized: src/runtime/interfaces.s states that every helper may clobber A/X/Y and returns status in C plus if_error; a four-byte result travels through IF_RESULT, never A/X. The module asserts at link time that IF_RESULT follows the print vectors ($C0-$C5) and ends below the for-end values ($D0).
  • if_conv cannot expose an invalid pair: a non-null object with a zero table writes a zero table half and returns C=1/IF_ERR_TABLE (phase 2).

Coordination notes

  • Dependencies E01-S05, E03-S06, and E05-S02 are complete; no other claim was active. src/common/class.inc (E05-S02) already reserves the descriptor's interface-directory path, which this ABI reuses unchanged.
  • E06-S02 (trampoline) and E06-S03 (table emission) consume these constants and helpers; no dispatch code was added here.
  • The installed assembler is ca65 2.19 from C:\Program Files\cc65-snapshot-win32\bin, which is not on the default shell PATH in this session; the verification command added it to PATH.

Work log

  • Added interfaces.inc and interfaces.s, then the fixture. The fixture's first macro used a as a parameter name, which ca65 rejects because it is the accumulator keyword; renamed the parameters.
  • The fixture first used CR_RAM0_KERNEL; the frozen constant in src/common/c128.inc is spelled CR_RAM0_KERNAL. Fixed in the fixture.
  • ld65 warned about the module zero-page cells imported as absolute; the fixture now uses .importzp for if_obj, if_tab, if_dst, and if_src.
  • A first x128 session could not reach the remote monitor (port 6557) and a second reached it but the shared Stop-Nova128X128 quit handshake timed out. A manual session read the mailbox and screen, and the committed verify script then passed unchanged on port 6603, so both were transient emulator/port issues rather than fixture failures.

Completion

  • Tests run: scripts/verify-interface-test.ps1 (x128, fresh D81); git diff --check.
  • Results: PRG ends $246A; mailbox 4E 38 03 A5 00 00 00 00 01 01 01 01 01 01 00 00; screen shows NOVA128 INTERFACE ABI and INTERFACE OK; all six phase flags are 1.
  • Files changed: src/common/interfaces.inc, src/runtime/interfaces.s, tests/runtime/interface-test.s, scripts/build-interface-test.ps1, scripts/verify-interface-test.ps1, docs/decisions.md, docs/architecture.md, docs/memory-map.md, this claim.
  • Remaining risks: IF_RESULT is a single fixed area, so a caller must copy a result before evaluating another interface-returning call; the parser/emitter does not yet enforce that rule because interface expressions are not emitted. if_slot trusts the compile-time slot index (no runtime slot count), and no helper validates a destination pointer. Generated new/delete for interface-typed values and interface method tables are E06-S03/E06-S06. Physical C128 testing remains P2 validation.

Powered by TurnKey Linux.