let rec check_unused ~lib tm =
let rec check ?(toplevel=false) v tm = match tm.term with
| Var s -> Vars.remove s v
| Unit | Bool _ | Int _ | String _ | Float _ | Encoder _ -> v
| Ref r -> check v r
| Get r -> check v r
| Product (a,b) | Set (a,b) -> check (check v a) b
| Seq (a,b) -> check ~toplevel (check v a) b
| List l -> List.fold_left check v l
| App (hd,l) ->
let v = check v hd in
List.fold_left (fun v (lbl,t) -> check v t) v l
| Fun (fv,p,body) ->
let v =
List.fold_left
(fun v -> function
| (_,_,_,Some default) -> check v default
| _ -> v)
v p
in
let masked,v =
let v0 = v in
List.fold_left
(fun (masked,v) (_,var,_,_) ->
if Vars.mem var v0 then
Vars.add var masked, v
else
masked, Vars.add var v)
(Vars.empty, v) p
in
let v = check v body in
Vars.union masked v
| Let { var = s ; def = def ; body = body } ->
let v = check v def in
let mask = Vars.mem s v in
let v = Vars.add s v in
let v = check ~toplevel v body in
begin
if not (toplevel && lib) then
if Vars.mem s v then
if not (can_ignore def.t || (toplevel && is_fun def.t)) then
let start_pos = fst (Utils.get_some tm.t.T.pos) in
if !errors_as_warnings then
Printf.printf
"Warning: unused variable %s at %s.\n%!"
s (T.print_single_pos start_pos)
else
raise (Unused_variable (s,start_pos))
end ;
if mask then Vars.add s v else v
in
ignore (check ~toplevel:true Vars.empty tm)