1995-08-09 08:06:35 -07:00
|
|
|
(***********************************************************************)
|
|
|
|
(* *)
|
1996-04-30 07:53:58 -07:00
|
|
|
(* Objective Caml *)
|
1995-08-09 08:06:35 -07:00
|
|
|
(* *)
|
|
|
|
(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
|
|
|
|
(* *)
|
1996-04-30 07:53:58 -07:00
|
|
|
(* Copyright 1996 Institut National de Recherche en Informatique et *)
|
1999-11-17 10:59:06 -08:00
|
|
|
(* en Automatique. All rights reserved. This file is distributed *)
|
|
|
|
(* under the terms of the Q Public License version 1.0. *)
|
1995-08-09 08:06:35 -07:00
|
|
|
(* *)
|
|
|
|
(***********************************************************************)
|
|
|
|
|
|
|
|
(* $Id$ *)
|
|
|
|
|
1995-05-04 03:15:53 -07:00
|
|
|
(* Detection of partial matches and unused match cases. *)
|
|
|
|
|
|
|
|
open Misc
|
|
|
|
open Asttypes
|
1996-09-23 04:33:27 -07:00
|
|
|
open Types
|
1995-05-04 03:15:53 -07:00
|
|
|
open Typedtree
|
|
|
|
|
1999-10-29 07:42:37 -07:00
|
|
|
(****************************************)
|
|
|
|
(* Utilities for retrieving constructor *)
|
|
|
|
(* and record label names *)
|
|
|
|
(****************************************)
|
|
|
|
|
|
|
|
let get_type_descr ty tenv =
|
|
|
|
let ty = Ctype.repr (Ctype.expand_head tenv ty) in
|
|
|
|
match ty.desc with
|
|
|
|
| Tconstr (path,_,_) -> Env.find_type path tenv
|
|
|
|
| _ -> fatal_error "Parmatch.get_type_descr"
|
|
|
|
|
|
|
|
let get_constr tag ty tenv =
|
|
|
|
match get_type_descr ty tenv with
|
|
|
|
| {type_kind=Type_variant constr_list} ->
|
|
|
|
Datarepr.find_constr_by_tag tag constr_list
|
|
|
|
| _ -> fatal_error "Parmatch.get_constr"
|
|
|
|
|
|
|
|
let find_label lbl lbls =
|
|
|
|
try
|
|
|
|
let name,_,_ = List.nth lbls lbl.lbl_pos in
|
|
|
|
name
|
|
|
|
with Failure "nth" -> "*Unkown label*"
|
|
|
|
|
|
|
|
let get_record_labels ty tenv =
|
|
|
|
match get_type_descr ty tenv with
|
|
|
|
| {type_kind = Type_record lbls} -> lbls
|
|
|
|
| _ -> fatal_error "Parmatch.get_record_labels"
|
|
|
|
|
|
|
|
(*************************************)
|
|
|
|
(* Utilities for building patterns *)
|
|
|
|
(*************************************)
|
|
|
|
|
|
|
|
let make_pat desc ty tenv =
|
1998-04-06 02:23:01 -07:00
|
|
|
{pat_desc = desc; pat_loc = Location.none;
|
1999-10-29 07:42:37 -07:00
|
|
|
pat_type = ty ; pat_env = tenv }
|
1995-05-04 03:15:53 -07:00
|
|
|
|
1999-10-29 07:42:37 -07:00
|
|
|
let omega = make_pat Tpat_any Ctype.none Env.empty
|
1995-05-04 03:15:53 -07:00
|
|
|
|
|
|
|
let rec omegas i =
|
|
|
|
if i <= 0 then [] else omega :: omegas (i-1)
|
|
|
|
|
1999-10-29 07:42:37 -07:00
|
|
|
let omega_list l = List.map (fun _ -> omega) l
|
1995-05-04 03:15:53 -07:00
|
|
|
|
1999-10-29 07:42:37 -07:00
|
|
|
(****************************)
|
|
|
|
(* Utilities for matching *)
|
|
|
|
(****************************)
|
1995-05-04 03:15:53 -07:00
|
|
|
|
1999-10-29 07:42:37 -07:00
|
|
|
(* Check top matching *)
|
1995-05-04 03:15:53 -07:00
|
|
|
let simple_match p1 p2 =
|
|
|
|
match p1.pat_desc, p2.pat_desc with
|
1999-10-29 07:42:37 -07:00
|
|
|
| Tpat_construct(c1, _), Tpat_construct(c2, _) ->
|
1995-05-04 03:15:53 -07:00
|
|
|
c1.cstr_tag = c2.cstr_tag
|
1999-11-30 08:07:38 -08:00
|
|
|
| Tpat_variant(l1, _, _), Tpat_variant(l2, _, _) ->
|
|
|
|
l1 = l2
|
1999-10-29 07:42:37 -07:00
|
|
|
| Tpat_constant(Const_float s1), Tpat_constant(Const_float s2) ->
|
|
|
|
float_of_string s1 = float_of_string s2
|
|
|
|
| Tpat_constant(c1), Tpat_constant(c2) -> c1 = c2
|
|
|
|
| Tpat_tuple _, Tpat_tuple _ -> true
|
|
|
|
| Tpat_record _ , Tpat_record _ -> true
|
|
|
|
| Tpat_array p1s, Tpat_array p2s -> List.length p1s = List.length p2s
|
1995-05-04 03:15:53 -07:00
|
|
|
| _, (Tpat_any | Tpat_var(_)) -> true
|
|
|
|
| _, _ -> false
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-10-29 07:42:37 -07:00
|
|
|
(* extract record fields as a whole *)
|
|
|
|
let record_arg p = match p.pat_desc with
|
|
|
|
| Tpat_any -> []
|
|
|
|
| Tpat_record args -> args
|
|
|
|
| _ -> fatal_error "Parmatch.as_record"
|
|
|
|
|
|
|
|
|
|
|
|
(* Raise Not_found when pos is not present in arg *)
|
|
|
|
let get_field pos arg =
|
|
|
|
let _,p = List.find (fun (lbl,_) -> pos = lbl.lbl_pos) arg in
|
|
|
|
p
|
1995-05-04 03:15:53 -07:00
|
|
|
|
|
|
|
|
1999-10-29 07:42:37 -07:00
|
|
|
let extract_fields omegas arg =
|
|
|
|
List.map
|
|
|
|
(fun (lbl,_) ->
|
|
|
|
try
|
|
|
|
get_field lbl.lbl_pos arg
|
|
|
|
with Not_found -> omega)
|
|
|
|
omegas
|
|
|
|
|
|
|
|
let sort_record p = match p.pat_desc with
|
|
|
|
| Tpat_record args ->
|
|
|
|
make_pat
|
|
|
|
(Tpat_record
|
|
|
|
(Sort.list
|
|
|
|
(fun (lbl1,_) (lbl2,_) ->
|
|
|
|
lbl1.lbl_pos <= lbl2.lbl_pos)
|
|
|
|
args))
|
|
|
|
p.pat_type p.pat_env
|
|
|
|
| _ -> p
|
|
|
|
|
|
|
|
(* Build argument list when p2 >= p1, where p1 is a simple pattern *)
|
1995-05-04 03:15:53 -07:00
|
|
|
let simple_match_args p1 p2 =
|
|
|
|
match p2.pat_desc with
|
|
|
|
Tpat_construct(cstr, args) -> args
|
1999-11-30 08:07:38 -08:00
|
|
|
| Tpat_variant(lab, Some arg, _) -> [arg]
|
1995-05-04 03:15:53 -07:00
|
|
|
| Tpat_tuple(args) -> args
|
1999-10-29 07:42:37 -07:00
|
|
|
| Tpat_record(args) -> extract_fields (record_arg p1) args
|
1998-04-06 02:23:01 -07:00
|
|
|
| Tpat_array(args) -> args
|
1995-05-04 03:15:53 -07:00
|
|
|
| (Tpat_any | Tpat_var(_)) ->
|
|
|
|
begin match p1.pat_desc with
|
|
|
|
Tpat_construct(_, args) -> omega_list args
|
1999-11-30 08:07:38 -08:00
|
|
|
| Tpat_variant(_, Some _, _) -> [omega]
|
1995-05-04 03:15:53 -07:00
|
|
|
| Tpat_tuple(args) -> omega_list args
|
|
|
|
| Tpat_record(args) -> omega_list args
|
1998-04-06 02:23:01 -07:00
|
|
|
| Tpat_array(args) -> omega_list args
|
1995-05-04 03:15:53 -07:00
|
|
|
| _ -> []
|
|
|
|
end
|
|
|
|
| _ -> []
|
|
|
|
|
|
|
|
(*
|
1999-10-29 07:42:37 -07:00
|
|
|
Normalize a pattern ->
|
|
|
|
all arguments are omega (simple pattern) and no more variables
|
1995-05-04 03:15:53 -07:00
|
|
|
*)
|
|
|
|
|
1999-10-29 07:42:37 -07:00
|
|
|
let rec normalize_pat q = match q.pat_desc with
|
|
|
|
| Tpat_any | Tpat_constant _ | Tpat_construct (_,[]) -> q
|
|
|
|
| Tpat_var _ -> make_pat Tpat_any q.pat_type q.pat_env
|
|
|
|
| Tpat_alias (p,_) -> normalize_pat q
|
|
|
|
| Tpat_tuple (args) ->
|
|
|
|
make_pat (Tpat_tuple (omega_list args)) q.pat_type q.pat_env
|
|
|
|
| Tpat_construct (c,args) ->
|
|
|
|
make_pat (Tpat_construct (c,omega_list args)) q.pat_type q.pat_env
|
1999-11-30 08:07:38 -08:00
|
|
|
| Tpat_variant (l, arg, row) ->
|
|
|
|
make_pat (Tpat_variant (l, may_map (fun _ -> omega) arg, row))
|
|
|
|
q.pat_type q.pat_env
|
1999-10-29 07:42:37 -07:00
|
|
|
| Tpat_array (args) ->
|
|
|
|
make_pat (Tpat_array (omega_list args)) q.pat_type q.pat_env
|
|
|
|
| Tpat_record (largs) ->
|
|
|
|
make_pat (Tpat_record (List.map (fun (lbl,_) -> lbl,omega) largs))
|
|
|
|
q.pat_type q.pat_env
|
|
|
|
| Tpat_or (_,_) -> fatal_error "Parmatch.normalize_pat"
|
1995-05-04 03:15:53 -07:00
|
|
|
|
1999-10-29 07:42:37 -07:00
|
|
|
|
|
|
|
(*
|
|
|
|
Build normalized (cf. supra) discriminating pattern,
|
|
|
|
in the non-data type case
|
|
|
|
*)
|
|
|
|
|
|
|
|
let discr_pat q pss =
|
|
|
|
|
|
|
|
let rec acc_pat acc pss = match pss with
|
|
|
|
({pat_desc = Tpat_alias (p,_)}::ps)::pss ->
|
|
|
|
acc_pat acc ((p::ps)::pss)
|
|
|
|
| ({pat_desc = Tpat_or (p1,p2)}::ps)::pss ->
|
|
|
|
acc_pat acc ((p1::ps)::(p2::ps)::pss)
|
|
|
|
| ({pat_desc = (Tpat_any | Tpat_var _)}::_)::pss ->
|
|
|
|
acc_pat acc pss
|
|
|
|
| (({pat_desc = Tpat_tuple _} as p)::_)::_ -> normalize_pat p
|
|
|
|
| (({pat_desc = Tpat_record largs} as p)::_)::pss ->
|
|
|
|
let new_omegas =
|
|
|
|
List.fold_left
|
|
|
|
(fun r (lbl,_) ->
|
|
|
|
try
|
|
|
|
let _ = get_field lbl.lbl_pos r in
|
|
|
|
r
|
|
|
|
with Not_found ->
|
|
|
|
(lbl,omega)::r)
|
|
|
|
(record_arg acc)
|
|
|
|
largs in
|
|
|
|
acc_pat
|
|
|
|
(make_pat (Tpat_record new_omegas) p.pat_type p.pat_env)
|
|
|
|
pss
|
|
|
|
| _ -> acc in
|
|
|
|
|
|
|
|
match normalize_pat q with
|
|
|
|
| {pat_desc= (Tpat_any | Tpat_record _)} as q ->
|
|
|
|
sort_record (acc_pat q pss)
|
|
|
|
| q -> q
|
|
|
|
|
|
|
|
(*
|
|
|
|
In case a matching value is found, set actual arguments
|
|
|
|
of the matching pattern.
|
|
|
|
*)
|
|
|
|
|
|
|
|
let rec read_args xs r = match xs,r with
|
|
|
|
| [],_ -> [],r
|
|
|
|
| _::xs, arg::rest ->
|
|
|
|
let args,rest = read_args xs rest in
|
|
|
|
arg::args,rest
|
|
|
|
| _,_ -> fatal_error "Parmatch.read_args"
|
|
|
|
|
|
|
|
|
|
|
|
let set_args q r = match q with
|
|
|
|
| {pat_desc = Tpat_tuple omegas} ->
|
|
|
|
let args,rest = read_args omegas r in
|
|
|
|
make_pat (Tpat_tuple args) q.pat_type q.pat_env::rest
|
|
|
|
| {pat_desc = Tpat_record omegas} ->
|
|
|
|
let args,rest = read_args omegas r in
|
|
|
|
make_pat
|
|
|
|
(Tpat_record
|
|
|
|
(List.map2 (fun (lbl,_) arg -> lbl,arg) omegas args))
|
|
|
|
q.pat_type q.pat_env::
|
|
|
|
rest
|
|
|
|
| {pat_desc = Tpat_construct (c,omegas)} ->
|
|
|
|
let args,rest = read_args omegas r in
|
|
|
|
make_pat
|
|
|
|
(Tpat_construct (c,args)) q.pat_type q.pat_env::
|
|
|
|
rest
|
1999-11-30 08:07:38 -08:00
|
|
|
| {pat_desc = Tpat_variant (l, omega, row)} ->
|
|
|
|
let arg, rest =
|
|
|
|
match omega, r with
|
|
|
|
Some _, a::r -> Some a, r
|
|
|
|
| None, r -> None, r
|
|
|
|
| _ -> assert false
|
|
|
|
in
|
|
|
|
make_pat
|
|
|
|
(Tpat_variant (l, arg, row)) q.pat_type q.pat_env::
|
|
|
|
rest
|
1999-10-29 07:42:37 -07:00
|
|
|
| {pat_desc = Tpat_array omegas} ->
|
|
|
|
let args,rest = read_args omegas r in
|
|
|
|
make_pat
|
|
|
|
(Tpat_array args) q.pat_type q.pat_env::
|
|
|
|
rest
|
|
|
|
| {pat_desc=Tpat_constant c} ->
|
|
|
|
q::r
|
|
|
|
| _ -> fatal_error "Parmatch.set_args"
|
|
|
|
|
|
|
|
|
|
|
|
(* filter pss acording to pattern q *)
|
1995-05-04 03:15:53 -07:00
|
|
|
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
|
|
|
|
|
1999-10-29 07:42:37 -07:00
|
|
|
(*
|
|
|
|
Filter pss in the ``extra case''. This applies :
|
|
|
|
- According to an extra constructor (datatype case, non-complete signature).
|
|
|
|
- Acordinng to anything (all-variables case).
|
|
|
|
*)
|
1995-05-04 03:15:53 -07:00
|
|
|
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
|
|
|
|
|
1999-10-29 07:42:37 -07:00
|
|
|
(*
|
|
|
|
Pattern p0 is the discriminating pattern,
|
|
|
|
returns [(q0,[pss0]) ; ... ; (qn,[pssn])]
|
|
|
|
where the qi's are simple patterns and the pssi's are
|
|
|
|
matched matrices.
|
|
|
|
|
|
|
|
In the case when matching is useless (all-variable case),
|
|
|
|
returns []
|
|
|
|
|
|
|
|
*)
|
1995-05-04 03:15:53 -07:00
|
|
|
let filter_all pat0 pss =
|
|
|
|
|
|
|
|
let rec insert q qs env =
|
|
|
|
match env with
|
1999-10-29 07:42:37 -07:00
|
|
|
[] ->
|
|
|
|
let q0 = normalize_pat q in
|
|
|
|
[q0, [simple_match_args q0 q @ qs]]
|
|
|
|
| ((q0,pss) as c)::env ->
|
|
|
|
if simple_match q0 q
|
|
|
|
then (q0, ((simple_match_args q0 q @ qs) :: pss)) :: env
|
1995-05-04 03:15:53 -07:00
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
(*
|
1999-10-29 07:42:37 -07:00
|
|
|
Check whether the first column of env makes up a complete signature or
|
|
|
|
not.
|
|
|
|
*)
|
|
|
|
|
1999-11-30 08:07:38 -08:00
|
|
|
let full_match tdefs force env = match env with
|
1999-10-29 07:42:37 -07:00
|
|
|
| ({pat_desc = Tpat_construct ({cstr_tag=Cstr_exception _},_)},_)::_ ->
|
|
|
|
false
|
|
|
|
| ({pat_desc = Tpat_construct(c,_)},_) :: _ ->
|
|
|
|
List.length env = c.cstr_consts + c.cstr_nonconsts
|
1999-11-30 08:07:38 -08:00
|
|
|
| ({pat_desc = Tpat_variant(c,_,row); pat_type = ty},_) :: _ ->
|
|
|
|
let fields =
|
|
|
|
List.map
|
|
|
|
(function ({pat_desc = Tpat_variant (tag, _, row)}, _) ->
|
|
|
|
(* You must get a tag's type inside its own row *)
|
|
|
|
tag, List.assoc tag (Btype.row_repr row).row_fields
|
|
|
|
| _ -> assert false)
|
|
|
|
env
|
|
|
|
in
|
|
|
|
let row = Btype.row_repr row in
|
|
|
|
if force then begin
|
|
|
|
if not row.row_closed then begin
|
|
|
|
let more_fields =
|
|
|
|
List.fold_left
|
|
|
|
(fun acc (tag, f) ->
|
|
|
|
if List.mem_assoc tag acc || List.mem_assoc tag row.row_fields
|
|
|
|
then acc
|
|
|
|
else (tag, f)::acc)
|
|
|
|
[] fields
|
|
|
|
in
|
|
|
|
let closed = { row_fields = more_fields; row_more = Ctype.newvar();
|
|
|
|
row_bound = row.row_bound; row_closed = true;
|
|
|
|
row_name = None }
|
|
|
|
(* Cannot fail *)
|
|
|
|
in Ctype.unify tdefs row.row_more (Btype.newgenty (Tvariant closed))
|
|
|
|
end;
|
|
|
|
List.fold_left
|
|
|
|
(fun ok (tag,f) ->
|
|
|
|
match Btype.row_field_repr f with
|
|
|
|
Rabsent -> ok
|
|
|
|
| Reither(_, _, e) ->
|
|
|
|
if not (List.mem_assoc tag fields) then e := Some Rabsent;
|
|
|
|
ok
|
|
|
|
| Rpresent _ ->
|
|
|
|
ok && List.mem_assoc tag fields)
|
|
|
|
true row.row_fields
|
|
|
|
end else
|
|
|
|
row.row_closed &&
|
|
|
|
List.for_all
|
|
|
|
(fun (tag,f) ->
|
|
|
|
Btype.row_field_repr f = Rabsent || List.mem_assoc tag fields)
|
|
|
|
row.row_fields
|
1999-10-29 07:42:37 -07:00
|
|
|
| ({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
|
|
|
|
| ({pat_desc = Tpat_array(_)},_) :: _ -> false
|
|
|
|
| _ -> fatal_error "Parmatch.full_match"
|
|
|
|
|
|
|
|
let complete_tags nconsts nconstrs tags =
|
|
|
|
let seen_const = Array.create nconsts false
|
|
|
|
and seen_constr = Array.create nconstrs false in
|
|
|
|
List.iter
|
|
|
|
(function
|
|
|
|
| Cstr_constant i -> seen_const.(i) <- true
|
|
|
|
| Cstr_block i -> seen_constr.(i) <- true
|
|
|
|
| _ -> assert false)
|
|
|
|
tags ;
|
|
|
|
let r = ref [] in
|
|
|
|
for i = 0 to nconsts-1 do
|
|
|
|
if not seen_const.(i) then
|
|
|
|
r := Cstr_constant i :: !r
|
|
|
|
done ;
|
|
|
|
for i = 0 to nconstrs-1 do
|
|
|
|
if not seen_constr.(i) then
|
|
|
|
r := Cstr_block i :: !r
|
|
|
|
done ;
|
|
|
|
!r
|
|
|
|
|
|
|
|
(*
|
|
|
|
Builds a pattern that is incompatible with all patterns in
|
|
|
|
in the first column of env
|
|
|
|
*)
|
|
|
|
|
|
|
|
|
|
|
|
let build_other env = match env with
|
|
|
|
| ({pat_desc = Tpat_construct ({cstr_tag=Cstr_exception _} as c,_)},_) as p
|
|
|
|
::_ ->
|
|
|
|
make_pat
|
|
|
|
(Tpat_construct
|
|
|
|
({c with
|
|
|
|
cstr_tag=(Cstr_exception
|
|
|
|
(Path.Pident (Ident.create "*exception*")))},
|
|
|
|
[]))
|
|
|
|
Ctype.none Env.empty
|
|
|
|
| ({pat_desc = Tpat_construct (c,_)} as p,_) :: _ ->
|
|
|
|
begin try
|
|
|
|
|
|
|
|
let get_tag = function
|
|
|
|
| {pat_desc = Tpat_construct (c,_)} -> c.cstr_tag
|
|
|
|
| _ -> fatal_error "Parmatch.get_tag" in
|
|
|
|
let all_tags =
|
|
|
|
List.map (fun (p,_) -> get_tag p) env in
|
|
|
|
|
|
|
|
let not_tags = complete_tags c.cstr_consts c.cstr_nonconsts all_tags in
|
|
|
|
let make_other_pat tag =
|
|
|
|
let _,targs = get_constr tag p.pat_type p.pat_env in
|
|
|
|
make_pat
|
|
|
|
(Tpat_construct
|
|
|
|
({c with
|
|
|
|
cstr_tag = tag ;
|
|
|
|
cstr_args = targs ;
|
|
|
|
cstr_arity = List.length targs},
|
|
|
|
omega_list targs))
|
|
|
|
p.pat_type p.pat_env in
|
|
|
|
begin match not_tags with
|
|
|
|
| [] -> omega (* should not occur, because full_match env is true *)
|
|
|
|
| t::rest ->
|
|
|
|
List.fold_left
|
|
|
|
(fun p_res tag ->
|
|
|
|
make_pat
|
|
|
|
(Tpat_or (make_other_pat tag, p_res))
|
|
|
|
p.pat_type p.pat_env)
|
|
|
|
(make_other_pat t)
|
|
|
|
rest
|
|
|
|
end
|
|
|
|
with
|
|
|
|
| Datarepr.Constr_not_found -> omega
|
|
|
|
end
|
1999-11-30 08:07:38 -08:00
|
|
|
| ({pat_desc = Tpat_variant(_,_,row)} as p,_) :: _ ->
|
|
|
|
let tags =
|
|
|
|
List.map
|
|
|
|
(function ({pat_desc = Tpat_variant (tag, _, _)}, _) -> tag
|
|
|
|
| _ -> assert false)
|
|
|
|
env
|
|
|
|
in
|
|
|
|
let row = Btype.row_repr row in
|
|
|
|
let make_other_pat tag const =
|
|
|
|
let arg = if const then None else Some omega in
|
|
|
|
make_pat (Tpat_variant(tag, arg, row)) p.pat_type p.pat_env in
|
|
|
|
begin match
|
|
|
|
List.fold_left
|
|
|
|
(fun others (tag,f) -> match Btype.row_field_repr f with
|
|
|
|
Rabsent | Reither _ -> others
|
|
|
|
| Rpresent arg -> make_other_pat tag (arg = None) :: others)
|
|
|
|
[] row.row_fields
|
|
|
|
with [] -> assert false
|
|
|
|
| pat::other_pats ->
|
|
|
|
List.fold_left
|
|
|
|
(fun p_res pat ->
|
|
|
|
make_pat (Tpat_or (pat, p_res)) p.pat_type p.pat_env)
|
|
|
|
pat other_pats
|
|
|
|
end
|
1999-10-29 07:42:37 -07:00
|
|
|
| ({pat_desc = Tpat_constant(Const_char _)} as p,_) :: _ ->
|
|
|
|
let all_chars =
|
|
|
|
List.map
|
|
|
|
(fun (p,_) -> match p.pat_desc with
|
|
|
|
| Tpat_constant (Const_char c) -> c
|
|
|
|
| _ -> assert false)
|
|
|
|
env in
|
|
|
|
|
|
|
|
let rec find_other i imax =
|
|
|
|
if i > imax then raise Not_found
|
|
|
|
else
|
|
|
|
let ci = Char.chr i in
|
|
|
|
if List.mem ci all_chars then
|
|
|
|
find_other (i+1) imax
|
|
|
|
else
|
|
|
|
make_pat (Tpat_constant (Const_char ci)) p.pat_type p.pat_env in
|
|
|
|
let rec try_chars = function
|
|
|
|
| [] -> omega
|
|
|
|
| (c1,c2) :: rest ->
|
|
|
|
try
|
|
|
|
find_other (Char.code c1) (Char.code c2)
|
|
|
|
with
|
|
|
|
| Not_found -> try_chars rest in
|
|
|
|
|
|
|
|
try_chars
|
|
|
|
[ 'a', 'z' ; 'A', 'Z' ; '0', '9' ;
|
|
|
|
' ', '~' ; Char.chr 0 , Char.chr 255]
|
|
|
|
| ({pat_desc=(Tpat_constant (Const_int _))} as p,_) :: _ ->
|
|
|
|
let all_ints =
|
|
|
|
List.map
|
|
|
|
(fun (p,_) -> match p.pat_desc with
|
|
|
|
| Tpat_constant (Const_int i) -> i
|
|
|
|
| _ -> assert false)
|
|
|
|
env in
|
|
|
|
let rec try_ints i =
|
|
|
|
if List.mem i all_ints then try_ints (i+1)
|
|
|
|
else
|
|
|
|
make_pat
|
|
|
|
(Tpat_constant (Const_int i)) p.pat_type p.pat_env in
|
|
|
|
try_ints 0
|
|
|
|
| ({pat_desc=(Tpat_constant (Const_string _))} as p,_) :: _ ->
|
|
|
|
let all_lengths =
|
|
|
|
List.map
|
|
|
|
(fun (p,_) -> match p.pat_desc with
|
|
|
|
| Tpat_constant (Const_string s) -> String.length s
|
|
|
|
| _ -> assert false)
|
|
|
|
env in
|
|
|
|
let rec try_strings i =
|
|
|
|
if List.mem i all_lengths then try_strings (i+1)
|
|
|
|
else
|
|
|
|
make_pat
|
|
|
|
(Tpat_constant (Const_string (String.make i '*')))
|
|
|
|
p.pat_type p.pat_env in
|
|
|
|
try_strings 0
|
|
|
|
| ({pat_desc=(Tpat_constant (Const_float _))} as p,_) :: _ ->
|
|
|
|
let all_floats =
|
|
|
|
List.map
|
|
|
|
(fun (p,_) -> match p.pat_desc with
|
|
|
|
| Tpat_constant (Const_float s) -> float_of_string s
|
|
|
|
| _ -> assert false)
|
|
|
|
env in
|
|
|
|
let rec try_floats f =
|
|
|
|
if List.mem f all_floats then try_floats (f +. 1.0)
|
|
|
|
else
|
|
|
|
make_pat
|
|
|
|
(Tpat_constant (Const_float (string_of_float f^".0")))
|
|
|
|
p.pat_type p.pat_env in
|
|
|
|
try_floats 0.0
|
|
|
|
| ({pat_desc = Tpat_array args} as p,_)::_ ->
|
|
|
|
let all_lengths =
|
|
|
|
List.map
|
|
|
|
(fun (p,_) -> match p.pat_desc with
|
|
|
|
| Tpat_array args -> List.length args
|
|
|
|
| _ -> assert false)
|
|
|
|
env in
|
|
|
|
let rec try_arrays l =
|
|
|
|
if List.mem l all_lengths then try_arrays (l+1)
|
|
|
|
else
|
|
|
|
make_pat
|
|
|
|
(Tpat_array (omegas l))
|
|
|
|
p.pat_type p.pat_env in
|
|
|
|
try_arrays 0
|
|
|
|
| [] -> omega
|
|
|
|
| _ -> omega
|
|
|
|
|
|
|
|
(*
|
|
|
|
Core function :
|
1995-05-04 03:15:53 -07:00
|
|
|
Is the last row of pattern matrix pss + qs satisfiable ?
|
1999-10-29 07:42:37 -07:00
|
|
|
That is :
|
|
|
|
Does there 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)
|
|
|
|
|
|
|
|
Moreover, when argument buid is true, a matching value is returned.
|
1995-05-04 03:15:53 -07:00
|
|
|
*)
|
|
|
|
|
1999-11-09 02:53:31 -08:00
|
|
|
type 'a result = Rnone | Rsome of 'a | Rok
|
1999-10-29 07:42:37 -07:00
|
|
|
|
|
|
|
let rec try_many f = function
|
1999-11-09 02:53:31 -08:00
|
|
|
| [] -> Rnone
|
1999-10-29 07:42:37 -07:00
|
|
|
| x::rest ->
|
|
|
|
begin match f x with
|
1999-11-09 02:53:31 -08:00
|
|
|
| Rnone -> try_many f rest
|
1999-10-29 07:42:37 -07:00
|
|
|
| r -> r
|
|
|
|
end
|
|
|
|
|
1999-11-30 08:07:38 -08:00
|
|
|
let rec satisfiable tdefs build pss qs =
|
1995-05-04 03:15:53 -07:00
|
|
|
match pss with
|
1999-11-09 02:53:31 -08:00
|
|
|
[] -> if build then Rsome qs else Rok (* qs is a matching vector *)
|
1995-05-04 03:15:53 -07:00
|
|
|
| _ ->
|
|
|
|
match qs with
|
1999-11-09 02:53:31 -08:00
|
|
|
[] -> Rnone
|
1995-05-04 03:15:53 -07:00
|
|
|
| {pat_desc = Tpat_or(q1,q2)}::qs ->
|
1999-11-30 08:07:38 -08:00
|
|
|
begin match satisfiable tdefs build pss (q1::qs) with
|
|
|
|
| Rnone -> satisfiable tdefs build pss (q2::qs)
|
1999-10-29 07:42:37 -07:00
|
|
|
| r -> r
|
|
|
|
end
|
1995-05-04 03:15:53 -07:00
|
|
|
| {pat_desc = Tpat_alias(q,_)}::qs ->
|
1999-11-30 08:07:38 -08:00
|
|
|
satisfiable tdefs build pss (q::qs)
|
1995-05-04 03:15:53 -07:00
|
|
|
| {pat_desc = (Tpat_any | Tpat_var(_))}::qs ->
|
1999-10-29 07:42:37 -07:00
|
|
|
let q0 = discr_pat omega pss in
|
1995-05-04 03:15:53 -07:00
|
|
|
begin match filter_all q0 pss with
|
|
|
|
(* first column of pss is made of variables only *)
|
1999-11-30 08:07:38 -08:00
|
|
|
[] -> begin match satisfiable tdefs build (filter_extra pss) qs with
|
1999-11-09 02:53:31 -08:00
|
|
|
| Rsome r -> Rsome (q0::r)
|
1999-10-29 07:42:37 -07:00
|
|
|
| r -> r
|
|
|
|
end
|
1995-05-04 03:15:53 -07:00
|
|
|
| constrs ->
|
|
|
|
let try_non_omega (p,pss) =
|
1999-11-30 08:07:38 -08:00
|
|
|
match
|
|
|
|
satisfiable tdefs build pss (simple_match_args p omega @ qs)
|
|
|
|
with
|
1999-11-09 02:53:31 -08:00
|
|
|
| Rsome r -> Rsome (set_args p r)
|
1999-10-29 07:42:37 -07:00
|
|
|
| r -> r in
|
1999-11-30 08:07:38 -08:00
|
|
|
if full_match tdefs build constrs
|
1999-10-29 07:42:37 -07:00
|
|
|
then try_many try_non_omega constrs
|
|
|
|
else
|
1999-11-30 08:07:38 -08:00
|
|
|
match satisfiable tdefs build (filter_extra pss) qs with
|
1999-11-09 02:53:31 -08:00
|
|
|
| Rnone -> try_many try_non_omega constrs
|
|
|
|
| Rok -> Rok
|
|
|
|
| Rsome r -> Rsome (build_other constrs::r)
|
1995-05-04 03:15:53 -07:00
|
|
|
end
|
|
|
|
| q::qs ->
|
1999-10-29 07:42:37 -07:00
|
|
|
let q0 = discr_pat q pss in
|
|
|
|
match
|
1999-11-30 08:07:38 -08:00
|
|
|
satisfiable tdefs build (filter_one q0 pss)
|
|
|
|
(simple_match_args q0 q @ qs)
|
1999-10-29 07:42:37 -07:00
|
|
|
with
|
1999-11-09 02:53:31 -08:00
|
|
|
| Rsome r -> Rsome (set_args q0 r)
|
1999-10-29 07:42:37 -07:00
|
|
|
| r -> r
|
|
|
|
|
|
|
|
|
|
|
|
let has_guard act =
|
|
|
|
match act.exp_desc with
|
|
|
|
Texp_when(_, _) -> true
|
|
|
|
| _ -> false
|
|
|
|
|
|
|
|
(*
|
|
|
|
Build up a working pattern matrix.
|
|
|
|
1- Retain minimal patterns (for optimizing when catch all's are here)
|
|
|
|
2- Forget about guarded patterns
|
|
|
|
*)
|
1995-05-04 03:15:53 -07:00
|
|
|
|
|
|
|
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) ->
|
1998-04-06 02:23:01 -07:00
|
|
|
c1.cstr_tag = c2.cstr_tag && le_pats ps qs
|
1999-11-30 08:07:38 -08:00
|
|
|
| Tpat_variant(l1,Some p1,_), Tpat_variant(l2,Some p2,_) ->
|
|
|
|
l1 = l2 & le_pat p1 p2
|
|
|
|
| Tpat_variant(l1,None,_), Tpat_variant(l2,None,_) -> l1 = l2
|
1995-05-04 03:15:53 -07:00
|
|
|
| Tpat_tuple(ps), Tpat_tuple(qs) -> le_pats ps qs
|
1999-10-29 07:42:37 -07:00
|
|
|
| Tpat_record l1, Tpat_record l2 ->
|
|
|
|
let ps = List.map (fun (_,p) -> p) l1
|
|
|
|
and qs = extract_fields l1 l2 in
|
|
|
|
le_pats ps qs
|
1998-04-06 02:23:01 -07:00
|
|
|
| Tpat_array(ps), Tpat_array(qs) ->
|
|
|
|
List.length ps = List.length qs && le_pats ps qs
|
1995-05-04 03:15:53 -07:00
|
|
|
| _, _ -> false
|
|
|
|
|
|
|
|
and le_pats ps qs =
|
|
|
|
match ps,qs with
|
1998-04-06 02:23:01 -07:00
|
|
|
p::ps, q::qs -> le_pat p q && le_pats ps qs
|
1995-05-04 03:15:53 -07:00
|
|
|
| _, _ -> 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)
|
|
|
|
|
1999-10-29 07:42:37 -07:00
|
|
|
|
|
|
|
|
|
|
|
(*************************************)
|
|
|
|
(* Values as patterns pretty printer *)
|
|
|
|
(*************************************)
|
|
|
|
|
|
|
|
open Format
|
|
|
|
;;
|
|
|
|
|
|
|
|
let get_constr_name tag ty tenv = match tag with
|
|
|
|
| Cstr_exception path -> Path.name path
|
|
|
|
| _ ->
|
|
|
|
try
|
|
|
|
let name,_ = get_constr tag ty tenv in name
|
|
|
|
with
|
|
|
|
| Datarepr.Constr_not_found -> "*Unknown constructor*"
|
|
|
|
|
|
|
|
let is_cons tag v = match get_constr_name tag v.pat_type v.pat_env with
|
|
|
|
| "::" -> true
|
|
|
|
| _ -> false
|
|
|
|
|
|
|
|
|
|
|
|
let rec pretty_val ppf v = match v.pat_desc with
|
|
|
|
| Tpat_any | Tpat_var _ -> fprintf ppf "_"
|
|
|
|
| Tpat_constant (Const_int i) -> fprintf ppf "%d" i
|
|
|
|
| Tpat_constant (Const_char c) ->
|
|
|
|
fprintf ppf "'%s'" (Char.escaped c)
|
|
|
|
| Tpat_constant (Const_string s) ->
|
|
|
|
fprintf ppf "\"%s\"" (String.escaped s)
|
|
|
|
| Tpat_constant (Const_float s) ->
|
|
|
|
fprintf ppf "%s" s
|
|
|
|
| Tpat_tuple vs ->
|
|
|
|
fprintf ppf "@[(%a)@]" (pretty_vals ",") vs
|
|
|
|
| Tpat_construct ({cstr_tag=tag},[]) ->
|
|
|
|
let name = get_constr_name tag v.pat_type v.pat_env in
|
|
|
|
fprintf ppf "%s" name
|
|
|
|
| Tpat_construct ({cstr_tag=tag},[w]) ->
|
|
|
|
let name = get_constr_name tag v.pat_type v.pat_env in
|
|
|
|
fprintf ppf "@[<2>%s@ %a@]" name pretty_arg w
|
|
|
|
| Tpat_construct ({cstr_tag=tag},vs) ->
|
|
|
|
let name = get_constr_name tag v.pat_type v.pat_env in
|
|
|
|
begin match (name, vs) with
|
|
|
|
("::", [v1;v2]) ->
|
|
|
|
fprintf ppf "@[%a::@,%a@]" pretty_car v1 pretty_cdr v2
|
|
|
|
| _ ->
|
|
|
|
fprintf ppf "@[<2>%s@ @[(%a)@]@]" name (pretty_vals ",") vs
|
|
|
|
end
|
1999-11-30 08:07:38 -08:00
|
|
|
| Tpat_variant (l, None, _) ->
|
|
|
|
fprintf ppf "`%s" l
|
|
|
|
| Tpat_variant (l, Some w, _) ->
|
|
|
|
fprintf ppf "@[<2`%s@ %a@]" l pretty_arg w
|
1999-10-29 07:42:37 -07:00
|
|
|
| Tpat_record lvs ->
|
|
|
|
fprintf ppf "@[{%a}@]"
|
|
|
|
(pretty_lvals (get_record_labels v.pat_type v.pat_env))
|
|
|
|
(List.filter
|
|
|
|
(function
|
|
|
|
| (_,{pat_desc=Tpat_any}) -> false
|
|
|
|
| _ -> true) lvs)
|
|
|
|
| Tpat_array vs ->
|
|
|
|
fprintf ppf "@[[| %a |]@]" (pretty_vals " ;") vs
|
|
|
|
| Tpat_alias (v,_) -> pretty_val ppf v
|
|
|
|
| Tpat_or (v,w) ->
|
|
|
|
fprintf ppf "@[(%a|@,%a)@]" pretty_or v pretty_or w
|
|
|
|
|
|
|
|
and pretty_car ppf v = match v.pat_desc with
|
|
|
|
| Tpat_construct ({cstr_tag=tag}, [_ ; _])
|
|
|
|
when is_cons tag v ->
|
|
|
|
fprintf ppf "(%a)" pretty_val v
|
|
|
|
| _ -> pretty_val ppf v
|
|
|
|
|
|
|
|
and pretty_cdr ppf v = match v.pat_desc with
|
|
|
|
| Tpat_construct ({cstr_tag=tag}, [v1 ; v2])
|
|
|
|
when is_cons tag v ->
|
|
|
|
fprintf ppf "%a::@,%a" pretty_car v1 pretty_cdr v2
|
|
|
|
| _ -> pretty_val ppf v
|
|
|
|
|
|
|
|
and pretty_arg ppf v = match v.pat_desc with
|
|
|
|
| Tpat_construct (_,_::_) -> fprintf ppf "(%a)" pretty_val v
|
|
|
|
| _ -> pretty_val ppf v
|
|
|
|
|
|
|
|
and pretty_or ppf v = match v.pat_desc with
|
|
|
|
| Tpat_or (v,w) ->
|
|
|
|
fprintf ppf "%a|@,%a" pretty_or v pretty_or w
|
|
|
|
| _ -> pretty_val ppf v
|
|
|
|
|
|
|
|
and pretty_vals sep ppf = function
|
|
|
|
| [] -> ()
|
|
|
|
| [v] -> pretty_val ppf v
|
|
|
|
| v::vs ->
|
|
|
|
fprintf ppf "%a%s@ %a" pretty_val v sep (pretty_vals sep) vs
|
|
|
|
|
|
|
|
and pretty_lvals lbls ppf = function
|
|
|
|
| [] -> ()
|
|
|
|
| [lbl,v] ->
|
|
|
|
let name = find_label lbl lbls in
|
|
|
|
fprintf ppf "%s=%a" name pretty_val v
|
|
|
|
| (lbl,v)::rest ->
|
|
|
|
let name = find_label lbl lbls in
|
|
|
|
fprintf ppf "%s=%a;@ %a" name pretty_val v (pretty_lvals lbls) rest
|
|
|
|
|
|
|
|
let top_pretty ppf v =
|
1999-11-08 15:05:03 -08:00
|
|
|
fprintf ppf "@[%a@]@?" pretty_val v
|
1999-10-29 07:42:37 -07:00
|
|
|
|
|
|
|
|
|
|
|
(******************************)
|
|
|
|
(* Exported functions *)
|
|
|
|
(* - Partial match *)
|
|
|
|
(* - Unused match case *)
|
|
|
|
(******************************)
|
|
|
|
|
1999-11-30 08:07:38 -08:00
|
|
|
let check_partial tdefs loc casel =
|
1995-05-04 03:15:53 -07:00
|
|
|
let pss = get_mins (initial_matrix casel) in
|
1999-10-29 07:42:37 -07:00
|
|
|
let r = match pss with
|
|
|
|
| [] -> begin match casel with
|
1999-11-09 02:53:31 -08:00
|
|
|
| [] -> Rnone
|
|
|
|
| (p,_) :: _ -> Rsome [p]
|
1999-10-29 07:42:37 -07:00
|
|
|
end
|
1999-11-30 08:07:38 -08:00
|
|
|
| ps::_ -> satisfiable tdefs true pss (omega_list ps) in
|
1999-10-29 07:42:37 -07:00
|
|
|
match r with
|
1999-11-30 08:07:38 -08:00
|
|
|
| Rnone -> Total
|
1999-11-09 02:53:31 -08:00
|
|
|
| Rok ->
|
1999-11-30 08:07:38 -08:00
|
|
|
Location.print_warning loc (Warnings.Partial_match "");
|
|
|
|
Partial
|
1999-11-09 02:53:31 -08:00
|
|
|
| Rsome [v] ->
|
1999-10-29 07:42:37 -07:00
|
|
|
let errmsg =
|
|
|
|
try
|
|
|
|
let buf = Buffer.create 16 in
|
|
|
|
let fmt = formatter_of_buffer buf in
|
|
|
|
top_pretty fmt v;
|
|
|
|
Buffer.contents buf
|
|
|
|
with _ ->
|
|
|
|
"" in
|
1999-11-30 08:07:38 -08:00
|
|
|
Location.print_warning loc (Warnings.Partial_match errmsg);
|
|
|
|
Partial
|
1999-10-29 07:42:37 -07:00
|
|
|
| _ ->
|
|
|
|
fatal_error "Parmatch.check_partial"
|
1995-05-04 03:15:53 -07:00
|
|
|
|
|
|
|
let location_of_clause = function
|
|
|
|
pat :: _ -> pat.pat_loc
|
|
|
|
| _ -> fatal_error "Parmatch.location_of_clause"
|
|
|
|
|
1999-11-30 08:07:38 -08:00
|
|
|
let check_unused tdefs casel =
|
1995-05-04 03:15:53 -07:00
|
|
|
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)) ->
|
1999-10-29 07:42:37 -07:00
|
|
|
try
|
|
|
|
if
|
1999-11-30 08:07:38 -08:00
|
|
|
(match satisfiable tdefs false pss qs with
|
1999-11-09 02:53:31 -08:00
|
|
|
| Rnone -> true
|
|
|
|
| Rok -> false
|
1999-10-29 07:42:37 -07:00
|
|
|
| _ -> assert false)
|
|
|
|
then
|
|
|
|
Location.print_warning (location_of_clause qs) Warnings.Unused_match
|
|
|
|
with e ->
|
|
|
|
Location.print_warning (location_of_clause qs)
|
|
|
|
(Warnings.Other "Fatal Error") ;
|
|
|
|
raise e)
|
1995-05-04 03:15:53 -07:00
|
|
|
prefs
|