Quellcode durchsuchen

Record E06-S07 as blocked on calling-convention emission.

The story needs argument, return and interface-call emission, but the emitter
has no argument push, prologue or value return at all, and interface tables are
only placed after the code section. Document the exact gap and the decision
needed so the prerequisite work is not mistaken for this story.

Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
main
Daniel Covington vor 3 Tagen
Ursprung
Commit
8a2d8ce312
1 geänderte Dateien mit 77 neuen und 55 gelöschten Zeilen
  1. +77
    -55
      newLang/planning/claims/E06-S07.md

+ 77
- 55
newLang/planning/claims/E06-S07.md Datei anzeigen

@@ -1,7 +1,7 @@
---
story: E06-S07
owner: codebuff
status: in-progress
status: blocked
started: 2026-11-10
depends-on: [E06-S05, E05-S04, E04-S06, E04-S07]
---
@@ -52,67 +52,89 @@ emitted code reuses the E06-S02 trampoline, the E06-S04 conversions, and
through an interface each report their catalogue code and emit no PRG.
- [ ] MAP output names the interface tables and slots the emitted code uses.

## Blocking

**Exact failed criteria.** The argument, return and call criteria (1, 3, 4 and
5) cannot be met. The emitter has no calling-convention layer at all, so there
is nothing for an interface value to travel through:

- `parse_args` (`parser.s`, around line 2107) parses and type-checks each
argument but emits no code; the only emitter hooks in the call path are
`em_member_receiver` and `em_call` *before* the argument list.
- `em_call` (`emit.s`) refuses `C_MEM_PCOUNT != 0` with `EM_ERR_CALL`, so no
emitted call takes arguments.
- `em_return` emits a bare `RTS`; `em_begin_func` emits no prologue and
`fl_prologue`/`fl_ret`/`fl_ret_byte`/`fl_ret_word` are never called by the
parser, so parameters and returns have no emitted frame.
- `em_target`, `em_store_target`, `em_expr_name`, `em_push_left` and `em_bin`
reject every width but one byte, so interface locals/fields cannot even be
loaded or stored yet.
- `it_class` builds the per-class tables only in the output stage, after the
code section's length and addresses exist. A conversion emits the table
address as an immediate, so the table has to be placed (or its address fixed)
before pass 2 can emit the conversion.

**Evidence collected.** `src/compiler/emit.s` (whole file), `parser.s`
call/assignment/argument paths, `flow.s`, `codegen.s`, `iftables.s`,
`members.s`, `interfaces.s`, and `runtime/interfaces.s` were read. No emitter
hook for arguments, prologue or value returns exists in any of them; the
`calls-test.s` fixture passes `self` in A/X and runs a method body directly,
which is why the gap has not surfaced before.

**Smallest decision or fact needed.** A calling-convention emission story must
land first (argument push in source order, argument byte count for the discard,
`frame_enter` prologue sizing, `return` with 0/1/2-byte and interface results),
together with a decision placing interface tables at a layout-time-known address
so a conversion can embed the table pointer. That work is larger than this
story and changes the generated ABI/section layout, so it needs its own story
and a `Dxxx` record rather than being folded in here.

**Safe work that remains possible.** The storage half can be implemented and
proven without the calling convention: four-byte `em_expr_name`/`em_target`/
`em_store_target` for locals and fields, four-byte member load/store in
`members.s`, `null` as the canonical zero value, and copy-mode `if_assign`
between two interface slots. It cannot satisfy the story's call and argument
criteria on its own, so the claim stays `blocked` until the calling-convention
story exists.

## 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`).
- The type checker is not the gap: `types.s` classifies class and interface
references by name and `ty_assign` accepts a class for an interface it
implements (`tests/semantic/refs.n8`).
- `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.
the value pointer in A/X and the slot in Y. Both are already proven by
`tests/runtime/convert-test.s` and `tests/runtime/ifcall-test.s`.
- Zero page has no free pair: `$FB-$FE` is `FRAME_SP`/`FRAME_FP`, `$F5-$F8` is
`EM_LP`/`EM_TMP`, `$F9` is `MB_SELF`, `$C0-$C5` are the print vectors and
`$C6+` is `IF_RESULT`. A second value pointer must live in BSS and be copied
to `if_src`/`if_dst` with absolute stores.
- E07-S04's interface sample depends on this story, so E07-S04 is not eligible
work while this claim is blocked.

## 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.
- Read the emitter, parser call/argument paths, flow, codegen, iftables, member
and interface runtime modules. Confirmed the emitter is byte-only end to end
and that the parser's argument list emits no instructions.
- Confirmed the only interface machinery that exists is the runtime
(`if_assign`, `if_call`, `if_ret_*`, `if_arg_push`, `if_elem_*`) and the
pass-3 table builder; nothing emits calls to them.
- Confirmed interface tables are built after the code section, so a conversion
cannot embed a table address during the emitting pass without a layout
decision.
- Re-read the story's dependency E04-S07: its claim covers sizing, pass-3
addresses, MAP method records and deterministic PRGs, not the argument and
frame emission this story needs.

## 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.
- Tests run: none; no source change has landed for this story.
- Results: not applicable. The claim is `blocked` rather than `done` because
four acceptance criteria cannot be verified without the calling-convention
layer.
- Remaining risks: implementing the storage half alone would leave a compiler
that can copy interface values but cannot call through them, which is worse
than the current explicit refusal; the story should not be closed until the
prerequisite story and the table-placement decision exist.

Laden…
Abbrechen
Speichern

Powered by TurnKey Linux.