Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

5.4KB


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

E06-S03 Claim

Intended change

Emit the per-class interface method tables the E06-S01 ABI froze and if_call consumes. A new src/compiler/iftables.s walks each class's implements entries and writes one table per interface in implements order, one slot per interface method in slot order, resolving every requirement to the class member row of the same name. output.s records each table in the MAP. A new x128 fixture fills the real parser tables and proves table contents, distinct per-class tables, both rollback paths, and the MAP records.

File area

  • src/common/iftables.inc (new): buffer, table, and row limits and IT_ERR_*
  • src/compiler/iftables.s (new): it_begin, it_set_addr, it_class
  • src/common/formats.inc: OUT_MAX_TABLES, OUT_TABLE_RECORD_SIZE, OUT_ERR_TABLES
  • src/compiler/interfaces.s: exports the existing find_method
  • src/compiler/output.s: out_table, out_write_tables, TABLE records
  • tests/compiler/iftable-test.s (new)
  • scripts/build-iftable-test.ps1, scripts/verify-iftable-test.ps1 (new)
  • docs/decisions.md (D144), docs/architecture.md (7.5, 8.2, status), docs/memory-map.md (table rows)
  • planning/claims/E06-S03.md
  • generated files under build/

Acceptance evidence

  • One table per implemented interface, in implements order, slots in interface order, two bytes per slot: class A's IFOO table holds m_alpha_a then m_beta_a and its IBAR table holds m_alpha_a; the fixture checks it_data, it_class_ids, it_iface_ids, it_slots, it_table_addrs, and it_offsets.
  • Class B gets its own table with its own methods: phase 2 checks it_data+6..+9 against m_alpha_b/m_beta_b and the third address $B006.
  • One method satisfies every interface slot of that signature: A's single ALPHA method fills IFOO slot 0 and IBAR slot 0 (phases 0 and 3).
  • A slot with no address is refused, not written as zero: a table entry supplied as 0 gives IT_ERR_UNSET, it_count stays 3, and it_used returns to 10 (phase 4).
  • A table that cannot fit the buffer is refused and rolled back: interface IFOO temporarily claiming 255 slots gives IT_ERR_SPACE with the same restored watermark and count (phase 5).
  • The MAP gains one TABLE record per table: the fixture writes IFTTEST.PRG/IFTTEST.MAP through output.s and the verifier compares the three records with the linker labels of the four method stubs (phase 6).
  • Watermark and record count match the emitted tables: it_used = $000A, it_count = 3 (phase 7).

Coordination notes

  • Depends on E06-S01 (value/table ABI), E06-S02 (if_call), and E05-S02 (class descriptors); E06-S03 only builds bytes and MAP records and does not link a descriptor's directory yet.
  • it_class takes destination addresses from the caller because method placement is pass 3; pass 3 wiring is E06-S04/E06-S05.
  • find_method was exported from interfaces.s rather than duplicated, so table emission and check_interfaces resolve names identically.
  • ca65 2.19 lives in C:\Program Files\cc65-snapshot-win32\bin; VICE tools resolve through the test module and x128 (never x64sc) runs the fixture.

Work log

  • First fixture build hit two ca65 range errors (bcc @fail over more than 127 bytes); both became the project's bcs :+/jmp trampoline form.
  • The run then hung: @fail jumped to the phase-7 label, so a phase-0 failure re-ran phase 7 forever. @fail now jumps straight to the report block.
  • it_class initially read C_TYPE_ICOUNT without storing it, so the loop compared stale zeros and emitted no tables; ic_n/ic_row/ic_i are now initialised from C_TYPE_ICOUNT/C_TYPE_IFIRST.
  • The emitter advanced it_dst by one byte per slot, so pairs overlapped; it_dst is now recomputed from the watermark after each slot.
  • it_addr_get returned hi|lo because the unset test left the OR in A, so $72FC became $72FE; it now reloads the low byte before returning.
  • @report called mmu_shutdown first, but this fixture's fail_mask and message strings live above $4000, so they must be read while MAIN is mapped. The status and message are now decided first, the text is copied to a SCRATCH buffer at $1B00, and shutdown happens before CHROUT.
  • A stale D81 also made out_begin report OUT_ERR_EXISTS; the verifier now reports the mailbox check address instead of throwing on a missing MAP.

Completion

  • Tests run: scripts/verify-iftable-test.ps1 (x128, fresh D81 rebuilt by the verifier); git diff --check.
  • Results: PASS with all eight MB_DATA flags set; screen shows NOVA128 IFTABLE TEST OK; IFTTEST.MAP is exactly: NOVA128 MAP 1, ENTRY 1C0D, SECTION STUB 1C01 000C, SECTION START 1C0D 004A, TABLE A IFOO B000 02 731C 731D, TABLE A IBAR B004 01 731C, TABLE B IFOO B006 02 731F 7320. The PRG image ends $7EA5 (25,254 bytes).
  • Remaining risks: tables are built in a 512-byte buffer with 16 tables and 255 address rows, so a very large interface set is refused rather than spilled; it_class trusts the parser tables (an implements row that is not an interface is IT_ERR_STATE but a method row is not otherwise validated). Descriptor directories, interface conversion, and lifetime remain E06-S04/E06-S05/E06-S06, and physical C128 testing remains P2 validation.

Powered by TurnKey Linux.