25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

6.1KB


story: E03-S02 owner: e03_member_parser status: done started: 2026-11-07 depends-on: [E03-S01]

E03-S02 Claim

Intended change

Extend src/compiler/parser.s so pass 1 records every interface and class member (fields and method signatures, with access, type, and parameter types) in bank-1 tables, enforces unique field and method names per type and the init/destroy shapes, and keeps locals leading in method bodies. Each method and the program get their own local scope with recorded local types. Pass 2 scans statement lines for name references: bare names must resolve to a local/parameter or (inside a method) a field of the enclosing class, and expr.member chains through locals, fields, self, new, calls, and indexing to report unknown and private members at the member's position. E03-S03 replaces the scan with the real expression parser and reuses the lookups.

File area

  • src/compiler/parser.s, src/common/parser.inc
  • src/compiler/names.s (adds lookup-only name_find)
  • src/common/diagcat.inc (appended entries), docs/diagnostics.md
  • tests/parser/
  • scripts/build-parser-test.ps1, scripts/verify-parser-test.ps1
  • docs/architecture.md, docs/memory-map.md, docs/decisions.md
  • planning/claims/E03-S02.md
  • generated files under build/

Acceptance evidence

  • Parses access, signatures, parameters, fields, and leading local declarations: the member dump (owner, name, field/method, access, type, parameter types) matches an independent source-derived oracle for all 7 accepted fixtures and members/lifecycle/scopes/private (51 member rows, default field-private/method-public included). scopes.n8 rejects var after a method statement (22:5) and inside a block (40:5); the program may still interleave var at its top level (35).
  • Enforces unique method names and valid init/destroy shapes: members.n8 rejects a second method area in an interface (3:10) and a class (17:18) and a second field size (9:15), while one field and one method may share a name. lifecycle.n8 rejects init/destroy in an interface (E030), init ... as word (E151, D122), a second init (E060), and destroy with parameters (E152, first one) and a result (E151); class Fine shows parameterized init and private destroy pass.
  • Assigns lexical scopes without leaking names across methods/classes: scopes.n8 reports one()'s local and parameter in two(), class A's field in class B, three()'s parameter and local in four(), method locals and fields in the program, self in the program, and an unknown new Ghost() (8 pass-2 diagnostics, exact positions). Mutation: removing the per-signature scope reset fails 5 fixtures.
  • Reports private-member violations with source positions: private.n8 reports 6 E120s at the member's column, through a parameter, local, call result (v.make().hidden, p.look().secret), and index (list[0].secret), with Thief resolving Vault's members before Vault is declared; access from Vault's own methods (through self, a bare field, or another Vault) passes; unknown members are E061. Mutation: disabling the privacy test drops the 6 E120s and fails the fixture.

Coordination notes

  • No other claim is active. E03-S03 will own statement/expression grammar; the pass-2 scan here only resolves names and members token by token and reports nothing about expression shape or types.

Work log

  • Baseline: scripts/verify-parser-test.ps1 passes 24 fixtures before any change.
  • Added name_find (lookup without interning) so pass 2 never grows the name table: a name first seen in a statement was never declared.
  • Appended E151 SEM_LIFECYCLE_RETURN, E152 SEM_LIFECYCLE_PARAMS, E223 RES_TOO_MANY_MEMBERS, E224 RES_TOO_MANY_PARAMS; docs regenerated.
  • First x128 run hung with the C128 in its ML monitor. Cause: the test PRG now extends past $4000, and mmu_init copies the COMMON load image (then placed after DATA) in the system mapping, where BASIC ROM covers $4000-$7FFF. Fix: cfg/compiler.cfg loads COMMON directly after STARTUP, and mmu.s asserts at link time that mmu_init and the COMMON image stay at or below $4000. Region addresses (D117) are unchanged. Map skeleton, source, lexer, names, and diagnostics suites were rerun on the new layout.
  • Verifier: members are compared against an independent regex oracle over the fixture source (declaration order, access defaults, first declaration wins) for the 7 accepted fixtures and the 4 new ones.

Completion

  • Tests run: scripts/verify-parser-test.ps1 (final run, plus the two mutations above); scripts/build-diag-test.ps1 catalog check; because cfg/compiler.cfg changed, verify-map-skeleton.ps1 (including its overflow variants), verify-source-test.ps1, verify-lexer-test.ps1, verify-names-test.ps1, and verify-diag-test.ps1.
  • Results: 28 parser fixtures as expected (2 still pending E03-S03, with no false diagnostics); both mutations caught; all five other suites pass.
  • Files changed: src/compiler/parser.s, src/common/parser.inc, src/compiler/names.s, src/compiler/mmu.s, cfg/compiler.cfg, src/common/diagcat.inc, docs/diagnostics.md, docs/decisions.md (D122, D123 proposed), docs/architecture.md, docs/memory-map.md, tests/parser/ (4 fixtures + expectations, harness dump), scripts/build-parser-test.ps1, scripts/verify-parser-test.ps1, this claim.
  • Remaining risks: D121-D123 await approval. The pass-2 scan is token based: where it cannot know a left side's type (expression results, grouping, primitives, array-valued calls) it checks nothing, and a field used as x.f(...) reports “not declared” rather than a type error; E03-S03/S04 should replace it. Access to init from new outside the class is not checked (spec silent). The type descriptor (base, name, 16-bit length) is provisional until E03-S04. Member and parameter capacities (255 each) are untested at the limit. CODE/DATA may now exceed $4000; only mmu_init and code run before mmu_bank0 must stay below it (asserted for mmu_init and COMMON; test STARTUP code is first in MAIN).

Powered by TurnKey Linux.