Turn a class reference or null into an interface value, and carry that value
through every place the language allows, on top of the E06-S01 value ABI and the
E06-S03 tables. it_find selects the table a class emitted for a given
interface, so a conversion site never guesses. if_assign, if_arg_push,
if_elem_store, and if_elem_load add the assignment, argument, and array
paths the ABI described but did not yet implement. The compile-time rejection
stays in types.s (E080) and is re-verified by the semantic suite.
src/common/interfaces.inc: IF_ERR_RANGE, element-stride wordingsrc/common/iftables.inc: IT_ERR_IFACEsrc/compiler/iftables.s: it_findsrc/runtime/interfaces.s: if_assign, if_arg_push, if_elem_store,
if_elem_load, if_elem_addrtests/compiler/iftable-test.s: it_find checks in phase 7tests/runtime/convert-test.s (new)scripts/build-convert-test.ps1, scripts/verify-convert-test.ps1 (new)scripts/verify-iftable-test.ps1: failure detail (check address and value)docs/decisions.md (D145), docs/architecture.md (status, 7.5),
docs/memory-map.md (conversion rows)planning/claims/E06-S04.mdbuild/if_assign mode 1 and checks all four bytes of the
stored value (obj_a_stub then tab_a), with if_error IF_OK. The table
fixture proves it_find returns exactly the emitted table for A/IFOO
($B000), A/IBAR ($B004), B/IFOO ($B006).null conversion produces a canonical null: convert phase 2 converts a
zero object and checks four zero bytes, if_error IF_OK, and
if_is_null's C=1; copying that null value verbatim stays canonical.IF_ERR_NULL while leaving the destination intact; phase 4
stores the pair in a four-byte field (leaving the two bytes before it at
$5A) and in three independent array elements, loads elements 0, 1, and 2
back, and refuses a wrapped element address ($FF00 + 4*200) with
IF_ERR_RANGE; phase 5 pushes the value as an argument and the callee reads
object and table at FP+2..FP+5, with the frame stack restored; phase 6
round-trips a converted value through IF_RESULT twice, the second time with
a different table.types.s (converts), and tests/semantic/refs.n8 expects
TYP_MISMATCH for n = b (a class that does not implement Named) while
accepting s = b for the interface it does implement.if_call), and E06-S03 (tables);
all are complete.it_find is the compiler-side half of conversion: pass 3 can ask for the
table by class and interface instead of indexing it_table_addrs itself.emit.s belongs to
E06-S05, which also emits the interface call itself.C:\Program Files\cc65-snapshot-win32\bin; VICE tools
resolve through the test module and x128 runs every fixture.it_find over the existing parallel arrays; a pair with no emitted
table returns IT_ERR_IFACE with A/X=0, so a caller cannot manufacture a
table for an interface the class does not implement.if_elem_addr
shifts the index into a 16-bit offset with asl/rol on memory so a byte
index cannot lose its high bits (200*4 = $0320).STEP $23 recorded.
Step markers narrowed it to the refusal case: its guard used the success
branch (bcc) where a correct refusal returns C=1, so the refusal jumped to
@fail. Changed to bcs.scripts/verify-iftable-test.ps1 (x128, fresh D81; phase 7 now
covers it_find); scripts/verify-convert-test.ps1 (x128, fresh D81);
scripts/verify-parser-test.ps1 (semantic goldens, including refs.n8);
git diff --check.NOVA128 IFTABLE TEST OK / CONVERT OK; IFTTEST.MAP still matches its
four section records plus TABLE A IFOO B000 02 7419 741A,
TABLE A IBAR B004 01 7419, TABLE B IFOO B006 02 741C 741D. The
conversion PRG ends $25E5.if_arg_push pushes byte by byte, so a frame-stack refusal
can leave the higher bytes already pushed; the caller's frame cleanup owns
them. it_find returns the first matching table, which is unique because a
class emits one table per implements entry and duplicate entries are a
separate conformance question. Descriptor-directory lookups at run time,
interface calls in generated code, and lifetime remain E06-S05/E06-S06;
physical C128 testing remains P2 validation.Powered by TurnKey Linux.