aboutsummaryrefslogtreecommitdiff
path: root/plugins/extraction/mlutil.ml
diff options
context:
space:
mode:
authorPierre Letouzey2015-12-15 11:15:00 +0100
committerPierre Letouzey2015-12-15 11:24:21 +0100
commit4b197ed247d1f30ff40fa59f85b070766f305bea (patch)
tree86f9a765c493bc1eaf2c3cabfbec64ad3cfa78d5 /plugins/extraction/mlutil.ml
parentce395ca02311bbe6ecc1b2782e74312272dd15ec (diff)
Extraction: replace unused variable names by _ in funs and matchs (fix #2842)
This is done via a unique pass which seems roughly linear in practice, even on big developments like CompCert. There's a List.nth in an env at each MLrel, that could be made logarithmic if necessary via Okasaki's skew list for instance. Another approach would be to keep names (as a form of documentation), but prefix them by _ to please OCaml's warnings. For now, let's be radical and use the _ pattern.
Diffstat (limited to 'plugins/extraction/mlutil.ml')
-rw-r--r--plugins/extraction/mlutil.ml69
1 files changed, 69 insertions, 0 deletions
diff --git a/plugins/extraction/mlutil.ml b/plugins/extraction/mlutil.ml
index bfd0794de2..2b606bf13c 100644
--- a/plugins/extraction/mlutil.ml
+++ b/plugins/extraction/mlutil.ml
@@ -511,6 +511,75 @@ let nb_occur_match =
| MLglob _ | MLexn _ | MLdummy _ | MLaxiom -> 0
in nb 1
+(* Replace unused variables by _ *)
+
+let dump_unused_vars a =
+ let dump_id = function
+ | Dummy -> Dummy
+ | Id _ -> Id dummy_name
+ | Tmp _ -> Tmp dummy_name
+ in
+ let rec ren env a = match a with
+ | MLrel i ->
+ let () = (List.nth env (i-1)) := true in a
+
+ | MLlam (id,b) ->
+ let occ_id = ref false in
+ let b' = ren (occ_id::env) b in
+ if !occ_id then if b' == b then a else MLlam(id,b')
+ else MLlam(dump_id id,b')
+
+ | MLletin (id,b,c) ->
+ let occ_id = ref false in
+ let b' = ren env b in
+ let c' = ren (occ_id::env) c in
+ if !occ_id then
+ if b' == b && c' == c then a else MLletin(id,b',c')
+ else
+ (* 'let' without occurrence: shouldn't happen after simpl *)
+ MLletin(dump_id id,b',c')
+
+ | MLcase (t,e,br) ->
+ let e' = ren env e in
+ let br' = Array.smartmap (ren_branch env) br in
+ if e' == e && br' == br then a else MLcase (t,e',br')
+
+ | MLfix (i,ids,v) ->
+ let env' = List.init (Array.length ids) (fun _ -> ref false) @ env in
+ let v' = Array.smartmap (ren env') v in
+ if v' == v then a else MLfix (i,ids,v')
+
+ | MLapp (b,l) ->
+ let b' = ren env b and l' = List.smartmap (ren env) l in
+ if b' == b && l' == l then a else MLapp (b',l')
+
+ | MLcons(t,r,l) ->
+ let l' = List.smartmap (ren env) l in
+ if l' == l then a else MLcons (t,r,l')
+
+ | MLtuple l ->
+ let l' = List.smartmap (ren env) l in
+ if l' == l then a else MLtuple l'
+
+ | MLmagic b ->
+ let b' = ren env b in
+ if b' == b then a else MLmagic b'
+
+ | MLglob _ | MLexn _ | MLdummy _ | MLaxiom -> a
+
+ and ren_branch env ((ids,p,b) as tr) =
+ let occs = List.map (fun _ -> ref false) ids in
+ let b' = ren (List.rev_append occs env) b in
+ let ids' =
+ List.map2
+ (fun id occ -> if !occ then id else dump_id id)
+ ids occs
+ in
+ if b' == b && List.equal eq_ml_ident ids ids' then tr
+ else (ids',p,b')
+ in
+ ren [] a
+
(*s Lifting on terms.
[ast_lift k t] lifts the binding depth of [t] across [k] bindings. *)