Quellcode durchsuchen

Claim E06-S07 and freeze how interface values are emitted (D153).

Analysis shows the type checker already models class/interface references, so
the work is emitter-side: four-byte slots, member transfers and if_call sites.
E04-S07 becomes a dependency because argument push/discard is its work.

Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
main
Daniel Covington vor 4 Tagen
Ursprung
Commit
1cd49f9a9a
3 geänderte Dateien mit 120 neuen und 1 gelöschten Zeilen
  1. +1
    -0
      newLang/docs/decisions.md
  2. +118
    -0
      newLang/planning/claims/E06-S07.md
  3. +1
    -1
      newLang/planning/epics-and-stories.md

+ 1
- 0
newLang/docs/decisions.md Datei anzeigen

@@ -85,6 +85,7 @@ documented default. `Proposed` means a later change still needs approval.

| D151 | The editor workflow now defaults to the C128 builds: `scripts/launch-editor.ps1` starts `x128` in 80-column mode with `../vim/vim128.prg`, injected as `vim128` into the session's copy of `../vim/vim-improved.d81`, and autostarts that disk copy. This supersedes the `x64sc` editor default in E07-S02's acceptance text; the C64 editor build and its disk remain available through explicit arguments. Because `x128`'s plain `-exitscreenshot` captures the active display (VDC in 80-column mode) while `-exitscreenshotvicii` captures the 40-column screen, the shared launcher selects the option by emulator and mode. The E07-S03 round-trip test now creates, reopens and tokenizes the source through `vim128` in `x128`, so the whole path stays on the target machine. The editor must be autostarted from the session disk (`work.d81:vim128`, with the launcher running in the image's folder), not from a host path: a host-injected program has no device number from its load, and `vim128` then reports `written` while the image never receives the file — observed while validating the round-trip, which only passed once the disk copy was autostarted. | The user asked for the C128 Vim to be the default editor everywhere. The C128 build was already present as `../vim/vim128.prg` (80-column, built by `vim/build128.bat`) but no shipped `.d81` held it; injecting it into the per-session disk copy makes the editor available to the session's own disk access without writing `../vim` or adding a new reference image. Capturing the VDC screen is required for automated checks: a VIC-II capture of an 80-column session is blank. Keeping the C64 build reachable as an argument preserves the proven fallback instead of deleting working behaviour. |
| D152 | The E08-S01 harness reads its suite list from `tests/regression/suites.ps1`, which returns an array of hashtables, and gives each suite a fresh `build/<name>-test` directory unless `-NoFresh` is passed. Results are written as JSON with per-suite status, seconds, exit code, signature, problems, log path and artifacts; artifact SHA-256 values are compared against `tests/regression/baseline.json`, which `-UpdateBaseline` rewrites. A failed suite's signature is the diagnosis line it printed (for example a fixture name and the mismatch), falling back to the structural problem such as `exit code N` or a timeout when the suite produced no output. | A `.psd1` cannot be invoked with `&` (PowerShell returns nothing), so the manifest is a script whose array literal is evaluated on read; a data file would need `Import-PowerShellDataFile` and could not express per-suite logic. Fresh per-suite directories satisfy the `E08-S01` requirement that every run creates its own D81; `-NoFresh` exists so the self-test can prove that changed artifacts are detected on a rerun. Reviewing hashes rather than regenerating them keeps `E08-S02`'s "reviewed rather than blindly regenerated" rule intact. Preferring the observed diagnosis over an exit status is what makes a failure identify the fixture, as the story requires. |
| D153 | E06-S07 emits interface values without a new type category: the parser already classifies class and interface references by name (`sc_name`/`tt_name`) and `ty_assign` already accepts a class for an interface it implements, so a four-byte interface slot reaches `em_local`/`em_param` through the same size argument as any other type. Each storage or conversion site emits a pointer to the four-byte destination in `if_dst` and the operand in `if_src`, with the compile-time table from `it_find` in `if_tab`, then `JSR if_assign`; a null object is written to `if_obj` and does not need a distinct path. An interface call emits the slot address in `if_dst`, `Y` from `iface_slot`, and `JSR if_call`, and reports refusal through `if_error` rather than C. A field or array element of interface type is reached through a four-byte member load/store that copies between the value and `if_dst`/`if_src`, not through `mb_ld_field`/`mb_st_field`, which are byte/word only. Four-byte values never travel in A/X except through `IF_RESULT`, and the emitter does not add a zero-page pointer: `EM_LP` (`$F5-$F6`) addresses one value at a time, `$F2-$F4` is the only free zero page, and `$FB-$FE` is the frame ABI. | The runtime already provides every transfer (D145); the missing half is emission, so reuse keeps one audited conversion and one dispatch path instead of copies in generated code. Deriving the slot size from the parser avoids inventing parallel interface types that would then disagree with `ty_assign`. Refusing to add a fourth zero-page pointer is forced by the map: `$C0-$C5` print vectors, `$C6-$C9` `IF_RESULT`, `$D0-$E0` for-end values, `$E1-$F1` for-step values, `$F5-$F6` `EM_LP`, `$F7-$F8` `EM_TMP`, `$F9-$FA` `MB_SELF`, `$FB-$FE` frame ABI. Argument-bearing interface calls wait for E04-S07's push/discard emission, which is why that story is now a dependency. |

