feat(lang): reserved-name check covers :: const/fn/type decls + scope call rewrite to raw provenance [F0.6]

A bare reserved-type-name `::` declaration was silently accepted, and the
attempt-2 lowerCall rewrite then made a bare `s2 :: (…) {…}` function callable —
bypassing the backtick rule for handwritten sx. The reserved-name binding check
covered `:=` / typed-local / param / captures but NOT the `::` declaration form.

- ast: `ConstDecl`/`FnDecl` carry `is_raw` + `name_span` threaded from the parser
  (parseConstBinding / parseFnDecl, all call sites incl. struct/impl methods).
- semantic_diagnostics: reject a bare reserved spelling at EVERY declaration-name
  site — const, function (incl. struct/impl methods), struct/enum/union/error-set,
  protocol, foreign-class, ufcs alias, namespaced/library/c-import name. Backtick
  (`is_raw`) and the compiler's `#builtin` definition (`string :: []u8 #builtin`)
  are the only exemptions; a value whose node is itself a named decl defers to
  that node's own check.
- c_import: synthesized foreign fn_decls are `is_raw = true`, so a C function
  whose own name collides with a reserved spelling (`int s2(int);`) imports and
  bare-calls unedited.
- lower: scope the `.type_expr`→`.identifier` call rewrite to a callee FnDecl of
  RAW provenance (`is_raw`) — only a backtick / `#import c` foreign fn can carry a
  reserved-name spelling, so a non-raw match never gets rewritten.
- examples: 0153 (positive — backtick `::` const + fn, bare + tick call), 1140
  (negative — bare `::` const + fn rejected).
- docs: specs.md + readme.md state the backtick is required at every binding site
  including `::` const / function / type declarations; issue 0089 banner updated.
This commit is contained in:
agra
2026-06-04 19:16:37 +03:00
parent 640f59dc54
commit c0e1a5db82
16 changed files with 232 additions and 62 deletions

View File

@@ -106,15 +106,18 @@ z : s32 = ---; // uninitialized
```
Builtin type names (`s2`, `u8`, `bool`, `string`, …) are reserved and can't be used
as bare value identifiers. A leading backtick at the **binding site** escapes one
into a raw identifier — its text drops the backtick and it's never read as a type —
so reserved spellings (and keywords) work as ordinary names. The backtick is needed
only where the name is declared; a later bare reference in value position resolves
to the binding, while a bare `s2` in type position is still the type. It works in
every identifier position (local, global, parameter, field, function name, and the
control-flow / capture / binding forms — destructure, `if`/`while` binding, `for`
capture, match capture, `catch`/`onfail` tag), and a reserved-spelled function is
bare-callable:
as bare identifiers at **any** binding site — a value binding (`:=` / typed local /
parameter), a `::` constant or function declaration, or a `::` type declaration
(`struct` / `enum` / `union` / alias / `protocol` / …) — each is an error
(`s2 :: 5` and `s2 :: (n) { … }` are rejected just like `s2 := 5`). A leading
backtick at the binding site escapes one into a raw identifier — its text drops the
backtick and it's never read as a type — so reserved spellings (and keywords) work
as ordinary names. The backtick is needed only where the name is declared; a later
bare reference in value position resolves to the binding, while a bare `s2` in type
position is still the type. It works in every identifier position (local, global,
parameter, field, function name, constant, and the control-flow / capture / binding
forms — destructure, `if`/`while` binding, `for` capture, match capture,
`catch`/`onfail` tag), and a reserved-spelled function is bare-callable:
```sx
`s2 := 2.5; // value identifier "s2", distinct from the s2 type