let fire_beta, upto =
match l with C.Meta _ :: _ -> true, List.length l - 1 | _ -> false, 0
in
- let a,l1 =
- (* sharing fold? *)
- List.fold_right
- (fun t (a,l) -> let a,t = f k a t in a, t :: l)
- l (a,[])
- in
+ let a,l1 = HExtlib.sharing_map_acc (f k) a l in
a, if l1 == l then orig else
let t =
match l1 with
a, if ty1 == ty && t1 == t && b1 == b then orig else C.LetIn (n,ty1,t1,b1)
| C.Match (r,oty,t,pl) as orig ->
let a,oty1 = f k a oty in let a,t1 = f k a t in
- let a,pl1 =
- (* sharing fold? *)
- List.fold_right (fun t (a,l) -> let a,t = f k a t in a,t::l) pl (a,[])
- in
+ let a,pl1 = HExtlib.sharing_map_acc (f k) a pl in
a, if oty1 == oty && t1 == t && pl1 == pl then orig
else C.Match(r,oty1,t1,pl1)
;;
aux (List.map fst ctx) t
;;
-let apply_subst subst context t =
+let rec fire_projection_redex on_args = function
+ | C.Meta _ as t -> t
+ | C.Appl(C.Const(Ref.Ref(_,Ref.Fix(fno,rno,_)) as r)::args as ol)as ot->
+ let l= if on_args then List.map (fire_projection_redex true) ol else ol in
+ let t = if l == ol then ot else C.Appl l in
+ let ifl,(_,_,pragma),_ = NCicEnvironment.get_checked_fixes_or_cofixes r in
+ let conclude () =
+ if on_args then
+ let l' = HExtlib.sharing_map (fire_projection_redex true) l in
+ if l == l' then t else C.Appl l'
+ else
+ t (* ot is the same *)
+ in
+ if pragma <> `Projection || List.length args <= rno then conclude ()
+ else
+ (match List.nth args rno with
+ | C.Appl (C.Const(Ref.Ref(_,Ref.Con _))::_) ->
+ let _, _, _, _, fbody = List.nth ifl fno in (* fbody is closed! *)
+ let t = C.Appl (fbody::args) in
+ (match NCicReduction.head_beta_reduce ~delta:max_int t with
+ | C.Match (_,_,C.Appl(C.Const(Ref.Ref(_,Ref.Con (_,_,leftno)))::kargs),[pat])->
+ let _,kargs = HExtlib.split_nth leftno kargs in
+ fire_projection_redex false
+ (NCicReduction.head_beta_reduce
+ ~delta:max_int (C.Appl (pat :: kargs)))
+ | C.Appl(C.Match(_,_,C.Appl(C.Const(Ref.Ref(_,Ref.Con (_,_,leftno)))::kargs),[pat]) :: args) ->
+ let _,kargs = HExtlib.split_nth leftno kargs in
+ fire_projection_redex false
+ (NCicReduction.head_beta_reduce
+ ~delta:max_int (C.Appl (pat :: kargs @ args)))
+ | _ -> conclude ())
+ | _ -> conclude ())
+ | t when on_args -> NCicUtils.map (fun _ x -> x) true fire_projection_redex t
+ | t -> t
+;;
+
+let apply_subst ?(fix_projections=false) subst context t =
let rec apply_subst subst () =
function
NCic.Meta (i,lc) ->
let t = NCicSubstitution.subst_meta lc t in
apply_subst subst () t
with
- Not_found ->
+ NCicUtils.Subst_not_found j when j = i ->
match lc with
_,NCic.Irl _ -> NCic.Meta (i,lc)
| n,NCic.Ctx l ->
apply_subst subst () (NCicSubstitution.lift n t)) l))))
| t -> NCicUtils.map (fun _ () -> ()) () (apply_subst subst) t
in
- clean_or_fix_dependent_abstrations context (apply_subst subst () t)
+ (if fix_projections then fire_projection_redex true else fun x -> x)
+ (clean_or_fix_dependent_abstrations context (apply_subst subst () t))
;;
-let apply_subst_context subst context =
+let apply_subst_context ~fix_projections subst context =
+ let apply_subst = apply_subst ~fix_projections in
let rec aux c = function
| [] -> []
| (name,NCic.Decl t as e) :: tl ->
| [] -> []
| (i,_) :: _ when List.mem_assoc i subst -> assert false
| (i,(name,ctx,ty)) :: tl ->
- (i,(name,apply_subst_context subst ctx,apply_subst subst ctx ty)) ::
+ (i,(name,apply_subst_context ~fix_projections:true subst ctx,
+ apply_subst ~fix_projections:true subst ctx ty)) ::
apply_subst_metasenv subst tl
;;
-let height_of_term tl =
- let h = ref 0 in
- let get_height (NReference.Ref (uri,_)) =
- let _,height,_,_,_ = NCicEnvironment.get_checked_obj uri in
- height in
- let rec aux =
- function
- NCic.Meta (_,(_,NCic.Ctx l)) -> List.iter aux l
- | NCic.Meta _ -> ()
- | NCic.Rel _
- | NCic.Sort _ -> ()
- | NCic.Implicit _ -> assert false
- | NCic.Const nref -> h := max !h (get_height nref)
- | NCic.Prod (_,t1,t2)
- | NCic.Lambda (_,t1,t2) -> aux t1; aux t2
- | NCic.LetIn (_,s,ty,t) -> aux s; aux ty; aux t
- | NCic.Appl l -> List.iter aux l
- | NCic.Match (_,outty,t,pl) -> aux outty; aux t; List.iter aux pl
- in
- List.iter aux tl;
- 1 + !h
+(* hide optional arg *)
+let apply_subst s c t = apply_subst s c t;;
+
+
+type meta_kind = [ `IsSort | `IsType | `IsTerm ]
+
+let is_kind x = x = `IsSort || x = `IsType || x = `IsTerm ;;
+
+let kind_of_meta l =
+ try
+ (match List.find is_kind l with
+ | `IsSort | `IsType | `IsTerm as x -> x
+ | _ -> assert false)
+ with
+ Not_found -> assert false
;;
-let height_of_obj_kind uri =
- function
- NCic.Inductive _
- | NCic.Constant (_,_,None,_,_)
- | NCic.Fixpoint (false,_,_) -> 0
- | NCic.Fixpoint (true,ifl,_) ->
- let iflno = List.length ifl in
- height_of_term
- (List.fold_left
- (fun l (_,_,_,ty,bo) ->
- let bo = NCicTypeChecker.debruijn uri iflno [] bo in
- ty::bo::l
- ) [] ifl)
- | NCic.Constant (_,_,Some bo,ty,_) -> height_of_term [bo;ty]
+let rec replace_in_metasenv i f = function
+ | [] -> assert false
+ | (j,e)::tl when j=i -> (i,f e) :: tl
+ | x::tl -> x :: replace_in_metasenv i f tl
+;;
+
+let rec replace_in_subst i f = function
+ | [] -> assert false
+ | (j,e)::tl when j=i -> (i,f e) :: tl
+ | x::tl -> x :: replace_in_subst i f tl
;;
+
+let set_kind newkind attrs =
+ newkind :: List.filter (fun x -> not (is_kind x)) attrs
+;;
+
+let max_kind k1 k2 =
+ match k1, k2 with
+ | `IsSort, _ | _, `IsSort -> `IsSort
+ | `IsType, _ | _, `IsType -> `IsType
+ | _ -> `IsTerm
+;;
+