A loop, dotimes, match, macro, class or generic binding that starts with $ is refused too

This commit is contained in:
Joseph Ferano 2026-09-25 10:37:43 +07:00
parent 83b244475a
commit 222dc0ae90
3 changed files with 16 additions and 7 deletions

View File

@ -622,9 +622,10 @@ arguments, which can pick the wrong one of two equal subtrees.
** DONE A declared name may carry the $ sigil
CLOSED: [2026-09-25]
A name that starts with =$= is refused where it is declared — every top-level
form, a struct or union field, an enum member, a data case and a =let= name —
saying =$= marks a type variable and naming the bare spelling. A parameter was
already refused, as a type in a name slot.
form, a struct or union field, an enum member, a data case, a class slot, and a
=let=, =loop=, =dotimes=, =match=, macro or generic binding — saying =$= marks a
type variable and naming the bare spelling. A =defn= parameter was already
refused, as a type in a name slot.
* Checker

View File

@ -177,6 +177,7 @@ and dyn_params which (items : Form.t list) : Ast.field list =
(fun (it : Form.t) ->
match it.v with
| Sym s ->
no_sigil it;
{ Ast.fname = s;
fty = { Ast.t = Ast.Tname "dyn"; tloc = it.loc };
floc = it.loc }
@ -554,7 +555,7 @@ and form f mk (head : Form.t) (args : Form.t list) : Ast.expr =
{ Ast.dstart = Some start; dstop = stop; dstep = Some step }
| _ -> assert false
in
mk (Ast.Dotimes (lbl, sym n, b, body_of body))
mk (Ast.Dotimes (lbl, dname n, b, body_of body))
| _ ->
fail f
"dotimes is (dotimes [name stop] body ...), \
@ -800,7 +801,7 @@ and loop_bindings f (items : Form.t list) : (string * Ast.expr) list =
| [] -> []
| name :: value :: rest ->
no_pattern name;
(sym name, expr value) :: go rest
(dname name, expr value) :: go rest
| [ odd ] ->
Loc.fail odd.loc
"binding %s has no value — loop takes name/value pairs"
@ -1237,7 +1238,7 @@ and pattern (f : Form.t) : Ast.pattern =
member member
| List ({ v = Sym ctor; _ } :: binds) ->
List.iter no_pattern binds;
Ast.Pctor (ctor, List.map sym binds)
Ast.Pctor (ctor, List.map dname binds)
| _ -> fail f "expected a pattern, found %s" (Form.to_string f)
(* ── The third element of a defonce or a def ───────────────────────────
@ -1485,7 +1486,7 @@ let rec decl (f : Form.t) : Ast.decl =
List.map
(fun (s : Form.t) ->
match s.v with
| Sym name -> (name, s.loc)
| Sym name -> no_sigil s; (name, s.loc)
| _ ->
fail s
"a class slot is a name — its value is dyn, so there \

View File

@ -6341,6 +6341,13 @@ let () =
sigil "defdata case" "(defdata D [($C [a i32])])";
sigil "defmacro" "(defmacro $m [x] x)";
sigil "a let binding" "(defn f [] i32 (let [$y 1] y))";
sigil "a dotimes counter" "(defn f [] () (dotimes [$i 3] (println i)))";
sigil "a loop binding" "(defn f [] i32 (loop [$i 0] i))";
sigil "a match bind"
"(defdata D [(C [a i32])]) (defn f [d D] i32 (match d (D.C $x) x))";
sigil "a macro parameter" "(defmacro m [$x] x)";
sigil "a class slot" "(defclass K [$s])";
sigil "a generic's parameter" "(defgeneric area [$s] f64)";
parse_rejects "the $ refusal names the bare spelling"
"(defn $foo [x i32] i32 x)" ~needle:"Name it foo";