| @@ -687,15 +687,17 @@ with no fields and no destructor, and a class with an optional destructor and | |||||
| one interface-directory entry. | one interface-directory entry. | ||||
| `output.s` accepts class records through `out_class` and appends deterministic | `output.s` accepts class records through `out_class` and appends deterministic | ||||
| MAP lines after the section records: | |||||
| MAP lines after the section records. `out_class_addr` supplies the descriptor | |||||
| address: | |||||
| ```text | ```text | ||||
| CLASS name size destroy interface-count interface-directory | |||||
| CLASS name address size destroy interface-count interface-directory | |||||
| METHOD name address | METHOD name address | ||||
| ``` | ``` | ||||
| All numeric fields are four hex digits except the interface count, which is | All numeric fields are four hex digits except the interface count, which is | ||||
| two. METHOD records follow all CLASS records in `out_method` call order. Empty classes and no destructor are written as `0000`; records keep the | |||||
| two. METHOD records follow all CLASS records in `out_method` call order; both | |||||
| record kinds use the final linked addresses. Empty classes and no destructor are written as `0000`; records keep the | |||||
| caller's order. The class test reads the emitted MAP back and compares it with | caller's order. The class test reads the emitted MAP back and compares it with | ||||
| the descriptor's actual destructor and directory addresses. | the descriptor's actual destructor and directory addresses. | ||||
| @@ -69,6 +69,8 @@ documented default. `Proposed` means a later change still needs approval. | |||||
| | D139 | E04-S07 begins the pass-3 address path. `flow.s` resolves absolute `JMP`/`JSR` operands against `fl_code_base`, which defaults to `cg_code`; `sizing.s` computes the final code base as `PRG_ENTRY_ADDR + bytes before CODE` and installs it with `em_set_base` before pass 2. `counter.n8` aliases two local bytes, loops `i = 1 to 5`, and sums into `total`; its fixture writes `COUNTER.PRG`/`COUNTB.PRG` with STUB, START, and CODE sections. The generated wrapper selects CR `$0E`, sets `FRAME_FP` to `$BF80`, calls the code base, reads `total`, restores CR, and reports PASS. | Proves final section addresses and generated-code relocation in a real x128 run while keeping existing in-place emitter fixtures unchanged. D140 completes the count-mode and MAP work for E04-S07. Implemented by `flow.s`, `emit.s`, `sizing.s`, `counter.n8`, the counter fixture, and its scripts. | | | D139 | E04-S07 begins the pass-3 address path. `flow.s` resolves absolute `JMP`/`JSR` operands against `fl_code_base`, which defaults to `cg_code`; `sizing.s` computes the final code base as `PRG_ENTRY_ADDR + bytes before CODE` and installs it with `em_set_base` before pass 2. `counter.n8` aliases two local bytes, loops `i = 1 to 5`, and sums into `total`; its fixture writes `COUNTER.PRG`/`COUNTB.PRG` with STUB, START, and CODE sections. The generated wrapper selects CR `$0E`, sets `FRAME_FP` to `$BF80`, calls the code base, reads `total`, restores CR, and reports PASS. | Proves final section addresses and generated-code relocation in a real x128 run while keeping existing in-place emitter fixtures unchanged. D140 completes the count-mode and MAP work for E04-S07. Implemented by `flow.s`, `emit.s`, `sizing.s`, `counter.n8`, the counter fixture, and its scripts. | | ||||
| | D140 | E04-S07 completes count-mode sizing and the MAP/diagnostic evidence. `em_count` selects the count pass; `em_end_func` records each routine length in `em_routine_sizes`; `sz_capture` snapshots code length, entry, routine sizes, and all 64 label offsets; the emitting pass runs with `diag_suppress`; `sz_verify` counts every difference and raises `RES_SIZE_MISMATCH` (E228) after the pass. The counter fixture requires `sz_mismatch = 0`, 175 code bytes, `CODE 1C4F`, deterministic PRGs, and `total = 15`. `output.s` adds `METHOD name address` records after `CLASS` records, proven by `METHOD DESTROY`/`METHOD STUB` in the class MAP. `tests/parser/unresolved.n8` proves one unknown method produces exactly one `SEM_UNKNOWN_NAME` (E61), and the output suite still proves E202 in the pass-3-adjacent writer path. | Closes the E04-S07 acceptance evidence without changing ordinary in-place fixtures: `parse_file` clears `em_count`, `diag_suppress`, and the base request, while `parse_file_sized` opts into the counted path. The code buffer remains 255 bytes and `em_entry` remains an offset; general program startup and frame sizing are separate work. Implemented by `parser.s`, `emit.s`, `emit.inc`, `sizing.s`, `diagnostics.s`, `diagcat.inc`, `output.s`, `formats.inc`, the counter/class/output/parser fixtures, and their scripts. | | | D140 | E04-S07 completes count-mode sizing and the MAP/diagnostic evidence. `em_count` selects the count pass; `em_end_func` records each routine length in `em_routine_sizes`; `sz_capture` snapshots code length, entry, routine sizes, and all 64 label offsets; the emitting pass runs with `diag_suppress`; `sz_verify` counts every difference and raises `RES_SIZE_MISMATCH` (E228) after the pass. The counter fixture requires `sz_mismatch = 0`, 175 code bytes, `CODE 1C4F`, deterministic PRGs, and `total = 15`. `output.s` adds `METHOD name address` records after `CLASS` records, proven by `METHOD DESTROY`/`METHOD STUB` in the class MAP. `tests/parser/unresolved.n8` proves one unknown method produces exactly one `SEM_UNKNOWN_NAME` (E61), and the output suite still proves E202 in the pass-3-adjacent writer path. | Closes the E04-S07 acceptance evidence without changing ordinary in-place fixtures: `parse_file` clears `em_count`, `diag_suppress`, and the base request, while `parse_file_sized` opts into the counted path. The code buffer remains 255 bytes and `em_entry` remains an offset; general program startup and frame sizing are separate work. Implemented by `parser.s`, `emit.s`, `emit.inc`, `sizing.s`, `diagnostics.s`, `diagcat.inc`, `output.s`, `formats.inc`, the counter/class/output/parser fixtures, and their scripts. | | ||||
| | D141 | The MAP CLASS record carries the class descriptor's final address between the name and size: `CLASS name address size destroy interface-count interface-directory`. `out_class_addr` supplies it, `OUT_CLASS_RECORD_SIZE` grows from 10 to 12 bytes, and METHOD records remain `METHOD name address`. The class fixture exports `desc_empty`/`desc_box` and compares both descriptor addresses plus the two method addresses against the linker labels. | Makes class and method map records symmetric and directly verifiable, instead of requiring the caller to infer a descriptor address from the size/destructor fields. This is a visible MAP format change; existing SECTION, ENTRY, and method records keep their order. | | |||||
| ## Deferred | ## Deferred | ||||
| - Native C128/80-column Vim port | - Native C128/80-column Vim port | ||||
| @@ -19,7 +19,7 @@ later stories. | |||||
| | BASIC 7 stub | 12 bytes, `10 SYS 7181` | | | BASIC 7 stub | 12 bytes, `10 SYS 7181` | | ||||
| | Entry | `$1C0D` | | | Entry | `$1C0D` | | ||||
| | Sections | ascending addresses, zero-filled gaps | | | Sections | ascending addresses, zero-filled gaps | | ||||
| | MAP | `NOVA128 MAP 1`, `ENTRY hhhh`, `SECTION name start size`, `CLASS name size destroy count ifdir`, `METHOD name address` | | |||||
| | MAP | `NOVA128 MAP 1`, `ENTRY hhhh`, `SECTION name start size`, `CLASS name address size destroy count ifdir`, `METHOD name address` | | |||||
| | Startup | clears mailbox, producer `$03`, status PASS, then `RTS` | | | Startup | clears mailbox, producer `$03`, status PASS, then `RTS` | | ||||
| The fixed startup is copied from `src/runtime/startup.s`; `output.s` refuses | The fixed startup is copied from `src/runtime/startup.s`; `output.s` refuses | ||||
| @@ -116,14 +116,15 @@ wired. | |||||
| | Destructor | `$0000` means none | | | Destructor | `$0000` means none | | ||||
| | Interface directory | 4-byte entries: interface descriptor, method table | | | Interface directory | 4-byte entries: interface descriptor, method table | | ||||
| | Flags | reserved, must be 0; no parent-class slot | | | Flags | reserved, must be 0; no parent-class slot | | ||||
| | MAP | `CLASS name size destroy count ifdir` and `METHOD name address` after sections | | |||||
| | MAP | `CLASS name address size destroy count ifdir` and `METHOD name address` after sections | | |||||
| The ABI is fixed in `src/common/class.inc`; D134 records the provisional | The ABI is fixed in `src/common/class.inc`; D134 records the provisional | ||||
| decision. `src/runtime/objects.s` reads descriptors and objects without | decision. `src/runtime/objects.s` reads descriptors and objects without | ||||
| allocating. `output.s` writes class MAP records in `out_class` call order and method MAP | allocating. `output.s` writes class MAP records in `out_class` call order and method MAP | ||||
| records in `out_method` call order; the E05-S02 fixture checks a | |||||
| no-destructor/no-interface class, a destructor plus one interface entry, and | |||||
| two method addresses. Interface dispatch remains E06 work. | |||||
| records in `out_method` call order. The descriptor address comes from | |||||
| `out_class_addr`; method addresses come from `out_method_addr`. The E05-S02 | |||||
| fixture checks a no-destructor/no-interface class, a destructor plus one | |||||
| interface entry, two method addresses, and both descriptor addresses. Interface dispatch remains E06 work. | |||||
| ## Construction and Deletion (E05-S03) | ## Construction and Deletion (E05-S03) | ||||
| @@ -52,6 +52,8 @@ function Read-DiskFile([string]$Name, [string]$Dest, [bool]$Seq) { | |||||
| $mapPath = Join-Path $out "CLASSTEST.MAP" | $mapPath = Join-Path $out "CLASSTEST.MAP" | ||||
| Read-DiskFile "classtest.map" $mapPath $true | Read-DiskFile "classtest.map" $mapPath $true | ||||
| $mapLines = ([IO.File]::ReadAllText($mapPath)).TrimEnd("`r", "`n") -split "`r`n|`r|`n" | $mapLines = ([IO.File]::ReadAllText($mapPath)).TrimEnd("`r", "`n") -split "`r`n|`r|`n" | ||||
| $empty = Get-Nova128Label $labels "desc_empty" | |||||
| $box = Get-Nova128Label $labels "desc_box" | |||||
| $destroy = Get-Nova128Label $labels "destroy_b" | $destroy = Get-Nova128Label $labels "destroy_b" | ||||
| $stub = Get-Nova128Label $labels "method_stub" | $stub = Get-Nova128Label $labels "method_stub" | ||||
| $ifdir = Get-Nova128Label $labels "iface_dir" | $ifdir = Get-Nova128Label $labels "iface_dir" | ||||
| @@ -60,8 +62,8 @@ $expectedMap = @( | |||||
| "ENTRY 1C0D", | "ENTRY 1C0D", | ||||
| "SECTION STUB 1C01 000C", | "SECTION STUB 1C01 000C", | ||||
| "SECTION START 1C0D 004A", | "SECTION START 1C0D 004A", | ||||
| ("CLASS EMPTY 0007 0000 00 0000"), | |||||
| ("CLASS BOX 0023 {0:X4} 01 {1:X4}" -f $destroy, $ifdir), | |||||
| ("CLASS EMPTY {0:X4} 0007 0000 00 0000" -f $empty), | |||||
| ("CLASS BOX {0:X4} 0023 {1:X4} 01 {2:X4}" -f $box, $destroy, $ifdir), | |||||
| ("METHOD DESTROY {0:X4}" -f $destroy), | ("METHOD DESTROY {0:X4}" -f $destroy), | ||||
| ("METHOD STUB {0:X4}" -f $stub)) | ("METHOD STUB {0:X4}" -f $stub)) | ||||
| if (($mapLines -join "`n") -ne ($expectedMap -join "`n")) { | if (($mapLines -join "`n") -ne ($expectedMap -join "`n")) { | ||||
| @@ -16,7 +16,7 @@ OUT_MAX_SECTIONS = 8 | |||||
| OUT_SECTION_NAME_MAX = 12 | OUT_SECTION_NAME_MAX = 12 | ||||
| OUT_RECORD_SIZE = 7 ; name ptr(2), name len(1), start(2), size(2) | OUT_RECORD_SIZE = 7 ; name ptr(2), name len(1), start(2), size(2) | ||||
| OUT_MAX_CLASSES = 8 | OUT_MAX_CLASSES = 8 | ||||
| OUT_CLASS_RECORD_SIZE = 10 ; name ptr(2), len(1), size(2), destroy(2), count(1), dir(2) | |||||
| OUT_CLASS_RECORD_SIZE = 12 ; name ptr(2), len(1), addr(2), size(2), destroy(2), count(1), dir(2) | |||||
| OUT_MAX_METHODS = 16 | OUT_MAX_METHODS = 16 | ||||
| OUT_METHOD_RECORD_SIZE = 5 ; name ptr(2), len(1), address(2) | OUT_METHOD_RECORD_SIZE = 5 ; name ptr(2), len(1), address(2) | ||||
| @@ -7,7 +7,7 @@ | |||||
| ; NOVA128 MAP 1 | ; NOVA128 MAP 1 | ||||
| ; ENTRY hhhh | ; ENTRY hhhh | ||||
| ; SECTION name start size | ; SECTION name start size | ||||
| ; CLASS name size destroy interface-count interface-directory | |||||
| ; CLASS name address size destroy interface-count interface-directory | |||||
| ; | ; | ||||
| ; API (all calls in the bank-0 compiler state): | ; API (all calls in the bank-0 compiler state): | ||||
| ; out_begin A/X = source name (bank 0), Y = length. Sets out_load and | ; out_begin A/X = source name (bank 0), Y = length. Sets out_load and | ||||
| @@ -21,7 +21,7 @@ | |||||
| ; out_end_section | ; out_end_section | ||||
| ; out_finish Writes the MAP, closes both files, and returns C=0 on success. | ; out_finish Writes the MAP, closes both files, and returns C=0 on success. | ||||
| ; out_class A/X = class name, Y = length. Adds a deterministic CLASS | ; out_class A/X = class name, Y = length. Adds a deterministic CLASS | ||||
| ; record from out_class_size/destroy/ifaces/ifdir. Class | |||||
| ; record from out_class_addr/size/destroy/ifaces/ifdir. Class | |||||
| ; records follow the SECTION lines in call order. | ; records follow the SECTION lines in call order. | ||||
| ; out_abort Closes and scratches only files created by this run. | ; out_abort Closes and scratches only files created by this run. | ||||
| ; | ; | ||||
| @@ -39,7 +39,7 @@ | |||||
| .export out_begin, out_startup, out_section, out_end_section | .export out_begin, out_startup, out_section, out_end_section | ||||
| .export out_byte, out_bytes, out_finish, out_abort | .export out_byte, out_bytes, out_finish, out_abort | ||||
| .export out_class, out_method, out_method_addr | |||||
| .export out_class, out_class_addr, out_method, out_method_addr | |||||
| .export out_class_size, out_class_destroy, out_class_ifaces, out_class_ifdir | .export out_class_size, out_class_destroy, out_class_ifaces, out_class_ifdir | ||||
| .export out_load, out_entry, out_start, out_err | .export out_load, out_entry, out_start, out_err | ||||
| @@ -254,6 +254,8 @@ out_begin: | |||||
| sta out_count | sta out_count | ||||
| sta out_class_count | sta out_class_count | ||||
| sta out_method_count | sta out_method_count | ||||
| sta out_class_addr | |||||
| sta out_class_addr+1 | |||||
| sta out_in_section | sta out_in_section | ||||
| sta out_prg_created | sta out_prg_created | ||||
| sta out_map_created | sta out_map_created | ||||
| @@ -596,6 +598,12 @@ out_class: | |||||
| lda out_tmp_len | lda out_tmp_len | ||||
| sta (out_rec_ptr),y | sta (out_rec_ptr),y | ||||
| iny | iny | ||||
| lda out_class_addr | |||||
| sta (out_rec_ptr),y | |||||
| iny | |||||
| lda out_class_addr+1 | |||||
| sta (out_rec_ptr),y | |||||
| iny | |||||
| lda out_class_size | lda out_class_size | ||||
| sta (out_rec_ptr),y | sta (out_rec_ptr),y | ||||
| iny | iny | ||||
| @@ -932,9 +940,9 @@ out_write_classes: | |||||
| lda (out_rec_ptr),y | lda (out_rec_ptr),y | ||||
| sta out_num+1 | sta out_num+1 | ||||
| jsr out_hex4 | jsr out_hex4 | ||||
| bcc @size_ok | |||||
| bcc @addr_ok | |||||
| jmp @out | jmp @out | ||||
| @size_ok: | |||||
| @addr_ok: | |||||
| lda #' ' | lda #' ' | ||||
| jsr out_char | jsr out_char | ||||
| bcc @space2 | bcc @space2 | ||||
| @@ -947,9 +955,9 @@ out_write_classes: | |||||
| lda (out_rec_ptr),y | lda (out_rec_ptr),y | ||||
| sta out_num+1 | sta out_num+1 | ||||
| jsr out_hex4 | jsr out_hex4 | ||||
| bcc @destroy_ok | |||||
| bcc @size_ok | |||||
| jmp @out | jmp @out | ||||
| @destroy_ok: | |||||
| @size_ok: | |||||
| lda #' ' | lda #' ' | ||||
| jsr out_char | jsr out_char | ||||
| bcc @space3 | bcc @space3 | ||||
| @@ -957,16 +965,31 @@ out_write_classes: | |||||
| @space3: | @space3: | ||||
| ldy #7 | ldy #7 | ||||
| lda (out_rec_ptr),y | lda (out_rec_ptr),y | ||||
| sta out_num | |||||
| iny | |||||
| lda (out_rec_ptr),y | |||||
| sta out_num+1 | |||||
| jsr out_hex4 | |||||
| bcc @destroy_ok | |||||
| jmp @out | |||||
| @destroy_ok: | |||||
| lda #' ' | |||||
| jsr out_char | |||||
| bcc @space4 | |||||
| jmp @out | |||||
| @space4: | |||||
| ldy #9 | |||||
| lda (out_rec_ptr),y | |||||
| jsr out_hex_byte | jsr out_hex_byte | ||||
| bcc @count_ok | bcc @count_ok | ||||
| jmp @out | jmp @out | ||||
| @count_ok: | @count_ok: | ||||
| lda #' ' | lda #' ' | ||||
| jsr out_char | jsr out_char | ||||
| bcc @space4 | |||||
| bcc @space5 | |||||
| jmp @out | jmp @out | ||||
| @space4: | |||||
| ldy #8 | |||||
| @space5: | |||||
| ldy #10 | |||||
| lda (out_rec_ptr),y | lda (out_rec_ptr),y | ||||
| sta out_num | sta out_num | ||||
| iny | iny | ||||
| @@ -1172,6 +1195,7 @@ out_classes: .res OUT_MAX_CLASSES * OUT_CLASS_RECORD_SIZE | |||||
| out_methods: .res OUT_MAX_METHODS * OUT_METHOD_RECORD_SIZE | out_methods: .res OUT_MAX_METHODS * OUT_METHOD_RECORD_SIZE | ||||
| out_method_count: .res 1 | out_method_count: .res 1 | ||||
| out_method_addr: .res 2 | out_method_addr: .res 2 | ||||
| out_class_addr: .res 2 | |||||
| out_class_size: .res 2 | out_class_size: .res 2 | ||||
| out_class_destroy: .res 2 | out_class_destroy: .res 2 | ||||
| out_class_ifaces: .res 1 | out_class_ifaces: .res 1 | ||||
| @@ -15,12 +15,12 @@ | |||||
| .import mmu_init, mmu_bank0, mmu_shutdown | .import mmu_init, mmu_bank0, mmu_shutdown | ||||
| .import out_begin, out_startup, out_finish, out_abort | .import out_begin, out_startup, out_finish, out_abort | ||||
| .import out_load, out_entry, out_err | .import out_load, out_entry, out_err | ||||
| .import out_class, out_class_size, out_class_destroy | |||||
| .import out_class, out_class_addr, out_class_size, out_class_destroy | |||||
| .import out_method, out_method_addr | .import out_method, out_method_addr | ||||
| .import out_class_ifaces, out_class_ifdir | .import out_class_ifaces, out_class_ifdir | ||||
| .import obj_class, obj_size, obj_destroy, obj_iface_dir | .import obj_class, obj_size, obj_destroy, obj_iface_dir | ||||
| .export destroy_b, iface_dir, method_stub | |||||
| .export desc_empty, desc_box, destroy_b, iface_dir, method_stub | |||||
| .segment "LOADADDR" | .segment "LOADADDR" | ||||
| .word $1C01 | .word $1C01 | ||||
| @@ -205,6 +205,10 @@ test_entry: | |||||
| jmp @p7_abort | jmp @p7_abort | ||||
| : | : | ||||
| lda #<desc_empty | |||||
| sta out_class_addr | |||||
| lda #>desc_empty | |||||
| sta out_class_addr+1 | |||||
| lda #7 ; EMPTY: size 7, no destructor/interface | lda #7 ; EMPTY: size 7, no destructor/interface | ||||
| sta out_class_size | sta out_class_size | ||||
| lda #$00 | lda #$00 | ||||
| @@ -220,6 +224,10 @@ test_entry: | |||||
| jsr out_class | jsr out_class | ||||
| bcs @p7_abort | bcs @p7_abort | ||||
| lda #<desc_box | |||||
| sta out_class_addr | |||||
| lda #>desc_box | |||||
| sta out_class_addr+1 | |||||
| lda #35 ; BOX: destructor and one interface | lda #35 ; BOX: destructor and one interface | ||||
| sta out_class_size | sta out_class_size | ||||
| lda #$00 | lda #$00 | ||||
Powered by TurnKey Linux.