瀏覽代碼

Add class descriptor addresses to Nova128 MAP records.

main
Daniel Covington 4 天之前
父節點
當前提交
e2aed7a932
共有 7 個文件被更改,包括 62 次插入 和 23 次删除
  1. +5
    -3
      newLang/docs/architecture.md
  2. +2
    -0
      newLang/docs/decisions.md
  3. +6
    -5
      newLang/docs/memory-map.md
  4. +4
    -2
      newLang/scripts/verify-class-test.ps1
  5. +1
    -1
      newLang/src/common/formats.inc
  6. +34
    -10
      newLang/src/compiler/output.s
  7. +10
    -2
      newLang/tests/runtime/class-test.s

+ 5
- 3
newLang/docs/architecture.md 查看文件

@@ -687,15 +687,17 @@ with no fields and no destructor, and a class with an optional destructor and
one interface-directory entry.

`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
CLASS name size destroy interface-count interface-directory
CLASS name address size destroy interface-count interface-directory
METHOD name address
```

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
the descriptor's actual destructor and directory addresses.



+ 2
- 0
newLang/docs/decisions.md 查看文件

@@ -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. |
| 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

- Native C128/80-column Vim port


+ 6
- 5
newLang/docs/memory-map.md 查看文件

@@ -19,7 +19,7 @@ later stories.
| BASIC 7 stub | 12 bytes, `10 SYS 7181` |
| Entry | `$1C0D` |
| 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` |

The fixed startup is copied from `src/runtime/startup.s`; `output.s` refuses
@@ -116,14 +116,15 @@ wired.
| Destructor | `$0000` means none |
| Interface directory | 4-byte entries: interface descriptor, method table |
| 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
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
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)



+ 4
- 2
newLang/scripts/verify-class-test.ps1 查看文件

@@ -52,6 +52,8 @@ function Read-DiskFile([string]$Name, [string]$Dest, [bool]$Seq) {
$mapPath = Join-Path $out "CLASSTEST.MAP"
Read-DiskFile "classtest.map" $mapPath $true
$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"
$stub = Get-Nova128Label $labels "method_stub"
$ifdir = Get-Nova128Label $labels "iface_dir"
@@ -60,8 +62,8 @@ $expectedMap = @(
"ENTRY 1C0D",
"SECTION STUB 1C01 000C",
"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 STUB {0:X4}" -f $stub))
if (($mapLines -join "`n") -ne ($expectedMap -join "`n")) {


+ 1
- 1
newLang/src/common/formats.inc 查看文件

@@ -16,7 +16,7 @@ OUT_MAX_SECTIONS = 8
OUT_SECTION_NAME_MAX = 12
OUT_RECORD_SIZE = 7 ; name ptr(2), name len(1), start(2), size(2)
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_METHOD_RECORD_SIZE = 5 ; name ptr(2), len(1), address(2)



+ 34
- 10
newLang/src/compiler/output.s 查看文件

@@ -7,7 +7,7 @@
; NOVA128 MAP 1
; ENTRY hhhh
; 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):
; out_begin A/X = source name (bank 0), Y = length. Sets out_load and
@@ -21,7 +21,7 @@
; out_end_section
; 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
; 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.
; 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_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_load, out_entry, out_start, out_err

@@ -254,6 +254,8 @@ out_begin:
sta out_count
sta out_class_count
sta out_method_count
sta out_class_addr
sta out_class_addr+1
sta out_in_section
sta out_prg_created
sta out_map_created
@@ -596,6 +598,12 @@ out_class:
lda out_tmp_len
sta (out_rec_ptr),y
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
sta (out_rec_ptr),y
iny
@@ -932,9 +940,9 @@ out_write_classes:
lda (out_rec_ptr),y
sta out_num+1
jsr out_hex4
bcc @size_ok
bcc @addr_ok
jmp @out
@size_ok:
@addr_ok:
lda #' '
jsr out_char
bcc @space2
@@ -947,9 +955,9 @@ out_write_classes:
lda (out_rec_ptr),y
sta out_num+1
jsr out_hex4
bcc @destroy_ok
bcc @size_ok
jmp @out
@destroy_ok:
@size_ok:
lda #' '
jsr out_char
bcc @space3
@@ -957,16 +965,31 @@ out_write_classes:
@space3:
ldy #7
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
bcc @count_ok
jmp @out
@count_ok:
lda #' '
jsr out_char
bcc @space4
bcc @space5
jmp @out
@space4:
ldy #8
@space5:
ldy #10
lda (out_rec_ptr),y
sta out_num
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_method_count: .res 1
out_method_addr: .res 2
out_class_addr: .res 2
out_class_size: .res 2
out_class_destroy: .res 2
out_class_ifaces: .res 1


+ 10
- 2
newLang/tests/runtime/class-test.s 查看文件

@@ -15,12 +15,12 @@
.import mmu_init, mmu_bank0, mmu_shutdown
.import out_begin, out_startup, out_finish, out_abort
.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_class_ifaces, out_class_ifdir
.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"
.word $1C01
@@ -205,6 +205,10 @@ test_entry:
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
sta out_class_size
lda #$00
@@ -220,6 +224,10 @@ test_entry:
jsr out_class
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
sta out_class_size
lda #$00


Loading…
取消
儲存

Powered by TurnKey Linux.