summaryrefslogtreecommitdiff
path: root/typing/parmatch.ml
diff options
context:
space:
mode:
Diffstat (limited to 'typing/parmatch.ml')
-rw-r--r--typing/parmatch.ml263
1 files changed, 0 insertions, 263 deletions
diff --git a/typing/parmatch.ml b/typing/parmatch.ml
deleted file mode 100644
index 8d3ee419bc..0000000000
--- a/typing/parmatch.ml
+++ /dev/null
@@ -1,263 +0,0 @@
-(* Detection of partial matches and unused match cases. *)
-
-open Misc
-open Asttypes
-open Typedtree
-
-
-let make_pat desc ty =
- {pat_desc = desc; pat_loc = Location.none; pat_type = ty}
-
-let omega = make_pat Tpat_any Ctype.none
-
-let rec omegas i =
- if i <= 0 then [] else omega :: omegas (i-1)
-
-let omega_list l = omegas(List.length l)
-
-let has_guard act =
- match act.exp_desc with
- Texp_when(_, _) -> true
- | _ -> false
-
-let simple_match p1 p2 =
- match p1.pat_desc, p2.pat_desc with
- Tpat_construct(c1, _), Tpat_construct(c2, _) ->
- c1.cstr_tag = c2.cstr_tag
- | Tpat_constant(c1), Tpat_constant(c2) ->
- c1 = c2
- | Tpat_tuple(_), Tpat_tuple(_) -> true
- | Tpat_record(_), Tpat_record(_) -> true
- | _, (Tpat_any | Tpat_var(_)) -> true
- | _, _ -> false
-
-(* Return the set of labels and number of fields for a record pattern. *)
-
-let record_labels p =
- match p.pat_desc with
- Tpat_record((lbl1, pat1) :: rem) -> Array.to_list lbl1.lbl_all
- | _ -> fatal_error "Parmatch.record_labels"
-
-let record_num_fields p =
- match p.pat_desc with
- Tpat_record((lbl1, pat1) :: rem) -> Array.length lbl1.lbl_all
- | _ -> fatal_error "Parmatch.record_num_fields"
-
-let set_fields size l =
- let v = Array.new size omega in
- let rec change_rec l = match l with
- (lbl,p)::l -> v.(lbl.lbl_pos) <- p ; change_rec l
- | [] -> () in
- change_rec l;
- Array.to_list v
-
-let simple_match_args p1 p2 =
- match p2.pat_desc with
- Tpat_construct(cstr, args) -> args
- | Tpat_tuple(args) -> args
- | Tpat_record(args) -> set_fields (record_num_fields p1) args
- | (Tpat_any | Tpat_var(_)) ->
- begin match p1.pat_desc with
- Tpat_construct(_, args) -> omega_list args
- | Tpat_tuple(args) -> omega_list args
- | Tpat_record(args) -> omega_list args
- | _ -> []
- end
- | _ -> []
-
-(*
- Computes the discriminating pattern for matching by the first
- column of pss, that is:
- checks for a tuple or a record when q is a variable.
-*)
-
-let rec simple_pat q pss = match pss with
- ({pat_desc = Tpat_alias(p,_)}::ps)::pss ->
- simple_pat q ((p::ps)::pss)
- | ({pat_desc = Tpat_or(p1,p2)}::ps)::pss ->
- simple_pat q ((p1::ps)::(p2::ps)::pss)
- | ({pat_desc = (Tpat_any | Tpat_var(_))}::_)::pss ->
- simple_pat q pss
- | (({pat_desc = Tpat_tuple(args)} as p)::_)::_ ->
- make_pat (Tpat_tuple(omega_list args)) p.pat_type
- | (({pat_desc = Tpat_record(args)} as p)::_)::pss ->
- make_pat (Tpat_record (List.map (fun lbl -> (lbl,omega)) (record_labels p)))
- p.pat_type
- | _ -> q
-
-let filter_one q pss =
- let rec filter_rec = function
- ({pat_desc = Tpat_alias(p,_)}::ps)::pss ->
- filter_rec ((p::ps)::pss)
- | ({pat_desc = Tpat_or(p1,p2)}::ps)::pss ->
- filter_rec ((p1::ps)::(p2::ps)::pss)
- | (p::ps)::pss ->
- if simple_match q p
- then (simple_match_args q p @ ps) :: filter_rec pss
- else filter_rec pss
- | _ -> [] in
- filter_rec pss
-
-let filter_extra pss =
- let rec filter_rec = function
- ({pat_desc = Tpat_alias(p,_)}::ps)::pss ->
- filter_rec ((p::ps)::pss)
- | ({pat_desc = Tpat_or(p1,p2)}::ps)::pss ->
- filter_rec ((p1::ps)::(p2::ps)::pss)
- | ({pat_desc = (Tpat_any | Tpat_var(_))} :: qs) :: pss ->
- qs :: filter_rec pss
- | _::pss -> filter_rec pss
- | [] -> [] in
- filter_rec pss
-
-let filter_all pat0 pss =
-
- let rec insert q qs env =
- match env with
- [] -> [q, [simple_match_args q q @ qs]]
- | ((p,pss) as c)::env ->
- if simple_match q p
- then (p, ((simple_match_args p q @ qs) :: pss)) :: env
- else c :: insert q qs env in
-
- let rec filter_rec env = function
- ({pat_desc = Tpat_alias(p,_)}::ps)::pss ->
- filter_rec env ((p::ps)::pss)
- | ({pat_desc = Tpat_or(p1,p2)}::ps)::pss ->
- filter_rec env ((p1::ps)::(p2::ps)::pss)
- | ({pat_desc = (Tpat_any | Tpat_var(_))}::_)::pss ->
- filter_rec env pss
- | (p::ps)::pss ->
- filter_rec (insert p ps env) pss
- | _ -> env
-
- and filter_omega env = function
- ({pat_desc = Tpat_alias(p,_)}::ps)::pss ->
- filter_omega env ((p::ps)::pss)
- | ({pat_desc = Tpat_or(p1,p2)}::ps)::pss ->
- filter_omega env ((p1::ps)::(p2::ps)::pss)
- | ({pat_desc = (Tpat_any | Tpat_var(_))}::ps)::pss ->
- filter_omega
- (List.map (fun (q,qss) -> (q,(simple_match_args q omega @ ps) :: qss)) env)
- pss
- | _::pss -> filter_omega env pss
- | [] -> env in
-
- filter_omega
- (filter_rec
- (match pat0.pat_desc with
- (Tpat_record(_) | Tpat_tuple(_)) -> [pat0,[]]
- | _ -> [])
- pss)
- pss
-
-
-let full_match env =
- match env with
- ({pat_desc = Tpat_construct(c,_)},_) :: _ ->
- List.length env = c.cstr_span
- | ({pat_desc = Tpat_constant(Const_char _)},_) :: _ ->
- List.length env = 256
- | ({pat_desc = Tpat_constant(_)},_) :: _ -> false
- | ({pat_desc = Tpat_tuple(_)},_) :: _ -> true
- | ({pat_desc = Tpat_record(_)},_) :: _ -> true
- | _ -> fatal_error "Parmatch.full_match"
-
-(*
- Is the last row of pattern matrix pss + qs satisfiable ?
- That is :
- Does there List.exists at least one value vector, es such that :
- 1/ for all ps in pss ps # es (ps and es are not compatible)
- 2/ qs <= es (es matches qs)
-*)
-
-let rec satisfiable pss qs =
- match pss with
- [] -> true
- | _ ->
- match qs with
- [] -> false
- | {pat_desc = Tpat_or(q1,q2)}::qs ->
- satisfiable pss (q1::qs) or satisfiable pss (q2::qs)
- | {pat_desc = Tpat_alias(q,_)}::qs ->
- satisfiable pss (q::qs)
- | {pat_desc = (Tpat_any | Tpat_var(_))}::qs ->
- let q0 = simple_pat omega pss in
- begin match filter_all q0 pss with
- (* first column of pss is made of variables only *)
- [] -> satisfiable (filter_extra pss) qs
- | constrs ->
- let try_non_omega (p,pss) =
- satisfiable pss (simple_match_args p omega @ qs) in
- if full_match constrs
- then List.exists try_non_omega constrs
- else satisfiable (filter_extra pss) qs or
- List.exists try_non_omega constrs
- end
- | q::qs ->
- let q0 = simple_pat q pss in
- satisfiable (filter_one q0 pss) (simple_match_args q0 q @ qs)
-
-let rec initial_matrix = function
- [] -> []
- | (pat, act) :: rem ->
- if has_guard act
- then initial_matrix rem
- else [pat] :: initial_matrix rem
-
-let rec le_pat p q =
- match (p.pat_desc, q.pat_desc) with
- (Tpat_var _ | Tpat_any), _ -> true
- | Tpat_alias(p,_), _ -> le_pat p q
- | _, Tpat_alias(q,_) -> le_pat p q
- | Tpat_or(p1,p2), _ -> le_pat p1 q or le_pat p2 q
- | _, Tpat_or(q1,q2) -> le_pat p q1 & le_pat p q2
- | Tpat_constant(c1), Tpat_constant(c2) -> c1 = c2
- | Tpat_construct(c1,ps), Tpat_construct(c2,qs) ->
- c1.cstr_tag = c2.cstr_tag & le_pats ps qs
- | Tpat_tuple(ps), Tpat_tuple(qs) -> le_pats ps qs
- | Tpat_record(l1), Tpat_record(l2) ->
- let size = record_num_fields p in
- le_pats (set_fields size l1) (set_fields size l2)
- | _, _ -> false
-
-and le_pats ps qs =
- match ps,qs with
- p::ps, q::qs -> le_pat p q & le_pats ps qs
- | _, _ -> true
-
-let get_mins ps =
- let rec select_rec r = function
- [] -> r
- | p::ps ->
- if List.exists (fun p0 -> le_pats p0 p) ps
- then select_rec r ps
- else select_rec (p::r) ps in
- select_rec [] (select_rec [] ps)
-
-let check_partial loc casel =
- let pss = get_mins (initial_matrix casel) in
- if match pss with
- [] -> true
- | ps::_ -> satisfiable pss (List.map (fun _ -> omega) ps)
- then Location.print_warning loc "this pattern-matching is not exhaustive"
-
-let location_of_clause = function
- pat :: _ -> pat.pat_loc
- | _ -> fatal_error "Parmatch.location_of_clause"
-
-let check_unused casel =
- let prefs =
- List.fold_right
- (fun (pat,act as clause) r ->
- if has_guard act
- then ([], ([pat], act)) :: r
- else ([], ([pat], act)) ::
- List.map (fun (pss,clause) -> [pat]::pss,clause) r)
- casel [] in
- List.iter
- (fun (pss, ((qs, _) as clause)) ->
- if not (satisfiable pss qs) then
- Location.print_warning (location_of_clause qs)
- "this match case is unused.")
- prefs