Give every expression a type and check it in pass 2. A new module
src/compiler/types.s holds the type registers, assignability (spec 3.4),
operator typing (spec 8), numeric-literal constants with folding, and the
spelling of types in diagnostics. The parser records each class's
implements list and init row, finds a method's own member row again in
pass 2, carries full types through member chains, groups, calls, indexing,
and operators, and checks assignments, call arguments (count and type),
returns, conditions, for, print, delete, indexing, and member access.
Missing returns are found by tracking whether each block ends in return
(an if counts only with an else whose branches both do).
src/compiler/types.s (new), src/compiler/parser.s,
src/common/parser.incsrc/common/diagcat.inc (appended entries), docs/diagnostics.mdtests/semantic/ (new fixtures), tests/parser/ (harness, expectations
that gain true type diagnostics, forms.n8)scripts/build-parser-test.ps1, scripts/verify-parser-test.ps1,
scripts/demo-write-check.ps1 (links the parser)docs/architecture.md, docs/decisions.mdtests/lexer/reference-lexer.ps1 (host spelling fix found by the
regression run)planning/claims/E03-S04.mdbuild/types_ok.n8 passes with five top-level types and eleven
members; its member table matches the source independently. convert.n8
and refs.n8 cover every illegal conversion, arrays included.convert.n8
matches all 19 unsafe primitive assignments and constant misfits;
refs.n8 matches all 13 illegal reference and array cases, including
class-to-interface, unrelated references, and identity rules.calls.n8 (16 diagnostics), uses.n8 (18), ops.n8 (16),
convert.n8 (19), and refs.n8 (13) match their goldens; types_ok.n8
exercises the accepted forms without a diagnostic.refs.n8 expects E080 for every unrelated reference; calls.n8 expects
E150 at three end method sites (plain body, if without else,
while only) and E151 for a program return value.return in a program plus the missing-return rule.types.s holds the sc_*/tt_* type registers, ty_assign,
ty_binary, ty_unary, constant folding (16x16 multiply, restoring
divide), and the diagnostic spellings (BYTE, WORD[4], a class name, a
constant, NO VALUE).parser.s records implements lists and each class's init row in pass 1,
then in pass 2 re-finds the current member row, carries types through
member chains, groups, calls, and indexing, and checks every place a value
is used. Missing returns are reported at the end token (E150).verify-parser-test.ps1.unknown.n8 (E150
for an empty result method), recover.n8 (E081 for while x/if x on a
word), and syntax.n8 (E151 for return a in a program). Their
expectations were updated; recover.n8 records the conditions in the
order the blocks close.Format-PetsciiText used
"{{{0:X2}}}", which Windows PowerShell renders as {X2}. It now builds
the braces explicitly and matches the goldens ({0D}, {22}, {5C}).verify-parser-test.ps1 uses port 6535; on this machine the first run's
monitor reply was empty. Port 6530 works and is the port the other suites
already use; the final runs used -Port 6530.$ErrorActionPreference = "Stop", so a
missing good.err (the success case) made c1541's stderr terminate the
script. It now checks the disk listing first and redirects stderr.scripts/build-parser-test.ps1,
scripts/verify-parser-test.ps1 -Port 6530 (37 fixtures),
scripts/build-lexer-test.ps1, scripts/verify-lexer-test.ps1,
scripts/build-diag-test.ps1 -UpdateDocs,
scripts/verify-diag-test.ps1, scripts/demo-write-check.ps1
(good.n8 and bad.n8).$A7); the
lexer matches 6,733 bytes over 10 fixtures; the 67-entry diagnostic catalog
matches its screen/ERR expectations and docs/diagnostics.md is in sync;
the demo saves both programs from Vim byte-for-byte, good.n8 reports no
errors, and bad.n8 reports E151, E152, E120, and E061.types.s and the semantic goldens. The type registers are
statically allocated, so nested type checks reuse them deliberately.
for step typing follows the same operator table.Powered by TurnKey Linux.