diff --git a/TODO.org b/TODO.org index 2c65948b..07921c14 100644 --- a/TODO.org +++ b/TODO.org @@ -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 diff --git a/lib/parse.ml b/lib/parse.ml index 931caf4d..1f626ec4 100644 --- a/lib/parse.ml +++ b/lib/parse.ml @@ -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 \ diff --git a/test/test_flan.ml b/test/test_flan.ml index b24cb9f6..72e259af 100644 --- a/test/test_flan.ml +++ b/test/test_flan.ml @@ -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";