diff --git a/lib/check.ml b/lib/check.ml index fee8fb19..6e093a0d 100644 --- a/lib/check.ml +++ b/lib/check.ml @@ -9041,7 +9041,7 @@ and unknown_name : 'a. ?setting:bool -> ctx -> Loc.t -> string -> 'a = let n = String.length name in let stem = if n > 2 then String.sub name 0 (n - 2) else "" in let suffix = if n > 2 then String.sub name (n - 2) 2 else "" in - if (suffix = "++" || suffix = "--") && lookup ctx stem <> None then + if (suffix = "++" || suffix = "--") && List.mem stem (value_candidates ctx) then Loc.failk "check/unknown-name" loc "unknown name %s — to %s %s, write %s" name (if suffix = "++" then "add one to" else "take one from") stem diff --git a/lib/parse.ml b/lib/parse.ml index 4651dd4c..400f894d 100644 --- a/lib/parse.ml +++ b/lib/parse.ml @@ -1972,7 +1972,22 @@ let rec decl (f : Form.t) : Ast.decl = rule against a suggestion that does not compile. The shapes alone then, which is what there is to say about a form that named too little. *) + let atom (x : Form.t) = match x.v with Form.List _ | Form.Vec _ | Form.Map _ -> false | _ -> true in (match args with + (* In a .fln file, the two definitions in its spelling. *) + | [ n; v ] when Source.indented_at f.loc && atom n -> + let rest = + Form.to_string n ^ " = " ^ (if atom v then Form.to_string v else "...") in + Loc.failk "parse/defvar-renamed" f.loc + "there is no defvar. Did you mean once? once %s initialises once and \ + keeps its value; def %s re-initialises on every re-run" rest rest + | [ n; t; v ] when Source.indented_at f.loc && atom n && atom t -> + let rest = + Form.to_string n ^ ": " ^ Form.to_string t ^ " = " + ^ (if atom v then Form.to_string v else "...") in + Loc.failk "parse/defvar-renamed" f.loc + "there is no defvar. Did you mean once? once %s initialises once and \ + keeps its value; def %s re-initialises on every re-run" rest rest | [] | [ _ ] -> Loc.failk "parse/defvar-renamed" f.loc "there is no defvar. Did you mean defonce? \ diff --git a/test/test_syntax.ml b/test/test_syntax.ml index fb8c886d..0602f8f0 100644 --- a/test/test_syntax.ml +++ b/test/test_syntax.ml @@ -980,7 +980,11 @@ let () = refused "untyped-lambda.fln" "fn main() -> i32\n let f = fn(a)\n a\n 0\n" [ "let f: Fn(T, ...) -> R = fn(...)" ]; refused "plusplus.fln" "fn main() -> i32\n let x = 1\n x++\n x\n" - [ "write ++(x) or x += 1" ] + [ "write ++(x) or x += 1" ]; + refused "plusplus-global.fln" "once g = 0\n\nfn main() -> i32\n g--\n 0\n" + [ "write --(g) or g -= 1" ]; + refused "defvar.fln" "defvar(x, 1)\n\nfn main() -> i32 = 0\n" + [ "once x = 1 initialises once"; "def x = 1 re-initialises" ] (* ── Both directions of an import, on both backends ────────────────── *)