Integer literals now produce `Ty::UnboundInt` instead of a hardcoded
`i32`. This flexible type promotes to/from any concrete integer, so
literals resolve naturally in context (e.g. `n < 2` when `n: u8`
works without an explicit cast).
`common(UnboundInt, T)` returns `T` when `T` is a concrete integer,
so binary ops adopt the concrete operand's type. Includes 8 new tests
covering literal coercion, fibonacci-style patterns, and negative cases
(literals still don't coerce to float types).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix two test helpers (top/program) missing <Parsed> type argument
- Add checker/tests.rs with 74 tests covering all §7/§8 rules: entry
point validation, duplicate defs, struct cycles, literals, promotion,
type inference, definite assignment, undefined vars/funcs, arithmetic,
shift, comparison, logical ops, unary ops, pointers, struct literals,
field/index access, function calls, return checking, mutation, and
break/continue
- Fix assignment LHS check: bare identifier on the write side of `=`
must not trigger "uninitialized" — use lhs_ty() helper that skips
the assigned-set check for the direct write target
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Update ast.rs with Phase trait (Parsed/Typed), Ty enum, and generic
AST nodes so the same tree works pre- and post-type-checking
- Add checker/ module implementing the 4-pass semantic analyser from
SEMANTICS.md: struct/function collection, field resolution + size-cycle
detection, full expression/statement type checking, and entry-point
validation
- Wire checker into main; semantic errors are only run when the parse
succeeds and are rendered with the same diagnostic machinery
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>