A program's global named as a prelude function or global shadows it for the file, with the shadowing warning a defn gets
This commit is contained in:
parent
20684c2d9f
commit
d6e6a5dc0c
23
lib/check.ml
23
lib/check.ml
@ -14543,30 +14543,37 @@ let shown_name n =
|
||||
else n
|
||||
|
||||
let shadow_prelude (prelude : Ast.decl list) (decls : Ast.decl list) =
|
||||
let fn_name (d : Ast.decl) =
|
||||
(* A value name, and whether it is a function's. A program's global takes
|
||||
a prelude function's name over as a program's function does: both are
|
||||
names a call or a read reaches, and the prelude's own uses keep the
|
||||
prelude's. *)
|
||||
let value_name (d : Ast.decl) =
|
||||
match d.Ast.d with
|
||||
| Ast.Defn fn | Ast.Declare (fn, _) | Ast.DeclareC (fn, _) -> Some fn.Ast.name
|
||||
| Ast.Defn fn | Ast.Declare (fn, _) | Ast.DeclareC (fn, _) ->
|
||||
Some (fn.Ast.name, true)
|
||||
| Ast.Defvar (n, _, _, _) | Ast.Defconst (n, _, _) -> Some (n, false)
|
||||
| _ -> None
|
||||
in
|
||||
let theirs = List.filter_map fn_name prelude in
|
||||
let theirs = List.map fst (List.filter_map value_name prelude) in
|
||||
let taken =
|
||||
List.filter_map
|
||||
(fun (d : Ast.decl) ->
|
||||
match fn_name d with
|
||||
| Some n when List.mem n theirs -> Some (n, d.Ast.dloc)
|
||||
match value_name d with
|
||||
| Some (n, f) when List.mem n theirs -> Some (n, d.Ast.dloc, f)
|
||||
| _ -> None)
|
||||
decls
|
||||
in
|
||||
let warnings =
|
||||
List.map
|
||||
(fun (n, at) ->
|
||||
(fun (n, at, f) ->
|
||||
Loc.diag ~kind:"check/shadows-prelude" at
|
||||
(Printf.sprintf
|
||||
"%s shadows the prelude's %s — every call in this file now \
|
||||
"%s shadows the prelude's %s — every %s in this file now \
|
||||
reaches your definition"
|
||||
n n))
|
||||
n n (if f then "call" else "use")))
|
||||
taken
|
||||
in
|
||||
let taken = List.map (fun (n, at, _) -> (n, at)) taken in
|
||||
let prelude, decls =
|
||||
List.fold_left
|
||||
(fun (prelude, decls) (n, (at : Loc.t)) ->
|
||||
|
||||
14
test/programs/shadow-prelude-global.flan
Normal file
14
test/programs/shadow-prelude-global.flan
Normal file
@ -0,0 +1,14 @@
|
||||
;;;; A program's global named as a prelude function takes the name over for
|
||||
;;;; its own file, as a program's function does, and the prelude's own calls
|
||||
;;;; keep the prelude's: sort still swaps with the prelude's swap.
|
||||
(defonce swap i32 3)
|
||||
(defonce clamp i32 4)
|
||||
(defconst reverse i32 5)
|
||||
|
||||
(defn main [] i32
|
||||
(println (+ swap clamp reverse)) ; 12
|
||||
(let [xs [3 1 2]]
|
||||
(sort (slice xs))
|
||||
(println (at xs 0)) ; 1
|
||||
(println (at xs 2))) ; 3
|
||||
0)
|
||||
@ -592,6 +592,11 @@ let () =
|
||||
outputs "a prelude function shadowed" "programs/shadow-prelude.flan" sp_out;
|
||||
outputs ~x86:true "a prelude function shadowed, x86"
|
||||
"programs/shadow-prelude.flan" sp_out;
|
||||
(* And by a program's global, the same way. *)
|
||||
outputs "a prelude function shadowed by a global"
|
||||
"programs/shadow-prelude-global.flan" "12\n1\n3\n";
|
||||
outputs ~x86:true "a prelude function shadowed by a global, x86"
|
||||
"programs/shadow-prelude-global.flan" "12\n1\n3\n";
|
||||
(* (max-value T) and (min-value T), concrete and inside a generic. *)
|
||||
let maxof_out =
|
||||
"255\n0\n127\n-128\n2147483647\n-9223372036854775808\n\
|
||||
|
||||
@ -5953,6 +5953,20 @@ let () =
|
||||
| _ -> check "a defn of a prelude function's name warns exactly once" false);
|
||||
accepts "a defn of a prelude function's name is not defined twice"
|
||||
prelude_src;
|
||||
(* A global takes the name over the same way, with the same warning. *)
|
||||
(match
|
||||
snd (Check.shadow_prelude (Parse.program (Prelude.forms ()))
|
||||
(program "(defonce swap i32 3)"))
|
||||
with
|
||||
| [ d ] ->
|
||||
check "a global of a prelude function's name warns once"
|
||||
(d.Loc.kind = "check/shadows-prelude"
|
||||
&& d.Loc.dmsg
|
||||
= "swap shadows the prelude's swap — every use in this file now \
|
||||
reaches your definition")
|
||||
| _ -> check "a global of a prelude function's name warns exactly once" false);
|
||||
accepts "a global of a prelude function's name is not defined twice"
|
||||
"(defonce swap i32 3)\n(defn f [] i32 swap)";
|
||||
rejects_check "a struct of a prelude type's name is still defined twice"
|
||||
"(defstruct Form [x i32])" ~needle:"Form is defined twice";
|
||||
(* An operator is a builtin like any other and shadows like any other.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user