## Deferred



+ 118
- 0
newLang/planning/claims/E06-S07.md Datei anzeigen

@@ -0,0 +1,118 @@
---
story: E06-S07
owner: codebuff
status: in-progress
started: 2026-11-10
depends-on: [E06-S05, E05-S04, E04-S06, E04-S07]
---

# E06-S07 Claim

## Intended change

Emit interface values from source rather than only from hand-written fixtures:
store and copy all four bytes of an object/table pair in locals, parameters,
fields and array elements; convert a class reference or `null` at a use site;
and call an interface method through `if_call` with the compile-time slot. The
emitted code reuses the E06-S02 trampoline, the E06-S04 conversions, and
`iface_slot`, so no new runtime entry point or layout is introduced (D153).

## File area

- `src/compiler/emit.s`: four-byte value paths for a slot, a field and a call
site; interface-aware `em_target`/`em_store_target`
- `src/compiler/members.s`: four-byte member load/store between a field and
`if_dst`/`if_src`
- `src/compiler/parser.s`: pass-2 hooks for conversion assignment and interface
call sites
- `src/compiler/iftables.s`: the table lookup the conversion emission needs
(`it_find`, already present)
- `src/common/emit.inc`: new emitter error codes for an unsupported interface
shape
- `tests/compiler/iface.n8`, `tests/compiler/iface-test.s`
- `scripts/build-iface-test.ps1`, `scripts/verify-iface-test.ps1`
- `tests/semantic/*.n8` for the misuse diagnostics
- `docs/decisions.md` (D153), `docs/architecture.md`, `docs/memory-map.md`
- `planning/claims/E06-S07.md`
- generated files under `build/iface-test/`

## Acceptance criteria (from the story)

- [ ] Concrete-to-interface assignment in a statement, argument, return or
initializer emits the E06-S04 conversion path and stores all four bytes.
- [ ] `null` in an interface context produces the canonical null value and a
call through it takes the fault path.
- [ ] Interface-typed locals, parameters, returns and fields keep all four
bytes, including array elements and copies.
- [ ] A source-level interface call emits `if_call` with the value pointer in
A/X and the slot in Y, with arguments and one-/two-byte returns.
- [ ] Two classes dispatch one interface call differently, and one class
dispatching two interfaces works, compiled from source.
- [ ] Unrelated class assignment, undeclared interface member and private member
through an interface each report their catalogue code and emit no PRG.
- [ ] MAP output names the interface tables and slots the emitted code uses.

