aboutsummaryrefslogtreecommitdiff
path: root/kernel/term.ml
diff options
context:
space:
mode:
authorherbelin2000-09-10 07:19:28 +0000
committerherbelin2000-09-10 07:19:28 +0000
commit79dc33cbc403ebab0bd1fe815c13f740f0a1b850 (patch)
treee38e167003d7dd97d95a59ea7c026a1629b346f8 /kernel/term.ml
parentc0ff579606f2eba24bc834316d8bb7bcc076000d (diff)
Ajout d'un LetIn primitif.
Abstraction de constr via kind_of_constr dans une bonne partie du code. git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/coq/trunk@591 85f007b7-540e-0410-9357-904b9bb8a0f7
Diffstat (limited to 'kernel/term.ml')
-rw-r--r--kernel/term.ml1193
1 files changed, 673 insertions, 520 deletions
diff --git a/kernel/term.ml b/kernel/term.ml
index f4c074471a..40feeaab12 100644
--- a/kernel/term.ml
+++ b/kernel/term.ml
@@ -6,7 +6,6 @@
open Util
open Pp
open Names
-open Generic
open Univ
(* Coq abstract syntax with deBruijn variables; 'a is the type of sorts *)
@@ -64,14 +63,34 @@ let print_sort = function
| Prop Null -> [< 'sTR "Prop" >]
| Type _ -> [< 'sTR "Type" >]
-type constr = sorts oper term
+(********************************************************************)
+(* Generic syntax of terms with de Bruijn indexes *)
+(********************************************************************)
+
+type constr =
+ | DOP0 of sorts oper (* atomic terms *)
+ | DOP1 of sorts oper * constr (* operator of arity 1 *)
+ | DOP2 of sorts oper * constr * constr (* operator of arity 2 *)
+ | DOPN of sorts oper * constr array (* operator of variadic arity *)
+ | DLAM of name * constr (* deBruijn binder on one term *)
+ | DLAMV of name * constr array (* deBruijn binder on many terms *)
+ | CLam of name * constr * constr
+ | CPrd of name * constr * constr
+ | CLet of name * constr * constr * constr
+ | VAR of identifier (* named variable *)
+ | Rel of int (* variable as deBruijn index *)
+
+and
+ (*
+ typed_type = sorts judge
+ *)
+ typed_type = constr
type flat_arity = (name * constr) list * sorts
type 'a judge = { body : constr; typ : 'a }
(*
-type typed_type = sorts judge
type typed_term = typed_type judge
let make_typed t s = { body = t; typ = s }
@@ -91,7 +110,6 @@ let outcast_type = function
let typed_combine f g t u = { f t.body u.body ; g t.typ u.typ}
*)
-type typed_type = constr
type typed_term = typed_type judge
let make_typed t s = t
@@ -115,15 +133,281 @@ type rel_declaration = name * constr option * typed_type
(****************************************************************************)
(*********************)
+(* Occurring *)
+(*********************)
+
+exception FreeVar
+exception Occur
+
+(* (closedn n M) raises FreeVar if a variable of height greater than n
+ occurs in M, returns () otherwise *)
+
+let closedn =
+ let rec closed_rec n = function
+ | Rel(m) -> if m>n then raise FreeVar
+ | VAR _ -> ()
+ | DOPN(_,cl) -> Array.iter (closed_rec n) cl
+ | DOP2(_,c1,c2) -> closed_rec n c1; closed_rec n c2
+ | DOP1(_,c) -> closed_rec n c
+ | DLAM(_,c) -> closed_rec (n+1) c
+ | DLAMV(_,v) -> Array.iter (closed_rec (n+1)) v
+ | CLam (_,t,c) -> closed_rec n t; closed_rec (n+1) c
+ | CPrd (_,t,c) -> closed_rec n t; closed_rec (n+1) c
+ | CLet (_,b,t,c) -> closed_rec n b; closed_rec n t; closed_rec (n+1) c
+ | _ -> ()
+ in
+ closed_rec
+
+(* [closed0 M] is true iff [M] is a (deBruijn) closed term *)
+
+let closed0 term =
+ try closedn 0 term; true with FreeVar -> false
+
+(* returns the list of free debruijn indices in a term *)
+
+let free_rels m =
+ let rec frec depth acc = function
+ | Rel n -> if n >= depth then Intset.add (n-depth+1) acc else acc
+ | DOPN(_,cl) -> Array.fold_left (frec depth) acc cl
+ | DOP2(_,c1,c2) -> frec depth (frec depth acc c1) c2
+ | DOP1(_,c) -> frec depth acc c
+ | DLAM(_,c) -> frec (depth+1) acc c
+ | DLAMV(_,cl) -> Array.fold_left (frec (depth+1)) acc cl
+ | CLam (_,t,c) -> frec (depth+1) (frec depth acc t) c
+ | CPrd (_,t,c) -> frec (depth+1) (frec depth acc t) c
+ | CLet (_,b,t,c) -> frec (depth+1) (frec depth (frec depth acc b) t) c
+ | VAR _ -> acc
+ | DOP0 _ -> acc
+ in
+ frec 1 Intset.empty m
+
+(* (noccurn n M) returns true iff (Rel n) does NOT occur in term M *)
+
+let noccurn n term =
+ let rec occur_rec n = function
+ | Rel(m) -> if m = n then raise Occur
+ | VAR _ -> ()
+ | DOPN(_,cl) -> Array.iter (occur_rec n) cl
+ | DOP1(_,c) -> occur_rec n c
+ | DOP2(_,c1,c2) -> occur_rec n c1; occur_rec n c2
+ | DLAM(_,c) -> occur_rec (n+1) c
+ | DLAMV(_,v) -> Array.iter (occur_rec (n+1)) v
+ | CLam (_,t,c) -> occur_rec n t; occur_rec (n+1) c
+ | CPrd (_,t,c) -> occur_rec n t; occur_rec (n+1) c
+ | CLet (_,b,t,c) -> occur_rec n b; occur_rec n t; occur_rec (n+1) c
+ | _ -> ()
+ in
+ try occur_rec n term; true with Occur -> false
+
+(* (noccur_between n m M) returns true iff (Rel p) does NOT occur in term M
+ for n <= p < n+m *)
+
+let noccur_between n m term =
+ let rec occur_rec n = function
+ | Rel(p) -> if n<=p && p<n+m then raise Occur
+ | VAR _ -> ()
+ | DOPN(_,cl) -> Array.iter (occur_rec n) cl
+ | DOP1(_,c) -> occur_rec n c
+ | DOP2(_,c1,c2) -> occur_rec n c1; occur_rec n c2
+ | DLAM(_,c) -> occur_rec (n+1) c
+ | DLAMV(_,v) -> Array.iter (occur_rec (n+1)) v
+ | CLam (_,t,c) -> occur_rec n t; occur_rec (n+1) c
+ | CPrd (_,t,c) -> occur_rec n t; occur_rec (n+1) c
+ | CLet (_,b,t,c) -> occur_rec n b; occur_rec n t; occur_rec (n+1) c
+ | _ -> ()
+ in
+ try occur_rec n term; true with Occur -> false
+
+(* Checking function for terms containing existential variables.
+ The function [noccur_with_meta] considers the fact that
+ each existential variable (as well as each isevar)
+ in the term appears applied to its local context,
+ which may contain the CoFix variables. These occurrences of CoFix variables
+ are not considered *)
+
+let noccur_with_meta n m term =
+ let rec occur_rec n = function
+ | Rel p -> if n<=p & p<n+m then raise Occur
+ | VAR _ -> ()
+ | DOPN(AppL,cl) ->
+ (match cl.(0) with
+ | DOP2 (Cast,DOP0 (Meta _),_) -> ()
+ | DOP0 (Meta _) -> ()
+ | _ -> Array.iter (occur_rec n) cl)
+ | DOPN(Evar _, _) -> ()
+ | DOPN(op,cl) -> Array.iter (occur_rec n) cl
+ | DOP0(_) -> ()
+ | DOP1(_,c) -> occur_rec n c
+ | DOP2(_,c1,c2) -> occur_rec n c1; occur_rec n c2
+ | DLAM(_,c) -> occur_rec (n+1) c
+ | DLAMV(_,v) -> Array.iter (occur_rec (n+1)) v
+ | CLam (_,t,c) -> occur_rec n t; occur_rec (n+1) c
+ | CPrd (_,t,c) -> occur_rec n t; occur_rec (n+1) c
+ | CLet (_,b,t,c) -> occur_rec n b; occur_rec n t; occur_rec (n+1) c
+ in
+ try (occur_rec n term; true) with Occur -> false
+
+
+(*********************)
+(* Lifting *)
+(*********************)
+
+(* Explicit lifts and basic operations *)
+type lift_spec =
+ | ELID
+ | ELSHFT of lift_spec * int (* ELSHFT(l,n) == lift of n, then apply lift l *)
+ | ELLFT of int * lift_spec (* ELLFT(n,l) == apply l to de Bruijn > n *)
+ (* i.e under n binders *)
+
+(* compose a relocation of magnitude n *)
+let rec el_shft n = function
+ | ELSHFT(el,k) -> el_shft (k+n) el
+ | el -> if n = 0 then el else ELSHFT(el,n)
+
+
+(* cross n binders *)
+let rec el_liftn n = function
+ | ELID -> ELID
+ | ELLFT(k,el) -> el_liftn (n+k) el
+ | el -> if n=0 then el else ELLFT(n, el)
+
+let el_lift el = el_liftn 1 el
+
+(* relocation of de Bruijn n in an explicit lift *)
+let rec reloc_rel n = function
+ | ELID -> n
+ | ELLFT(k,el) ->
+ if n <= k then n else (reloc_rel (n-k) el) + k
+ | ELSHFT(el,k) -> (reloc_rel (n+k) el)
+
+
+(* The generic lifting function *)
+let rec exliftn el = function
+ | Rel i -> Rel(reloc_rel i el)
+ | DOPN(oper,cl) -> DOPN(oper, Array.map (exliftn el) cl)
+ | DOP1(oper,c) -> DOP1(oper, exliftn el c)
+ | DOP2(oper,c1,c2) -> DOP2(oper, exliftn el c1, exliftn el c2)
+ | DLAM(na,c) -> DLAM(na, exliftn (el_lift el) c)
+ | DLAMV(na,v) -> DLAMV(na, Array.map (exliftn (el_lift el)) v)
+ | CLam (n,t,c) -> CLam (n, exliftn el t, exliftn (el_lift el) c)
+ | CPrd (n,t,c) -> CPrd (n, exliftn el t, exliftn (el_lift el) c)
+ | CLet (n,b,t,c) -> CLet (n,exliftn el b,exliftn el t,exliftn (el_lift el) c)
+ | x -> x
+
+(* Lifting the binding depth across k bindings *)
+
+let liftn k n =
+ match el_liftn (pred n) (el_shft k ELID) with
+ | ELID -> (fun c -> c)
+ | el -> exliftn el
+
+let lift k = liftn k 1
+
+let pop t = lift (-1) t
+
+let lift_context n l =
+ let k = List.length l in
+ list_map_i (fun i (name,c) -> (name,liftn n (k-i) c)) 0 l
+
+(*********************)
+(* Substituting *)
+(*********************)
+
+(* (subst1 M c) substitutes M for Rel(1) in c
+ we generalise it to (substl [M1,...,Mn] c) which substitutes in parallel
+ M1,...,Mn for respectively Rel(1),...,Rel(n) in c *)
+
+(* 1st : general case *)
+
+type info = Closed | Open | Unknown
+type 'a substituend = { mutable sinfo: info; sit: 'a }
+
+let rec lift_substituend depth s =
+ match s.sinfo with
+ | Closed -> s.sit
+ | Open -> lift depth s.sit
+ | Unknown ->
+ s.sinfo <- if closed0 s.sit then Closed else Open;
+ lift_substituend depth s
+
+let make_substituend c = { sinfo=Unknown; sit=c }
+
+let substn_many lamv n =
+ let lv = Array.length lamv in
+ let rec substrec depth = function
+ | Rel k as x ->
+ if k<=depth then
+ x
+ else if k-depth <= lv then
+ lift_substituend depth lamv.(k-depth-1)
+ else
+ Rel (k-lv)
+ | VAR id -> VAR id
+ | DOPN(oper,cl) -> DOPN(oper,Array.map (substrec depth) cl)
+ | DOP1(oper,c) -> DOP1(oper,substrec depth c)
+ | DOP2(oper,c1,c2) -> DOP2(oper,substrec depth c1,substrec depth c2)
+ | DLAM(na,c) -> DLAM(na,substrec (depth+1) c)
+ | DLAMV(na,v) -> DLAMV(na,Array.map (substrec (depth+1)) v)
+ | CLam (n,t,c) -> CLam (n, substrec depth t, substrec (depth+1) c)
+ | CPrd (n,t,c) -> CPrd (n, substrec depth t, substrec (depth+1) c)
+ | CLet (n,b,t,c) -> CLet (n, substrec depth b, substrec depth t,
+ substrec (depth+1) c)
+ | x -> x
+ in
+ substrec n
+
+let substnl laml k =
+ substn_many (Array.map make_substituend (Array.of_list laml)) k
+let substl laml =
+ substn_many (Array.map make_substituend (Array.of_list laml)) 0
+let subst1 lam = substl [lam]
+
+(* (thin_val sigma) removes identity substitutions from sigma *)
+
+let rec thin_val = function
+ | [] -> []
+ | (((id,{sit=VAR id'}) as s)::tl) ->
+ if id = id' then thin_val tl else s::(thin_val tl)
+ | h::tl -> h::(thin_val tl)
+
+(* (replace_vars sigma M) applies substitution sigma to term M *)
+let replace_vars var_alist =
+ let var_alist =
+ List.map (fun (str,c) -> (str,make_substituend c)) var_alist in
+ let var_alist = thin_val var_alist in
+ let rec substrec n = function
+ | (VAR(x) as c) ->
+ (try lift_substituend n (List.assoc x var_alist)
+ with Not_found -> c)
+
+ | DOPN(oper,cl) -> DOPN(oper,Array.map (substrec n) cl)
+ | DOP1(oper,c) -> DOP1(oper,substrec n c)
+ | DOP2(oper,c1,c2) -> DOP2(oper,substrec n c1,substrec n c2)
+ | DLAM(na,c) -> DLAM(na,substrec (n+1) c)
+ | DLAMV(na,v) -> DLAMV(na,Array.map (substrec (n+1)) v)
+ | CLam (na,t,c) -> CLam (na, substrec n t, substrec (n+1) c)
+ | CPrd (na,t,c) -> CPrd (na, substrec n t, substrec (n+1) c)
+ | CLet (na,b,t,c) -> CLet (na,substrec n b,substrec n t,substrec (n+1) c)
+ | x -> x
+ in
+ if var_alist = [] then (function x -> x) else substrec 0
+
+(* (subst_var str t) substitute (VAR str) by (Rel 1) in t *)
+let subst_var str = replace_vars [(str, Rel 1)]
+
+(* (subst_vars [id1;...;idn] t) substitute (VAR idj) by (Rel j) in t *)
+let subst_vars vars =
+ let _,subst =
+ List.fold_left (fun (n,l) var -> ((n+1),(var,Rel n)::l)) (1,[]) vars
+ in replace_vars (List.rev subst)
+
+(*********************)
(* Term constructors *)
(*********************)
(* Constructs a DeBrujin index with number n *)
let mkRel n = (Rel n)
-(* Constructs an existential variable named "?" *)
-let mkExistential = (DOP0 (XTRA "ISEVAR"))
-
(* Constructs an existential variable named "?n" *)
let mkMeta n = DOP0 (Meta n)
@@ -155,30 +439,30 @@ let mkImplicit = DOP0 (Sort implicit_sort)
(* Constructs the term t1::t2, i.e. the term t1 casted with the type t2 *)
(* (that means t2 is declared as the type of t1) *)
-let mkCast t1 t2 =
+let mkCast (t1,t2) =
match t1 with
| DOP2(Cast,t,_) -> DOP2(Cast,t,t2)
| _ -> (DOP2 (Cast,t1,t2))
(* Constructs the product (x:t1)t2 *)
-let mkProd x t1 t2 = (DOP2 (Prod,t1,(DLAM (x,t2))))
-let mkNamedProd id typ c = mkProd (Name id) typ (subst_var id c)
-let mkProd_string s t c = mkProd (Name (id_of_string s)) t c
+let mkProd (x,t1,t2) = CPrd (x,t1,t2)
+let mkNamedProd id typ c = mkProd (Name id, typ, subst_var id c)
+let mkProd_string s t c = mkProd (Name (id_of_string s), t, c)
(* Constructs the abstraction [x:t1]t2 *)
-let mkLambda x t1 t2 = (DOP2 (Lambda,t1,(DLAM (x,t2))))
-let mkNamedLambda id typ c = mkLambda (Name id) typ (subst_var id c)
-let mkLambda_string s t c = mkLambda (Name (id_of_string s)) t c
+let mkLambda (x,t1,t2) = CLam (x,t1,t2)
+let mkNamedLambda id typ c = mkLambda (Name id, typ, subst_var id c)
+let mkLambda_string s t c = mkLambda (Name (id_of_string s), t, c)
(* Constructs [x=c_1:t]c_2 *)
-let mkLetIn x c1 t c2 = failwith "TODO"
-let mkNamedLetIn id c1 t c2 = mkLetIn (Name id) c1 t (subst_var id c2)
+let mkLetIn (x,c1,t,c2) = CLet (x,c1,t,c2)
+let mkNamedLetIn id c1 t c2 = mkLetIn (Name id, c1, t, subst_var id c2)
(* Constructs either [(x:t)c] or [[x=b:t]c] *)
let mkProd_or_LetIn (na,body,t) c =
match body with
- | None -> mkProd na t c
- | Some b -> mkLetIn na b t c
+ | None -> mkProd (na, t, c)
+ | Some b -> mkLetIn (na, b, t, c)
let mkNamedProd_or_LetIn (id,body,t) c =
match body with
@@ -188,8 +472,8 @@ let mkNamedProd_or_LetIn (id,body,t) c =
(* Constructs either [[x:t]c] or [[x=b:t]c] *)
let mkLambda_or_LetIn (na,body,t) c =
match body with
- | None -> mkLambda na t c
- | Some b -> mkLetIn na b t c
+ | None -> mkLambda (na, t, c)
+ | Some b -> mkLetIn (na, b, t, c)
let mkNamedLambda_or_LetIn (id,body,t) c =
match body with
@@ -199,7 +483,7 @@ let mkNamedLambda_or_LetIn (id,body,t) c =
(* Constructs either [(x:t)c] or [c] where [x] is replaced by [b] *)
let mkProd_wo_LetIn (na,body,t) c =
match body with
- | None -> mkProd na (body_of_type t) c
+ | None -> mkProd (na, body_of_type t, c)
| Some b -> subst1 b c
let mkNamedProd_wo_LetIn (id,body,t) c =
@@ -208,7 +492,7 @@ let mkNamedProd_wo_LetIn (id,body,t) c =
| Some b -> subst1 b (subst_var id c)
(* non-dependent product t1 -> t2 *)
-let mkArrow t1 t2 = mkProd Anonymous t1 t2
+let mkArrow t1 t2 = mkProd (Anonymous, t1, t2)
(* If lt = [t1; ...; tn], constructs the application (t1 ... tn) *)
let mkAppL a = DOPN (AppL, a)
@@ -234,7 +518,7 @@ let mkMutInd (ind_sp,l) = DOPN (MutInd ind_sp, l)
let mkMutConstruct (cstr_sp,l) = DOPN (MutConstruct cstr_sp,l)
(* Constructs the term <p>Case c of c1 | c2 .. | cn end *)
-let mkMutCase ci p c ac =
+let mkMutCase (ci, p, c, ac) =
DOPN (MutCase ci, Array.append [|p;c|] (Array.of_list ac))
let mkMutCaseA ci p c ac =
DOPN (MutCase ci, Array.append [|p;c|] ac)
@@ -316,7 +600,6 @@ let destMeta = function
| (DOP0 (Meta n)) -> n
| _ -> invalid_arg "destMeta"
-let isMETA = function DOP0(Meta _) -> true | _ -> false
(* Destructs a variable *)
let destVar = function
@@ -416,9 +699,12 @@ let rec strip_all_casts t =
| DOP1(oper,c) -> DOP1(oper,strip_all_casts c)
| DOP2(oper,c1,c2) -> DOP2(oper,strip_all_casts c1,strip_all_casts c2)
| DOPN(oper,cl) -> DOPN(oper,Array.map strip_all_casts cl)
- | DOPL(oper,cl) -> DOPL(oper,List.map strip_all_casts cl)
| DLAM(na,c) -> DLAM(na,strip_all_casts c)
| DLAMV(na,c) -> DLAMV(na,Array.map (under_outer_cast strip_all_casts) c)
+ | CLam (n,t,c) -> CLam (n, strip_all_casts t, strip_all_casts c)
+ | CPrd (n,t,c) -> CPrd (n, strip_all_casts t, strip_all_casts c)
+ | CLet (n,b,t,c) -> CLet (n, strip_all_casts b, strip_all_casts t,
+ strip_all_casts c)
| VAR _ as t -> t
| Rel _ as t -> t
@@ -430,13 +716,13 @@ let isVar = function VAR _ -> true | _ -> false
(* Destructs the product (x:t1)t2 *)
let destProd = function
- | DOP2 (Prod, t1, (DLAM (x,t2))) -> (x,t1,t2)
+ | CPrd (x,t1,t2) -> (x,t1,t2)
| _ -> invalid_arg "destProd"
let rec hd_of_prod prod =
match strip_outer_cast prod with
- | DOP2(Prod,c,DLAM(n,t')) -> hd_of_prod t'
- | t -> t
+ | CPrd (n,c,t') -> hd_of_prod t'
+ | t -> t
let hd_is_constructor t =
let is_constructor = function
@@ -449,9 +735,14 @@ let hd_is_constructor t =
(* Destructs the abstraction [x:t1]t2 *)
let destLambda = function
- | DOP2 (Lambda, t1, (DLAM (x,t2))) -> (x,t1,t2)
+ | CLam (x,t1,t2) -> (x,t1,t2)
| _ -> invalid_arg "destLambda"
+(* Destructs the let [x:=b:t1]t2 *)
+let destLetIn = function
+ | CLet (x,b,t1,t2) -> (x,b,t1,t2)
+ | _ -> invalid_arg "destProd"
+
(* Destructs an application *)
let destAppL = function
| (DOPN (AppL,a)) -> a
@@ -461,8 +752,6 @@ let destApplication = function
| (DOPN (AppL,a)) when Array.length a <> 0 -> (a.(0), array_tl a)
| _ -> invalid_arg "destApplication"
-let isAppL = function DOPN(AppL,_) -> true | _ -> false
-
let args_app = function
| DOPN(AppL,cl) -> if Array.length cl >1 then array_tl cl else [||]
| c -> [||]
@@ -573,9 +862,9 @@ let destCoFix = function
(**********************************************************************)
-type binder_kind = BProd | BLambda
+type binder_kind = BProd | BLambda | BLetIn
-type fix_kind = RFix of (int array * int) | RCofix of int
+type fix_kind = RFix of (int array * int) | RCoFix of int
type 'ctxt reference =
| RConst of section_path * 'ctxt
@@ -596,6 +885,12 @@ type cofixpoint = int * (constr array * name list * constr array)
(* Term analysis *)
(******************)
+type hnftype =
+ | HnfSort of sorts
+ | HnfProd of name * constr * constr
+ | HnfAtom of constr
+ | HnfMutInd of inductive * constr array
+
type kindOfTerm =
| IsRel of int
| IsMeta of int
@@ -605,6 +900,7 @@ type kindOfTerm =
| IsCast of constr * constr
| IsProd of name * constr * constr
| IsLambda of name * constr * constr
+ | IsLetIn of name * constr * constr * constr
| IsAppL of constr * constr list
| IsAbst of section_path * constr array
| IsEvar of existential
@@ -629,8 +925,9 @@ let kind_of_term c =
| DOP0 (Sort s) -> IsSort s
| DOP0 (XTRA s) -> IsXtra s
| DOP2 (Cast, t1, t2) -> IsCast (t1,t2)
- | DOP2 (Prod, t1, (DLAM (x,t2))) -> IsProd (x,t1,t2)
- | DOP2 (Lambda, t1, (DLAM (x,t2))) -> IsLambda (x,t1,t2)
+ | CPrd (x,t1,t2) -> IsProd (x,t1,t2)
+ | CLam (x,t1,t2) -> IsLambda (x,t1,t2)
+ | CLet (x,b,t1,t2) -> IsLetIn (x,b,t1,t2)
| DOPN (AppL,a) when Array.length a <> 0 ->
IsAppL (a.(0), List.tl (Array.to_list a))
| DOPN (Const sp, a) -> IsConst (sp,a)
@@ -648,26 +945,31 @@ let kind_of_term c =
IsCoFix (i,typedbodies)
| _ -> errorlabstrm "Term.kind_of_term" [< 'sTR "ill-formed constr" >]
+let isMeta = function DOP0(Meta _) -> true | _ -> false
+let isConst = function DOPN(Const _,_) -> true | _ -> false
+let isMutConstruct = function DOPN(MutCase _,_) -> true | _ -> false
+let isAppL = function DOPN(AppL,_) -> true | _ -> false
+
(***************************)
(* Other term constructors *)
(***************************)
-let abs_implicit c = mkLambda Anonymous mkImplicit c
-let lambda_implicit a = mkLambda (Name(id_of_string"y")) mkImplicit a
+let abs_implicit c = mkLambda (Anonymous, mkImplicit, c)
+let lambda_implicit a = mkLambda (Name(id_of_string"y"), mkImplicit, a)
let lambda_implicit_lift n a = iterate lambda_implicit n (lift n a)
(* prod_it b [xn:Tn;..;x1:T1] = (x1:T1)..(xn:Tn)b *)
-let prod_it = List.fold_left (fun c (n,t) -> mkProd n t c)
+let prod_it = List.fold_left (fun c (n,t) -> mkProd (n, t, c))
(* lam_it b [xn:Tn;..;x1:T1] = [x1:T1]..[xn:Tn]b *)
-let lam_it = List.fold_left (fun c (n,t) -> mkLambda n t c)
+let lam_it = List.fold_left (fun c (n,t) -> mkLambda (n, t, c))
(* prodn n [xn:Tn;..;x1:T1;Gamma] b = (x1:T1)..(xn:Tn)b *)
let prodn n env b =
let rec prodrec = function
| (0, env, b) -> b
- | (n, ((v,t)::l), b) -> prodrec (n-1, l, DOP2(Prod,t,DLAM(v,b)))
+ | (n, ((v,t)::l), b) -> prodrec (n-1, l, CPrd (v,t,b))
| _ -> assert false
in
prodrec (n,env,b)
@@ -676,7 +978,7 @@ let prodn n env b =
let lamn n env b =
let rec lamrec = function
| (0, env, b) -> b
- | (n, ((v,t)::l), b) -> lamrec (n-1, l, DOP2(Lambda,t,DLAM(v,b)))
+ | (n, ((v,t)::l), b) -> lamrec (n-1, l, CLam (v,t,b))
| _ -> assert false
in
lamrec (n,env,b)
@@ -712,8 +1014,7 @@ let rec to_lambda n prod =
prod
else
match prod with
- | DOP2(Prod,ty,DLAM(na,bd)) ->
- DOP2(Lambda,ty,DLAM(na, to_lambda (n-1) bd))
+ | CPrd(na,ty,bd) -> CLam(na,ty,to_lambda (n-1) bd)
| DOP2(Cast,c,_) -> to_lambda n c
| _ -> errorlabstrm "to_lambda" [<>]
@@ -722,8 +1023,7 @@ let rec to_prod n lam =
lam
else
match lam with
- | DOP2(Lambda,ty,DLAM(na,bd)) ->
- DOP2(Prod,ty,DLAM(na, to_prod (n-1) bd))
+ | CLam(na,ty,bd) -> CPrd(na,ty,to_prod (n-1) bd)
| DOP2(Cast,c,_) -> to_prod n c
| _ -> errorlabstrm "to_prod" [<>]
@@ -733,7 +1033,7 @@ let rec to_prod n lam =
let prod_app t n =
match strip_outer_cast t with
- | DOP2(Prod,_,DLAM(na,b)) -> subst1 n b
+ | CPrd (_,_,b) -> subst1 n b
| _ ->
errorlabstrm "prod_app"
[< 'sTR"Needed a product, but didn't find one" ; 'fNL >]
@@ -753,27 +1053,29 @@ let prod_applist t nL = List.fold_left prod_app t nL
(* Transforms a product term (x1:T1)..(xn:Tn)T into the pair
([(xn,Tn);...;(x1,T1)],T), where T is not a product *)
let destArity =
- let rec prodec_rec l = function
- | DOP2(Prod,t,DLAM(x,c)) -> prodec_rec ((x,t)::l) c
- | DOP2(Cast,c,_) -> prodec_rec l c
- | DOP0(Sort s) -> l,s
- | _ -> anomaly "decompose_arity: not an arity"
+ let rec prodec_rec l c =
+ match kind_of_term c with
+ | IsProd (x,t,c) -> prodec_rec ((x,t)::l) c
+ | IsCast (c,_) -> prodec_rec l c
+ | IsSort s -> l,s
+ | _ -> anomaly "decompose_arity: not an arity"
in
prodec_rec []
-let rec isArity = function
- | DOP2(Prod,_,DLAM(_,c)) -> isArity c
- | DOP2(Cast,c,_) -> isArity c
- | DOP0(Sort _) -> true
+let rec isArity c =
+ match kind_of_term c with
+ | IsProd (_,_,c) -> isArity c
+ | IsCast (c,_) -> isArity c
+ | IsSort _ -> true
| _ -> false
(* Transforms a product term (x1:T1)..(xn:Tn)T into the pair
([(xn,Tn);...;(x1,T1)],T), where T is not a product *)
let decompose_prod =
let rec prodec_rec l = function
- | DOP2(Prod,t,DLAM(x,c)) -> prodec_rec ((x,t)::l) c
- | DOP2(Cast,c,_) -> prodec_rec l c
- | c -> l,c
+ | CPrd(x,t,c) -> prodec_rec ((x,t)::l) c
+ | DOP2(Cast,c,_) -> prodec_rec l c
+ | c -> l,c
in
prodec_rec []
@@ -781,9 +1083,9 @@ let decompose_prod =
([(xn,Tn);...;(x1,T1)],T), where T is not a lambda *)
let decompose_lam =
let rec lamdec_rec l = function
- | DOP2(Lambda,t,DLAM(x,c)) -> lamdec_rec ((x,t)::l) c
- | DOP2(Cast,c,_) -> lamdec_rec l c
- | c -> l,c
+ | CLam (x,t,c) -> lamdec_rec ((x,t)::l) c
+ | DOP2 (Cast,c,_) -> lamdec_rec l c
+ | c -> l,c
in
lamdec_rec []
@@ -794,8 +1096,8 @@ let decompose_prod_n n =
let rec prodec_rec l n c =
if n=0 then l,c
else match c with
- | DOP2(Prod,t,DLAM(x,c)) -> prodec_rec ((x,t)::l) (n-1) c
- | DOP2(Cast,c,_) -> prodec_rec l n c
+ | CPrd (x,t,c) -> prodec_rec ((x,t)::l) (n-1) c
+ | DOP2 (Cast,c,_) -> prodec_rec l n c
| c -> error "decompose_prod_n: not enough products"
in
prodec_rec [] n
@@ -807,8 +1109,8 @@ let decompose_lam_n n =
let rec lamdec_rec l n c =
if n=0 then l,c
else match c with
- | DOP2(Lambda,t,DLAM(x,c)) -> lamdec_rec ((x,t)::l) (n-1) c
- | DOP2(Cast,c,_) -> lamdec_rec l n c
+ | CLam (x,t,c) -> lamdec_rec ((x,t)::l) (n-1) c
+ | DOP2 (Cast,c,_) -> lamdec_rec l n c
| c -> error "decompose_lam_n: not enough abstractions"
in
lamdec_rec [] n
@@ -817,7 +1119,7 @@ let decompose_lam_n n =
* gives n (casts are ignored) *)
let nb_lam =
let rec nbrec n = function
- | DOP2(Lambda,_,DLAM(_,c)) -> nbrec (n+1) c
+ | CLam (_,_,c) -> nbrec (n+1) c
| DOP2(Cast,c,_) -> nbrec n c
| _ -> n
in
@@ -826,145 +1128,13 @@ let nb_lam =
(* similar to nb_lam, but gives the number of products instead *)
let nb_prod =
let rec nbrec n = function
- | DOP2(Prod,_,DLAM(_,c)) -> nbrec (n+1) c
+ | CPrd (_,_,c) -> nbrec (n+1) c
| DOP2(Cast,c,_) -> nbrec n c
| _ -> n
in
nbrec 0
-(* Trop compliqué...
-(********************************************************************)
-(* various utility functions for implementing terms with bindings *)
-(********************************************************************)
-
-let extract_lifted (n,x) = lift n x
-let insert_lifted x = (0,x)
-
-(* l is a list of pairs (n:nat,x:constr), env is a stack of (na:name,T:constr)
- push_and_lift adds a component to env and lifts l one step *)
-let push_and_lift (na,t) env l =
- ((na,t)::env, List.map (fun (n,x) -> (n+1,x)) l)
-
-
-(* if T is not (x1:A1)(x2:A2)....(xn:An)T' then (push_and_liftl n env T l)
- raises an error else it gives ([x1,A1 ; x2,A2 ; ... ; xn,An]@env,T',l')
- where l' is l lifted n steps *)
-let push_and_liftl n env t l =
- let rec pushrec n t (env,l) =
- match (n,t) with
- | (0, _) -> (env,t,l)
- | (_, DOP2(Prod,t,DLAM(na,b))) ->
- pushrec (n-1) b (push_and_lift (na,t) env l)
- | (_, DOP2(Cast,t,_)) -> pushrec n t (env,l)
- | _ -> error "push_and_liftl"
- in
- pushrec n t (env,l)
-
-(* if T is not (x1:A1)(x2:A2)....(xn:An)T' then (push_and_liftl n env T l)
- raises an error else it gives ([x1,A1 ; x2,A2 ; ... ; xn,An]@env,T',l')
- where l' is l lifted n steps *)
-let push_lam_and_liftl n env t l =
- let rec pushrec n t (env,l) =
- match (n,t) with
- | (0, _) -> (env,t,l)
- | (_, DOP2(Lambda,t,DLAM(na,b))) ->
- pushrec (n-1) b (push_and_lift (na,t) env l)
- | (_, DOP2(Cast,t,_)) -> pushrec n t (env,l)
- | _ -> error "push_lam_and_liftl"
- in
- pushrec n t (env,l)
-
-(* l is a list of pairs (n:nat,x:constr), tlenv is a stack of
-(na:name,T:constr), B : constr, na : name
-(prod_and_pop ((na,T)::tlenv) B l) gives (tlenv, (na:T)B, l')
-where l' is l lifted down one step *)
-let prod_and_pop env b l =
- match env with
- | [] -> error "prod_and_pop"
- | (na,t)::tlenv ->
- (tlenv,DOP2(Prod,t,DLAM(na,b)),
- List.map (function
- (0,x) -> (0,lift (-1) x)
- | (n,x) -> (n-1,x)) l)
-
-(* recusively applies prod_and_pop :
-if env = [na1:T1 ; na2:T2 ; ... ; nan:Tn]@tlenv
-then
-(prod_and_popl n env T l) gives (tlenv,(nan:Tn)...(na1:Ta1)T,l') where
-l' is l lifted down n steps *)
-let prod_and_popl n env t l =
- let rec poprec = function
- | (0, (env,b,l)) -> (env,b,l)
- | (n, ([],_,_)) -> error "prod_and_popl"
- | (n, (env,b,l)) -> poprec (n-1, prod_and_pop env b l)
- in
- poprec (n,(env,t,l))
-
-(* similar to prod_and_pop, but gives [na:T]B intead of (na:T)B *)
-let lam_and_pop env b l =
- match env with
- | [] -> error "lam_and_pop"
- | (na,t)::tlenv ->
- (tlenv,DOP2(Lambda,t,DLAM(na,b)),
- List.map (function
- (0,x) -> (0,lift (-1) x)
- | (n,x) -> (n-1,x)) l)
-
-(* similar to lamn_and_pop but generates new names whenever the name is
- * Anonymous *)
-let lam_and_pop_named env body l acc_ids =
- match env with
- | [] -> error "lam_and_pop"
- | (na,t)::tlenv ->
- let id = match na with
- | Anonymous -> next_ident_away (id_of_string "a") acc_ids
- | Name id -> id
- in
- (tlenv,DOP2(Lambda,t,DLAM((Name id),body)),
- List.map (function
- | (0,x) -> (0,lift (-1) x)
- | (n,x) -> (n-1,x)) l,
- (id::acc_ids))
-
-(* similar to prod_and_popl but gives [nan:Tan]...[na1:Ta1]B instead of
- * (nan:Tan)...(na1:Ta1)B *)
-let lam_and_popl n env t l =
- let rec poprec = function
- | (0, (env,b,l)) -> (env,b,l)
- | (n, ([],_,_)) -> error "lam_and_popl"
- | (n, (env,b,l)) -> poprec (n-1, lam_and_pop env b l)
- in
- poprec (n,(env,t,l))
-
-(* similar to prod_and_popl but gives [nan:Tan]...[na1:Ta1]B instead of
- * but it generates names whenever nai=Anonymous *)
-
-let lam_and_popl_named n env t l =
- let rec poprec = function
- | (0, (env,b,l,_)) -> (env,b,l)
- | (n, ([],_,_,_)) -> error "lam_and_popl"
- | (n, (env,b,l,acc_ids)) -> poprec (n-1, lam_and_pop_named env b l acc_ids)
- in
- poprec (n,(env,t,l,[]))
-
-(* [lambda_ize n T endpt]
- * will pop off the first [n] products in [T], then stick in [endpt],
- * properly lifted, and then push back the products, but as lambda-
- * abstractions *)
-let lambda_ize n t endpt =
- let env = []
- and carry = [insert_lifted endpt] in
- let env, endpt =
- match push_and_liftl n env t carry with
- | (env,_,[endpt]) -> env, endpt
- | _ -> anomaly "bud in Term.lamda_ize"
- in
- let t = extract_lifted endpt in
- match lam_and_popl n env t [] with
- | (_,t,[]) -> t
- | _ -> anomaly "bud in Term.lamda_ize"
-*)
-
+(* Misc *)
let sort_hdchar = function
| Prop(_) -> "P"
| Type(_) -> "T"
@@ -1021,17 +1191,65 @@ let rec strip_head_cast = function
| DOP2(Cast,c,t) -> strip_head_cast c
| c -> c
+(* Returns the list of global variables in a term *)
+
+let global_varsl l constr =
+ let rec filtrec acc = function
+ | VAR id -> id::acc
+ | DOP1(oper,c) -> filtrec acc c
+ | DOP2(oper,c1,c2) -> filtrec (filtrec acc c1) c2
+ | DOPN(oper,cl) -> Array.fold_left filtrec acc cl
+ | DLAM(_,c) -> filtrec acc c
+ | DLAMV(_,v) -> Array.fold_left filtrec acc v
+ | CLam (_,t,c) -> filtrec (filtrec acc t) c
+ | CPrd (_,t,c) -> filtrec (filtrec acc t) c
+ | CLet (_,b,t,c) -> filtrec (filtrec (filtrec acc b) t) c
+ | _ -> acc
+ in
+ filtrec l constr
+
+let global_vars constr = global_varsl [] constr
+
+let global_vars_set constr =
+ let rec filtrec acc = function
+ | VAR id -> Idset.add id acc
+ | DOP1(oper,c) -> filtrec acc c
+ | DOP2(oper,c1,c2) -> filtrec (filtrec acc c1) c2
+ | DOPN(oper,cl) -> Array.fold_left filtrec acc cl
+ | DLAM(_,c) -> filtrec acc c
+ | DLAMV(_,v) -> Array.fold_left filtrec acc v
+ | CLam (_,t,c) -> filtrec (filtrec acc t) c
+ | CPrd (_,t,c) -> filtrec (filtrec acc t) c
+ | CLet (_,b,t,c) -> filtrec (filtrec (filtrec acc b) t) c
+ | _ -> acc
+ in
+ filtrec Idset.empty constr
+
+(* [Rel (n+m);...;Rel(n+1)] *)
+
+let rel_vect n m = Array.init m (fun i -> Rel(n+m-i))
+
+let rel_list n m =
+ let rec reln l p =
+ if p>m then l else reln (Rel(n+p)::l) (p+1)
+ in
+ reln [] 1
+
+(* Rem: end of import from old module Generic *)
+
(* Various occurs checks *)
let occur_opern s =
let rec occur_rec = function
| DOPN(oper,cl) -> s=oper or (array_exists occur_rec cl)
- | DOPL(oper,cl) -> s=oper or (List.exists occur_rec cl)
| VAR _ -> false
| DOP1(_,c) -> occur_rec c
| DOP2(_,c1,c2) -> (occur_rec c1) or (occur_rec c2)
| DLAM(_,c) -> occur_rec c
| DLAMV(_,v) -> array_exists occur_rec v
+ | CLam (_,t,c) -> occur_rec t or occur_rec c
+ | CPrd (_,t,c) -> occur_rec t or occur_rec c
+ | CLet (_,b,t,c) -> occur_rec b or occur_rec t or occur_rec c
| _ -> false
in
occur_rec
@@ -1044,12 +1262,14 @@ let occur_evar ev = occur_opern (Evar ev)
let occur_var s =
let rec occur_rec = function
| DOPN(_,cl) -> array_exists occur_rec cl
- | DOPL(_,cl) -> List.exists occur_rec cl
| VAR id -> s=id
| DOP1(_,c) -> occur_rec c
| DOP2(_,c1,c2) -> (occur_rec c1) or (occur_rec c2)
| DLAM(_,c) -> occur_rec c
| DLAMV(_,v) -> array_exists occur_rec v
+ | CLam (_,t,c) -> occur_rec t or occur_rec c
+ | CPrd (_,t,c) -> occur_rec t or occur_rec c
+ | CLet (_,b,t,c) -> occur_rec b or occur_rec t or occur_rec c
| _ -> false
in
occur_rec
@@ -1068,7 +1288,6 @@ let occur_var s =
- if no (sp,_) appears in sigma, then sp is not unfolded.
- NOTE : the case of DOPL is not handled...
*)
let replace_consts const_alist =
let rec substrec = function
@@ -1090,11 +1309,13 @@ let replace_consts const_alist =
| DOP2(oper,c1,c2) -> DOP2(oper,substrec c1,substrec c2)
| DLAM(na,c) -> DLAM(na,substrec c)
| DLAMV(na,v) -> DLAMV(na,Array.map substrec v)
+ | CLam (na,t,c) -> CLam (na, substrec t, substrec c)
+ | CPrd (na,t,c) -> CPrd (na, substrec t, substrec c)
+ | CLet (na,b,t,c) -> CLet (na, substrec b, substrec t, substrec c)
| x -> x
in
if const_alist = [] then function x -> x else substrec
-(* NOTE : the case of DOPL is not handled by whd_castapp_stack *)
let whd_castapp_stack =
let rec whrec x stack = match x with
| DOPN(AppL,cl) -> whrec (array_hd cl) (array_app_tl cl stack)
@@ -1129,41 +1350,31 @@ let rec eq_constr_rec m n =
| (DLAM(_,c1),DLAM(_,c2)) -> eq_constr_rec c1 c2
| (DLAMV(_,cl1),DLAMV(_,cl2)) ->
array_for_all2 eq_constr_rec cl1 cl2
+ | CLam(_,t1,c1), CLam(_,t2,c2) -> eq_constr_rec t1 t2 & eq_constr_rec c1 c2
+ | CPrd(_,t1,c1), CPrd(_,t2,c2) -> eq_constr_rec t1 t2 & eq_constr_rec c1 c2
+ | CLet(_,b1,t1,c1), CLet (_,b2,t2,c2) ->
+ eq_constr_rec b1 b2 & eq_constr_rec t1 t2 & eq_constr_rec c1 c2
| _ -> false
let eq_constr = eq_constr_rec
-let rec eq_constr_with_meta_rec m n=
- (m == n) or
- (m=n) or
- (match (strip_head_cast m,strip_head_cast n) with
- | (Rel p1,Rel p2) -> p1=p2
- | (DOPN(oper1,cl1),DOPN(oper2,cl2)) ->
- oper1=oper2 & array_for_all2 eq_constr_rec cl1 cl2
- | (DOP0 oper1,DOP0 oper2) -> oper1=oper2
- | (DOP1(i,c1),DOP1(j,c2)) -> (i=j) & eq_constr_rec c1 c2
- | (DOP2(i,c1,c1'),DOP2(j,c2,c2')) ->
- (i=j) & eq_constr_rec c1 c2 & eq_constr_rec c1' c2'
- | (DLAM(_,c1),DLAM(_,c2)) -> eq_constr_rec c1 c2
- | (DLAMV(_,cl1),DLAMV(_,cl2)) ->
- array_for_all2 eq_constr_rec cl1 cl2
- | _ -> false)
-
(* (dependent M N) is true iff M is eq_term with a subterm of N
M is appropriately lifted through abstractions of N *)
let dependent =
let rec deprec m t =
- (eq_constr m t)
- or (match t with
- | VAR _ -> false
- | DOP1(_,c) -> deprec m c
- | DOP2(_,c,t) -> deprec m c or deprec m t
- | DOPN(_,cl) -> array_exists (deprec m) cl
- | DOPL(_,cl) -> List.exists (deprec m) cl
- | DLAM(_,c) -> deprec (lift 1 m) c
- | DLAMV(_,v) -> array_exists (deprec (lift 1 m)) v
- | _ -> false)
+ (eq_constr m t) or
+ (match t with
+ | VAR _ -> false
+ | DOP1(_,c) -> deprec m c
+ | DOP2(_,c,t) -> deprec m c or deprec m t
+ | DOPN(_,cl) -> array_exists (deprec m) cl
+ | DLAM(_,c) -> deprec (lift 1 m) c
+ | DLAMV(_,v) -> array_exists (deprec (lift 1 m)) v
+ | CLam (_,t,c) -> deprec m t or deprec (lift 1 m) c
+ | CPrd (_,t,c) -> deprec m t or deprec (lift 1 m) c
+ | CLet (_,b,t,c) -> deprec m b or deprec m t or deprec (lift 1 m) c
+ | _ -> false)
in
deprec
@@ -1173,7 +1384,7 @@ let dependent =
let rec eta_reduce_head c =
match c with
- | DOP2(Lambda,c1,DLAM(_,c')) ->
+ | CLam (_,c1,c') ->
(match eta_reduce_head c' with
| DOPN(AppL,cl) ->
let lastn = (Array.length cl) - 1 in
@@ -1185,7 +1396,7 @@ let rec eta_reduce_head c =
if lastn = 1 then cl.(0)
else DOPN(AppL,Array.sub cl 0 lastn)
in
- if (not ((dependent (Rel 1) c')))
+ if (not ((dependent (mkRel 1) c')))
then lift (-1) c'
else c
| _ -> c)
@@ -1194,40 +1405,43 @@ let rec eta_reduce_head c =
(* alpha-eta conversion : ignore print names and casts *)
-let rec eta_eq_constr t1 t2 =
- let t1 = eta_reduce_head (strip_head_cast t1)
- and t2 = eta_reduce_head (strip_head_cast t2) in
- t1=t2 or match (t1,t2) with
- | (DOP2(Cast,c1,_),c2) -> eta_eq_constr c1 c2
- | (c1,DOP2(Cast,c2,_)) -> eta_eq_constr c1 c2
+let eta_eq_constr =
+ let rec aux t1 t2 =
+ let t1 = eta_reduce_head (strip_head_cast t1)
+ and t2 = eta_reduce_head (strip_head_cast t2) in
+ t1=t2 or match (t1,t2) with
+ | (DOP2(Cast,c1,_),c2) -> aux c1 c2
+ | (c1,DOP2(Cast,c2,_)) -> aux c1 c2
| (Rel p1,Rel p2) -> p1=p2
- | (DOPN(oper1,cl1),DOPN(oper2,cl2)) ->
- oper1=oper2 & array_for_all2 eta_eq_constr cl1 cl2
- | (DOP0 oper1,DOP0 oper2) -> oper1=oper2
- | (DOP1(i,c1),DOP1(j,c2)) -> (i=j) & eta_eq_constr c1 c2
- | (DOP2(i,c1,c1'),DOP2(j,c2,c2')) ->
- (i=j) & eta_eq_constr c1 c2 & eta_eq_constr c1' c2'
- | (DLAM(_,c1),DLAM(_,c2)) -> eta_eq_constr c1 c2
- | (DLAMV(_,cl1),DLAMV(_,cl2)) -> array_for_all2 eta_eq_constr cl1 cl2
+ | (DOPN(op1,cl1),DOPN(op2,cl2)) -> op1=op2 & array_for_all2 aux cl1 cl2
+ | (DOP0 oper1,DOP0 oper2) -> oper1=oper2
+ | (DOP1(i,c1),DOP1(j,c2)) -> (i=j) & aux c1 c2
+ | (DOP2(i,c1,c1'),DOP2(j,c2,c2')) -> (i=j) & aux c1 c2 & aux c1' c2'
+ | (DLAM(_,c1),DLAM(_,c2)) -> aux c1 c2
+ | (DLAMV(_,cl1),DLAMV(_,cl2)) -> array_for_all2 aux cl1 cl2
+ | CLam(_,t1,c1), CLam(_,t2,c2) -> aux t1 t2 & aux c1 c2
+ | CPrd(_,t1,c1), CPrd(_,t2,c2) -> aux t1 t2 & aux c1 c2
+ | CLet(_,b1,t1,c1), CLet (_,b2,t2,c2) -> aux b1 b2 & aux t1 t2 & aux c1 c2
| _ -> false
+ in aux
-(* This renames bound variablew with fresh and distinct names *)
+(* This renames bound variables with fresh and distinct names *)
(* in such a way that the printer doe not generate new names *)
(* and therefore that printed names are the intern names *)
(* In this way, tactics such as Induction works well *)
-let rec rename_bound_var l = function
- | DOP2(Prod,c1,DLAM(Name(s),c2)) ->
- if dependent (Rel 1) c2 then
+let rec rename_bound_var l c =
+ match kind_of_term c with
+ | IsProd (Name s,c1,c2) ->
+ if dependent (mkRel 1) c2 then
let s' = next_ident_away s (global_vars c2@l) in
- DOP2(Prod,c1,DLAM(Name(s'),rename_bound_var (s'::l) c2))
+ mkProd (Name s', c1, rename_bound_var (s'::l) c2)
else
- DOP2(Prod,c1,DLAM(Name(s),rename_bound_var l c2))
- | DOP2(Prod,c1,DLAM(Anonymous,c2)) ->
- DOP2(Prod,c1,DLAM(Anonymous,rename_bound_var l c2))
- | DOP2(Cast,c,t) -> DOP2(Cast,rename_bound_var l c,t)
- | x -> x
+ mkProd (Name s, c1, rename_bound_var l c2)
+ | IsProd (Anonymous,c1,c2) -> mkProd (Anonymous, c1, rename_bound_var l c2)
+ | IsCast (c,t) -> mkCast (rename_bound_var l c, t)
+ | x -> c
(***************************)
(* substitution functions *)
@@ -1269,47 +1483,38 @@ let sort_increasing_snd =
[subst_term c t] substitutes [(Rel 1)] for all occurrences of (closed)
term [c] in a term [t] *)
-let subst_term c t =
+let subst_term_gen eq_fun c t =
let rec substrec k c t =
match prefix_application k c t with
| Some x -> x
| None ->
- (if eq_constr t c then Rel(k) else match t with
- | DOPN(Const sp,cl) -> t
- | DOPN(MutInd (x_0,x_1),cl) -> t
- | DOPN(MutConstruct (x_0,x_1),cl) -> t
- | DOPN(oper,tl) -> DOPN(oper,Array.map (substrec k c) tl)
- | DOP1(i,t) -> DOP1(i,substrec k c t)
- | DOP2(oper,c1,c2) -> DOP2(oper,substrec k c c1,substrec k c c2)
- | DLAM(na,t) -> DLAM(na,substrec (k+1) (lift 1 c) t)
- | DLAMV(na,v) -> DLAMV(na,Array.map (substrec (k+1) (lift 1 c)) v)
- | _ -> t)
+ (if eq_fun t c then Rel(k) else match t with
+ | DOPN(Const sp,cl) -> t
+ | DOPN(MutInd (x_0,x_1),cl) -> t
+ | DOPN(MutConstruct (x_0,x_1),cl) -> t
+ | DOPN(oper,tl) -> DOPN(oper,Array.map (substrec k c) tl)
+ | DOP1(i,t) -> DOP1(i,substrec k c t)
+ | DOP2(oper,c1,c2) -> DOP2(oper,substrec k c c1,substrec k c c2)
+ | DLAM(na,t) -> DLAM(na,substrec (k+1) (lift 1 c) t)
+ | DLAMV(na,v) -> DLAMV(na,Array.map (substrec (k+1) (lift 1 c)) v)
+ | CLam(na,t,c2) -> CLam(na,substrec k c t,substrec (k+1) (lift 1 c) c2)
+ | CPrd(na,t,c2) -> CPrd(na,substrec k c t,substrec (k+1) (lift 1 c) c2)
+ | CLet(na,b,t,c2) -> CLet(na,substrec k c b,substrec k c t,
+ substrec (k+1) (lift 1 c) c2)
+ | _ -> t)
in
substrec 1 c t
-(* same as subst_term, but modulo eta *)
-
-let subst_term_eta_eq c t =
- let rec substrec k c t =
- match prefix_application_eta k c t with
- | Some x -> x
- | None ->
- (if eta_eq_constr t c then Rel(k) else match t with
- | DOPN(Const sp,cl) -> t
- | DOPN(oper,tl) -> DOPN(oper,Array.map (substrec k c) tl)
- | DOP1(i,t) -> DOP1(i,substrec k c t)
- | DOP2(oper,c1,c2) -> DOP2(oper,substrec k c c1,substrec k c c2)
- | DLAM(na,t) -> DLAM(na,substrec (k+1) (lift 1 c) t)
- | DLAMV(na,v)-> DLAMV(na,Array.map (substrec (k+1) (lift 1 c)) v)
- | _ -> t)
- in
- substrec 1 c t
+let subst_term = subst_term_gen eq_constr
+let subst_term_eta = subst_term_gen eta_eq_constr
(* bl : (int,constr) Listmap.t = (int * constr) list *)
(* c : constr *)
(* for each binding (i,c_i) in bl, substitutes the metavar i by c_i in c *)
(* Raises Not_found if c contains a meta that is not in the association list *)
+(* Bogué ? Pourquoi pas de lift en passant sous un lieur ?? *)
+(* Et puis meta doit fusionner avec Evar *)
let rec subst_meta bl c =
match c with
| DOP0(Meta(i)) -> List.assoc i bl
@@ -1317,6 +1522,10 @@ let rec subst_meta bl c =
| DOP2(op,c'1, c'2) -> DOP2(op, subst_meta bl c'1, subst_meta bl c'2)
| DOPN(op, c') -> DOPN(op, Array.map (subst_meta bl) c')
| DLAM(x,c') -> DLAM(x, subst_meta bl c')
+ | CLam(na,t,c) -> CLam(na,subst_meta bl t,subst_meta bl c)
+ | CPrd(na,t,c) -> CPrd(na,subst_meta bl t,subst_meta bl c)
+ | CLet(na,b,t,c) -> CLet(na,subst_meta bl b,subst_meta bl t,
+ subst_meta bl c)
| _ -> c
(* Substitute only a list of locations locs, the empty list is
@@ -1325,55 +1534,61 @@ let rec subst_meta bl c =
that will not be substituted. *)
let subst_term_occ_gen locs occ c t =
+ let pos = ref occ in
let except = List.for_all (fun n -> n<0) locs in
- let rec substcheck k occ c t =
- if except or List.exists (function u -> u>=occ) locs then
- substrec k occ c t
+ let rec substcheck k c t =
+ if except or List.exists (function u -> u >= !pos) locs then
+ substrec k c t
else
- (occ,t)
- and substrec k occ c t =
+ t
+ and substrec k c t =
if eq_constr t c then
- if except then
- if List.mem (-occ) locs then (occ+1,t) else (occ+1,Rel(k))
- else
- if List.mem occ locs then (occ+1,Rel(k)) else (occ+1,t)
- else
+ let r =
+ if except then
+ if List.mem (- !pos) locs then t else (Rel k)
+ else
+ if List.mem !pos locs then (Rel k) else t
+ in incr pos; r
+ else
match t with
- | DOPN(Const sp,tl) -> occ,t
- | DOPN(MutConstruct _,tl) -> occ,t
- | DOPN(MutInd _,tl) -> occ,t
- | DOPN(i,cl) ->
- let (occ',cl') =
- Array.fold_left
- (fun (nocc',lfd) f ->
- let (nocc'',f') = substcheck k nocc' c f in
- (nocc'',f'::lfd))
- (occ,[]) cl
- in
- (occ',DOPN(i,Array.of_list (List.rev cl')))
- | DOP2(i,t1,t2) ->
- let (nocc1,t1')=substrec k occ c t1 in
- let (nocc2,t2')=substcheck k nocc1 c t2 in
- nocc2,DOP2(i,t1',t2')
- | DOP1(i,t) ->
- let (nocc,t')= substrec k occ c t in
- nocc,DOP1(i,t')
- | DLAM(n,t) ->
- let (occ',t') = substcheck (k+1) occ (lift 1 c) t in
- (occ',DLAM(n,t'))
- | DLAMV(n,cl) ->
- let (occ',cl') =
+ | DOPN((Const _ | MutConstruct _ | MutInd _), _) -> t
+ | DOPN(i,cl) ->
+ let cl' =
+ Array.fold_left (fun lfd f -> substcheck k c f :: lfd) [] cl
+ in
+ DOPN(i,Array.of_list (List.rev cl'))
+ | DOP2(i,t1,t2) ->
+ let t1' = substrec k c t1 in
+ let t2' = substcheck k c t2 in
+ DOP2(i,t1',t2')
+ | DOP1(i,t) ->
+ DOP1(i,substrec k c t)
+ | DLAM(n,t) ->
+ DLAM(n,substcheck (k+1) (lift 1 c) t)
+ | DLAMV(n,cl) ->
+ let cl' =
Array.fold_left
- (fun (nocc',lfd) f ->
- let (nocc'',f') =
- substcheck (k+1) nocc' (lift 1 c) f
- in (nocc'',f'::lfd))
- (occ,[]) cl
+ (fun lfd f -> substcheck (k+1) (lift 1 c) f ::lfd)
+ [] cl
in
- (occ',DLAMV(n,Array.of_list (List.rev cl') ))
- | _ -> occ,t
+ DLAMV(n,Array.of_list (List.rev cl'))
+ | CLam(na,t,c2) ->
+ let t' = substrec k c t in
+ let c2' = substcheck (k+1) (lift 1 c) c2 in
+ CLam(na,t',c2')
+ | CPrd(na,t,c2) ->
+ let t' = substrec k c t in
+ let c2' = substcheck (k+1) (lift 1 c) c2 in
+ CPrd(na,t',c2')
+ | CLet(na,b,t,c2) ->
+ let b' = substrec k c b in
+ let t' = substrec k c t in
+ let c2' = substcheck (k+1) (lift 1 c) c2 in
+ CLet(na,b',t',c2')
+ | DOP0 _ | VAR _ | Rel _ -> t
in
- substcheck 1 occ c t
+ let t' = substcheck 1 c t in
+ (!pos, t')
let subst_term_occ locs c t =
if locs = [] then
@@ -1406,24 +1621,25 @@ let subst_term_occ_decl locs c (id,bodyopt,typ as d) =
(***************************)
let rec occur_meta = function
- | DOP2(Prod,t,DLAM(_,c)) -> (occur_meta t) or (occur_meta c)
- | DOP2(Lambda,t,DLAM(_,c)) -> (occur_meta t) or (occur_meta c)
+ | CPrd(_,t,c) -> (occur_meta t) or (occur_meta c)
+ | CLam(_,t,c) -> (occur_meta t) or (occur_meta c)
+ | CLet(_,b,t,c) -> (occur_meta b) or (occur_meta t) or (occur_meta c)
| DOPN(_,cl) -> (array_exists occur_meta cl)
| DOP2(Cast,c,t) -> occur_meta c or occur_meta t
| DOP0(Meta(_)) -> true
| _ -> false
-let rel_vect = (Generic.rel_vect : int -> int -> constr array)
-
let occur_existential =
let rec occrec = function
| DOPN(Evar _,_) -> true
| DOPN(_,cl) -> array_exists occrec cl
- | DOPL(_,cl) -> List.exists occrec cl
| DOP2(_,c1,c2) -> occrec c1 or occrec c2
| DOP1(_,c) -> occrec c
| DLAM(_,c) -> occrec c
| DLAMV(_,cl) -> array_exists occrec cl
+ | CPrd(_,t,c) -> (occrec t) or (occrec c)
+ | CLam(_,t,c) -> (occrec t) or (occrec c)
+ | CLet(_,b,t,c) -> (occrec b) or (occrec t) or (occrec c)
| _ -> false
in
occrec
@@ -1440,13 +1656,14 @@ let comp_term t1 t2 =
| (DOPN(o1,v1), DOPN(o2,v2)) ->
(o1==o2) & (Array.length v1 = Array.length v2)
& array_for_all2 (==) v1 v2
- | (DOPL(o1,l1), DOPL(o2,l2)) ->
- (o1==o2) & (List.length l1 = List.length l2)
- & List.for_all2 (==) l1 l2
| (DLAM(x1,t1), DLAM(x2,t2)) -> x1==x2 & t1==t2
| (DLAMV(x1,v1), DLAMV(x2,v2)) ->
(x1==x2) & (Array.length v1 = Array.length v2)
& array_for_all2 (==) v1 v2
+ | CLam(x1,t1,c1), CLam(x2,t2,c2) -> (x1==x2) & (t1==t2) & (c1==c2)
+ | CPrd(x1,t1,c1), CPrd(x2,t2,c2) -> (x1==x2) & (t1==t2) & (c1==c2)
+ | CLet(x1,b1,t1,c1), CLet (x2,b2,t2,c2) ->
+ (x1==x2) & (b1==b2) & (t1==t2) & (c1==c2)
| (Rel i, Rel j) -> i=j
| (VAR x, VAR y) -> x==y
| _ -> false
@@ -1457,9 +1674,11 @@ let hash_term (sh_rec,(sh_op,sh_na,sh_id)) t =
| DOP1(o,t) -> DOP1(sh_op o, sh_rec t)
| DOP2(o,t1,t2) -> DOP2(sh_op o, sh_rec t1, sh_rec t2)
| DOPN(o,v) -> DOPN(sh_op o, Array.map sh_rec v)
- | DOPL(o,l) -> DOPL(sh_op o, List.map sh_rec l)
| DLAM(n,t) -> DLAM(sh_na n, sh_rec t)
| DLAMV(n,v) -> DLAMV(sh_na n, Array.map sh_rec v)
+ | CLam (n,t,c) -> CLam (sh_na n, sh_rec t, sh_rec c)
+ | CPrd (n,t,c) -> CPrd (sh_na n, sh_rec t, sh_rec c)
+ | CLet (n,b,t,c) -> CLet (sh_na n, sh_rec b, sh_rec t, sh_rec c)
| Rel i -> t
| VAR x -> VAR (sh_id x)
@@ -1568,204 +1787,138 @@ let is_hd_const=function
Some (Const c,Array.of_list (List.tl (Array.to_list t)))
|_ -> None)
|_ -> None
-
-(*Gives the occurences number of t in u*)
-let rec nb_occ_term t u=
- let one_step t=function
- | DOP1(_,c) -> nb_occ_term t c
- | DOP2(_,c0,c1) -> (nb_occ_term t c0)+(nb_occ_term t c1)
- | DOPN(_,a) -> Array.fold_left (fun a x -> a+(nb_occ_term t x)) 0 a
- | DOPL(_,l) -> List.fold_left (fun a x -> a+(nb_occ_term t x)) 0 l
- | DLAM(_,c) -> nb_occ_term t c
- | DLAMV(_,a) -> Array.fold_left (fun a x -> a+(nb_occ_term t x)) 0 a
- | _ -> 0
- in
- if t=u then
- 1
- else
- one_step t u
-
-(*Alpha-conversion*)
-let bind_eq=function
- | (Anonymous,Anonymous) -> true
- | (Name _,Name _) -> true
- | _ -> false
-
- (*Tells if two constrs are equal modulo unification*)
-let rec eq_mod_rel l_meta=function
- | (t,DOP0(Meta n)) ->
- if not(List.mem n (fst (List.split l_meta))) then
- Some ([(n,t)]@l_meta)
- else if (List.assoc n l_meta)=t then
- Some l_meta
- else
- None
- | DOP1(op0,c0), DOP1(op1,c1) ->
- if op0=op1 then
- eq_mod_rel l_meta (c0,c1)
- else
- None
- | DOP2(op0,t0,c0), DOP2(op1,t1,c1) ->
- if op0=op1 then
- match (eq_mod_rel l_meta (t0,t1)) with
- | None -> None
- | Some l -> eq_mod_rel l (c0,c1)
- else
- None
- | DOPN(op0,t0), DOPN(op1,t1) ->
- if (op0=op1) & ((Array.length t0)=(Array.length t1)) then
- List.fold_left2
- (fun a c1 c2 ->
- match a with
- | None -> None
- | Some l -> eq_mod_rel l (c1,c2)) (Some l_meta)
- (Array.to_list t0) (Array.to_list t1)
- else
- None
- | DLAM(n0,t0),DLAM(n1,t1) ->
- if (bind_eq (n0,n1)) then
- eq_mod_rel l_meta (t0,t1)
- else
- None
- | (t,u) ->
- if t=u then Some l_meta else None
-
-(*Substitutes a list of meta l in t*)
-let rec subst_with_lmeta l=function
- | DOP0(Meta n) -> List.assoc n l
- | DOP1(op,t) -> DOP1(op,subst_with_lmeta l t)
- | DOP2(op,t0,t1) -> DOP2(op,subst_with_lmeta l t0,subst_with_lmeta l t1)
- | DOPN(op,t) -> DOPN(op,Array.map (subst_with_lmeta l) t)
- | DOPL(op,ld) -> DOPL(op,List.map (subst_with_lmeta l) ld)
- | DLAM(n,t) -> DLAM(n,subst_with_lmeta l t)
- | DLAMV(n,t) -> DLAMV(n,Array.map (subst_with_lmeta l) t)
- | t -> t
-
-(*Carries out the following translation: DOPN(AppL,[|t|]) -> t and
- DOPN(AppL,[|DOPN(AppL,t);...;t'|]) -> DOPN(AppL;[|t;...;t'|])*)
-let rec appl_elim=function
- | DOPN(AppL,t) ->
- if (Array.length t)=1 then
- appl_elim t.(0)
- else
- (match t.(0) with
- | DOPN(AppL,t') ->
- appl_elim (DOPN(AppL,Array.append t'
- (Array.of_list
- (List.tl (Array.to_list t)))))
- |_ -> DOPN(AppL,Array.map appl_elim t))
- | DOP1(op,t) -> DOP1(op,appl_elim t)
- | DOP2(op,t0,t1) -> DOP2(op,appl_elim t0,appl_elim t1)
- | DOPN(op,t) -> DOPN(op,Array.map appl_elim t)
- | DOPL(op,ld) -> DOPL(op,List.map appl_elim ld)
- | DLAM(n,t) -> DLAM(n,appl_elim t)
- | DLAMV(n,t) -> DLAMV(n,Array.map appl_elim t)
- | t -> t
-
-(*Gives Some(first instance of ceq in cref,occurence number for this
- instance) or None if no instance of ceq can be found in cref*)
-let sub_term_with_unif cref ceq=
- let rec find_match l_meta nb_occ op_ceq t_eq=function
- | DOPN(AppL,t) as u ->
- (match (t.(0)) with
- | DOPN(op,t_op) ->
- let t_args=Array.of_list (List.tl (Array.to_list t)) in
- if op=op_ceq then
- match
- (List.fold_left2
- (fun a c0 c1 ->
- match a with
- | None -> None
- | Some l -> eq_mod_rel l (c0,c1)) (Some l_meta)
- (Array.to_list t_args) (Array.to_list t_eq))
- with
- | None ->
- List.fold_left
- (fun (l_meta,nb_occ) x -> find_match l_meta nb_occ
- op_ceq t_eq x) (l_meta,nb_occ) (Array.to_list
- t_args)
- | Some l -> (l,nb_occ+1)
- else
- List.fold_left
- (fun (l_meta,nb_occ) x -> find_match l_meta
- nb_occ op_ceq t_eq x)
- (l_meta,nb_occ) (Array.to_list t)
- | VAR _ ->
- List.fold_left
- (fun (l_meta,nb_occ) x -> find_match l_meta
- nb_occ op_ceq t_eq x)
- (l_meta,nb_occ) (Array.to_list t)
- |_ -> (l_meta,nb_occ))
- | DOP2(_,t,DLAM(_,c)) ->
- let (lt,nbt)=find_match l_meta nb_occ op_ceq t_eq t in
- find_match lt nbt op_ceq t_eq c
- | DOPN(_,t) ->
- List.fold_left
- (fun (l_meta,nb_occ) x -> find_match l_meta nb_occ op_ceq t_eq x)
- (l_meta,nb_occ) (Array.to_list t)
- |_ -> (l_meta,nb_occ)
- in
- match (is_hd_const ceq) with
- | None ->
- if (occur_meta ceq) then
- None
- else
- let nb_occ=nb_occ_term ceq cref in
- if nb_occ=0 then
- None
- else
- Some (ceq,nb_occ)
- | Some (head,t_args) ->
- let (l,nb)=find_match [] 0 head t_args cref in
- if nb=0 then
- None
- else
- Some ((subst_with_lmeta l ceq),nb)
+
+(* Abstract decomposition of constr to deal with generic functions *)
type constr_operator =
| OpMeta of int
| OpSort of sorts
| OpRel of int | OpVar of identifier
- | OpCast | OpProd of name | OpLambda of name
+ | OpCast | OpProd of name | OpLambda of name | OpLetIn of name
| OpAppL | OpConst of section_path | OpAbst of section_path
| OpEvar of existential_key
| OpMutInd of inductive_path
| OpMutConstruct of constructor_path
| OpMutCase of case_info
- | OpRec of fix_kind
+ | OpRec of fix_kind * name list
let splay_constr = function
- | Rel n -> OpRel n, []
- | VAR id -> OpVar id, []
- | DOP0 (Meta n) -> OpMeta n, []
- | DOP0 (Sort s) -> OpSort s, []
- | DOP2 (Cast, t1, t2) -> OpCast, [t1;t2]
- | DOP2 (Prod, t1, (DLAM (x,t2))) -> OpProd x, [t1;t2]
- | DOP2 (Lambda, t1, (DLAM (x,t2))) -> OpLambda x, [t1;t2]
- | DOPN (AppL,a) -> OpAppL, Array.to_list a
- | DOPN (Const sp, a) -> OpConst sp, Array.to_list a
- | DOPN (Evar sp, a) -> OpEvar sp, Array.to_list a
- | DOPN (MutInd ind_sp, l) -> OpMutInd ind_sp, Array.to_list l
- | DOPN (MutConstruct cstr_sp,l) -> OpMutConstruct cstr_sp, Array.to_list l
- | DOPN (MutCase ci,v) -> OpMutCase ci, Array.to_list v
- | DOPN ((Fix (f,i),a)) -> OpRec (RFix (f,i)), Array.to_list a
- | DOPN ((CoFix i),a) -> OpRec (RCofix i), Array.to_list a
+ | Rel n -> OpRel n, [||]
+ | VAR id -> OpVar id, [||]
+ | DOP0 (Meta n) -> OpMeta n, [||]
+ | DOP0 (Sort s) -> OpSort s, [||]
+ | DOP2 (Cast, t1, t2) -> OpCast, [|t1;t2|]
+ | CPrd (x, t1, t2) -> OpProd x, [|t1;t2|]
+ | CLam (x, t1, t2) -> OpLambda x, [|t1;t2|]
+ | CLet (x, b, t1, t2) -> OpLetIn x, [|b;t1;t2|]
+ | DOPN (AppL,a) -> OpAppL, a
+ | DOPN (Const sp, a) -> OpConst sp, a
+ | DOPN (Evar sp, a) -> OpEvar sp, a
+ | DOPN (MutInd ind_sp, l) -> OpMutInd ind_sp, l
+ | DOPN (MutConstruct cstr_sp,l) -> OpMutConstruct cstr_sp, l
+ | DOPN (MutCase ci,v) -> OpMutCase ci, v
+ | DOPN ((Fix (f,i),a)) as c ->
+ let (fi,(tl,lna,bl)) = destFix c in
+ OpRec (RFix fi,lna), Array.append tl bl
+ | DOPN ((CoFix i),a) as c ->
+ let (fi,(tl,lna,bl)) = destCoFix c in
+ OpRec (RCoFix fi,lna), Array.append tl bl
| _ -> errorlabstrm "Term.splay_term" [< 'sTR "ill-formed constr" >]
let gather_constr = function
- | OpRel n, [] -> Rel n
- | OpVar id, [] -> VAR id
- | OpMeta n, [] -> DOP0 (Meta n)
- | OpSort s, [] -> DOP0 (Sort s)
- | OpCast, [t1;t2] -> DOP2 (Cast, t1, t2)
- | OpProd x, [t1;t2] -> DOP2 (Prod, t1, (DLAM (x,t2)))
- | OpLambda x, [t1;t2] -> DOP2 (Lambda, t1, (DLAM (x,t2)))
- | OpAppL, a -> DOPN (AppL,Array.of_list a)
- | OpConst sp, a -> DOPN (Const sp,Array.of_list a)
- | OpEvar sp, a -> DOPN (Evar sp, Array.of_list a)
- | OpMutInd ind_sp, l -> DOPN (MutInd ind_sp, Array.of_list l)
- | OpMutConstruct cstr_sp, l -> DOPN (MutConstruct cstr_sp,Array.of_list l)
- | OpMutCase ci, v -> DOPN (MutCase ci,Array.of_list v)
- | OpRec (RFix (f,i)), a -> DOPN ((Fix (f,i),Array.of_list a))
- | OpRec (RCofix i), a -> DOPN ((CoFix i),Array.of_list a)
+ | OpRel n, [||] -> Rel n
+ | OpVar id, [||] -> VAR id
+ | OpMeta n, [||] -> DOP0 (Meta n)
+ | OpSort s, [||] -> DOP0 (Sort s)
+ | OpCast, [|t1;t2|] -> DOP2 (Cast, t1, t2)
+ | OpProd x, [|t1;t2|] -> mkProd (x, t1, t2)
+ | OpLambda x, [|t1;t2|] -> mkLambda (x, t1, t2)
+ | OpLetIn x, [|b;t1;t2|] -> mkLetIn (x, b, t1, t2)
+ | OpAppL, a -> DOPN (AppL, a)
+ | OpConst sp, a -> DOPN (Const sp, a)
+ | OpEvar sp, a -> DOPN (Evar sp, a)
+ | OpMutInd ind_sp, l -> DOPN (MutInd ind_sp, l)
+ | OpMutConstruct cstr_sp, l -> DOPN (MutConstruct cstr_sp, l)
+ | OpMutCase ci, v -> DOPN (MutCase ci, v)
+ | OpRec (RFix fi,lna), a ->
+ let n = Array.length a / 2 in
+ mkFix (fi,(Array.sub a 0 n, lna, Array.sub a n n))
+ | OpRec (RCoFix i,lna), a ->
+ let n = Array.length a / 2 in
+ mkCoFix (i,(Array.sub a 0 n, lna, Array.sub a n n))
| _ -> errorlabstrm "Term.gather_term" [< 'sTR "ill-formed constr" >]
+
+let rec mycombine l1 l3 =
+ match (l1, l3) with
+ ([], []) -> []
+ | (a1::l1, a3::l3) -> (a1, None, a3) :: mycombine l1 l3
+ | (_, _) -> invalid_arg "mycombine"
+
+let rec mysplit = function
+ [] -> ([], [])
+ | (x, _, z)::l -> let (rx, rz) = mysplit l in (x::rx, z::rz)
+
+let splay_constr_with_binders = function
+ | Rel n -> OpRel n, [], [||]
+ | VAR id -> OpVar id, [], [||]
+ | DOP0 (Meta n) -> OpMeta n, [], [||]
+ | DOP0 (Sort s) -> OpSort s, [], [||]
+ | DOP2 (Cast, t1, t2) -> OpCast, [], [|t1;t2|]
+ | CPrd (x, t1, t2) -> OpProd x, [x,None,t1], [|t2|]
+ | CLam (x, t1, t2) -> OpLambda x, [x,None,t1], [|t2|]
+ | CLet (x, b, t1, t2) -> OpLetIn x, [x,Some b,t1], [|t2|]
+ | DOPN (AppL,a) -> OpAppL, [], a
+ | DOPN (Const sp, a) -> OpConst sp, [], a
+ | DOPN (Evar sp, a) -> OpEvar sp, [], a
+ | DOPN (MutInd ind_sp, l) -> OpMutInd ind_sp, [], l
+ | DOPN (MutConstruct cstr_sp,l) -> OpMutConstruct cstr_sp, [], l
+ | DOPN (MutCase ci,v) -> OpMutCase ci, [], v
+ | DOPN ((Fix (f,i),a)) as c ->
+ let (fi,(tl,lna,bl)) = destFix c in
+ let n = Array.length bl in
+ let ctxt = mycombine
+ (List.rev lna)
+ (Array.to_list (Array.mapi lift tl)) in
+ OpRec (RFix fi,lna), ctxt, bl
+ | DOPN ((CoFix i),a) as c ->
+ let (fi,(tl,lna,bl)) = destCoFix c in
+ let n = Array.length bl in
+ let ctxt = mycombine
+ (List.rev lna)
+ (Array.to_list (Array.mapi lift tl)) in
+ OpRec (RCoFix fi,lna), ctxt, bl
+ | _ -> errorlabstrm "Term.splay_term" [< 'sTR "ill-formed constr" >]
+
+let gather_constr_with_binders = function
+ | OpRel n, [], [||] -> Rel n
+ | OpVar id, [], [||] -> VAR id
+ | OpMeta n, [], [||] -> DOP0 (Meta n)
+ | OpSort s, [], [||] -> DOP0 (Sort s)
+ | OpCast, [], [|t1;t2|] -> DOP2 (Cast, t1, t2)
+ | OpProd _, [x,None,t1], [|t2|] -> mkProd (x, t1, t2)
+ | OpLambda _, [x,None,t1], [|t2|] -> mkLambda (x, t1, t2)
+ | OpLetIn _, [x,Some b,t1], [|t2|] -> mkLetIn (x, b, t1, t2)
+ | OpAppL, [], a -> DOPN (AppL, a)
+ | OpConst sp, [], a -> DOPN (Const sp, a)
+ | OpEvar sp, [], a -> DOPN (Evar sp, a)
+ | OpMutInd ind_sp, [], l -> DOPN (MutInd ind_sp, l)
+ | OpMutConstruct cstr_sp, [], l -> DOPN (MutConstruct cstr_sp, l)
+ | OpMutCase ci, [], v -> DOPN (MutCase ci, v)
+ | OpRec (RFix fi,lna), ctxt, bl ->
+ let (lna, tl) = mysplit ctxt in
+ let tl = Array.mapi (fun i -> lift (-i)) (Array.of_list tl) in
+ mkFix (fi,(tl, List.rev lna, bl))
+ | OpRec (RCoFix i,lna), ctxt, bl ->
+ let (lna, tl) = mysplit ctxt in
+ let tl = Array.mapi (fun i -> lift (-i)) (Array.of_list tl) in
+ mkCoFix (i,(tl, List.rev lna, bl))
+ | _ -> errorlabstrm "Term.gather_term" [< 'sTR "ill-formed constr" >]
+
+let generic_fold_left f acc bl tl =
+ let acc =
+ List.fold_left
+ (fun acc (_,bo,t) ->
+ match bo with
+ | None -> f acc t
+ | Some b -> f (f acc b) t) acc bl in
+ Array.fold_left f acc tl