## Coordination notes

- The type checker is not the gap: `types.s` already classifies class and
interface references by name and `ty_assign` accepts a class for an interface
it implements (`tests/semantic/refs.n8`). Interface slots therefore allocate
four bytes through the existing size argument; the byte-only emitter is what
refuses them (`EM_ERR_SIZE` from `em_expr_name`, `em_target`, `em_bin`).
- `if_assign` takes the destination in A/X and the mode in Y (0 copies
`if_src`, any other value converts `if_obj` with `if_tab`); `if_call` takes
the value pointer in A/X and the slot in Y and reports through `if_error`.
Both are already proven by `tests/runtime/convert-test.s` and
`tests/runtime/ifcall-test.s`.
- Zero page has no room for another pointer: `$F2-$F4` is the only free gap, so
D153 keeps one value address (`EM_LP`) plus the runtime's own module
pointers.
- E04-S07 owns frame sizing, pass-3 addresses and argument push/discard, so
interface calls with arguments cannot be emitted before it; that is why this
claim lists it as a dependency. The zero-argument call and all storage and
conversion shapes do not need it.

## Work log

- Read `emit.s`, `members.s`, `codegen.s`, `emit.inc`, `interfaces.inc`,
`types.s` and the runtime interface API. The emitter is byte-only end to end:
`em_size` is compared with 1 in load, push, combine, target and store, and
`em_target` accepts only a one-byte local or a one-byte self field.
- `mb_ld_field`/`mb_st_field` accept `MB_BYTE` or `MB_WORD` only, so a
four-byte interface field needs its own member transfer; `mb_point` already
loads any object reference into `MB_SELF`, which a receiver expression can
reuse.
- `iface_slot` returns the slot from the interface's signature rows and is the
only correct source of the call's Y; `it_find` returns the class's table for a
given interface, which is the compile-time half of a conversion.
- Emitter state has no four-byte temp: `em_size` is a single byte count and the
left-operand path pushes exactly one byte. Conversions and copies must move
all four bytes through the runtime routines rather than a new temp.
- Story dependency corrected: E04-S07 added, because argument push/discard and
word results are its work, and the story's argument criterion cannot be met
without it.

## Completion

- Tests run: none yet. This claim records analysis and the emission decision;
no emitter, parser or fixture change has landed, so there is no behaviour to
verify and the claim stays `in-progress` rather than `done`.
- Results: not applicable.
- Remaining risks: pass 2 emits as it type-checks, so a four-byte target must be
known before the operand is emitted, which is a different ordering from the
byte path where the target is captured and consumed afterwards; a conversion
site must also decide between `if_assign` mode 0 and 1 from the source type
that `types.s` already computed.

## Next steps

1. Add the four-byte slot load/store and `em_target`/`em_store_target` cases
with `IF_VALUE_SIZE`, plus `EM_ERR_SIZE` only for shapes that are still
unsupported.
2. Add `mb_ld_iface`/`mb_st_iface` and use them for interface fields.
3. Emit conversion assignment at a use site: `it_find` for `if_tab`, source
pointer or zero into `if_obj`, destination slot pointer into `if_dst`,
`JSR if_assign` with mode 0 or 1.
4. Emit `if_call` from an interface receiver with `iface_slot` as Y, then the
`iface.n8` fixture with two classes and two interfaces, and the misuse
diagnostics in the semantic suite.

+ 1
- 1
newLang/planning/epics-and-stories.md Datei anzeigen

@@ -557,7 +557,7 @@ compiler/runtime `interfaces.s`, class descriptors, code generation, ABI tests.

### E06-S07 — Interface expressions in code generation (P0)

**Depends on:** E06-S05, E05-S04, E04-S06
**Depends on:** E06-S05, E05-S04, E04-S06, E04-S07

**Acceptance criteria:**



Laden…
Abbrechen
Speichern

Powered by TurnKey Linux.