Skip to content

Commit ed93de7

Browse files
committed
improve efficiency of the reduction interpreter of coqtop
Conflicts: kernel/closure.ml kernel/closure.mli kernel/reduction.ml
1 parent 5b1e6e5 commit ed93de7

File tree

3 files changed

+55
-108
lines changed

3 files changed

+55
-108
lines changed

kernel/closure.ml

Lines changed: 41 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,8 @@ and fterm =
346346
| FProj of projection * fconstr
347347
| FFix of fixpoint * fconstr subs
348348
| FCoFix of cofixpoint * fconstr subs
349-
| FCases of case_info * fconstr * fconstr * fconstr array
349+
| FCase of case_info * fconstr * fconstr * fconstr array
350+
| FCaseT of case_info * constr * fconstr * constr array * fconstr subs (* predicate and branches are closures *)
350351
| FLambda of int * (Name.t * constr) list * constr * fconstr subs
351352
| FProd of Name.t * fconstr * fconstr
352353
| FLetIn of Name.t * fconstr * fconstr * constr * fconstr subs
@@ -376,6 +377,7 @@ let update v1 no t =
376377
type stack_member =
377378
| Zapp of fconstr array
378379
| Zcase of case_info * fconstr * fconstr array
380+
| ZcaseT of case_info * constr * constr array * fconstr subs
379381
| Zproj of int * int * constant
380382
| Zfix of fconstr * stack
381383
| Zshift of int
@@ -490,72 +492,7 @@ let zupdate m s =
490492
Zupdate(m)::s'
491493
else s
492494

493-
(* Closure optimization: *)
494-
let rec compact_constr (lg, subs as s) c k =
495-
match kind_of_term c with
496-
Rel i ->
497-
if i < k then s, c else
498-
(try (lg,subs), mkRel (k + lg - List.index Int.equal (i-k+1) subs)
499-
with Not_found -> (lg+1, (i-k+1)::subs), mkRel (k+lg))
500-
| (Sort _|Var _|Meta _|Ind _|Const _|Construct _) -> s, c
501-
| Evar(ev,v) ->
502-
let (s, v') = compact_vect s v k in
503-
if v==v' then s, c else s, mkEvar(ev, v')
504-
| Cast(a,ck,b) ->
505-
let (s, a') = compact_constr s a k in
506-
let (s, b') = compact_constr s b k in
507-
if a==a' && b==b' then s, c else s, mkCast(a', ck, b')
508-
| App(f,v) ->
509-
let (s, f') = compact_constr s f k in
510-
let (s, v') = compact_vect s v k in
511-
if f==f' && v==v' then s, c else s, mkApp(f',v')
512-
| Proj (p,t) ->
513-
let (s, t') = compact_constr s t k in
514-
if t'==t then s, c else s, mkProj (p,t')
515-
| Lambda(n,a,b) ->
516-
let (s, a') = compact_constr s a k in
517-
let (s, b') = compact_constr s b (k+1) in
518-
if a==a' && b==b' then s, c else s, mkLambda(n,a',b')
519-
| Prod(n,a,b) ->
520-
let (s, a') = compact_constr s a k in
521-
let (s, b') = compact_constr s b (k+1) in
522-
if a==a' && b==b' then s, c else s, mkProd(n,a',b')
523-
| LetIn(n,a,ty,b) ->
524-
let (s, a') = compact_constr s a k in
525-
let (s, ty') = compact_constr s ty k in
526-
let (s, b') = compact_constr s b (k+1) in
527-
if a==a' && ty==ty' && b==b' then s, c else s, mkLetIn(n,a',ty',b')
528-
| Fix(fi,(na,ty,bd)) ->
529-
let (s, ty') = compact_vect s ty k in
530-
let (s, bd') = compact_vect s bd (k+Array.length ty) in
531-
if ty==ty' && bd==bd' then s, c else s, mkFix(fi,(na,ty',bd'))
532-
| CoFix(i,(na,ty,bd)) ->
533-
let (s, ty') = compact_vect s ty k in
534-
let (s, bd') = compact_vect s bd (k+Array.length ty) in
535-
if ty==ty' && bd==bd' then s, c else s, mkCoFix(i,(na,ty',bd'))
536-
| Case(ci,p,a,br) ->
537-
let (s, p') = compact_constr s p k in
538-
let (s, a') = compact_constr s a k in
539-
let (s, br') = compact_vect s br k in
540-
if p==p' && a==a' && br==br' then s, c else s, mkCase(ci,p',a',br')
541-
542-
and compact_vect s v k =
543-
let fold s c = compact_constr s c k in
544-
Array.smartfoldmap fold s v
545-
546-
(* Computes the minimal environment of a closure.
547-
Idea: if the subs is not identity, the term will have to be
548-
reallocated entirely (to propagate the substitution). So,
549-
computing the set of free variables does not change the
550-
complexity. *)
551-
let optimise_closure env c =
552-
if is_subs_id env then (env,c) else
553-
let ((_,s), c') = compact_constr (0,[]) c 1 in
554-
let env' = Array.map_of_list (fun i -> clos_rel env i) s in
555-
(subs_cons (env', subs_id 0),c')
556-
557495
let mk_lambda env t =
558-
let (env,t) = optimise_closure env t in
559496
let (rvars,t') = decompose_lam t in
560497
FLambda(List.length rvars, List.rev rvars, t', env)
561498

@@ -601,8 +538,7 @@ let mk_clos_deep clos_fun env t =
601538
term = FProj (p, clos_fun env c) }
602539
| Case (ci,p,c,v) ->
603540
{ norm = Red;
604-
term = FCases (ci, clos_fun env p, clos_fun env c,
605-
CArray.Fun1.map clos_fun env v) }
541+
term = FCaseT (ci, p, clos_fun env c, v, env) }
606542
| Fix fx ->
607543
{ norm = Cstr; term = FFix (fx, env) }
608544
| CoFix cfx ->
@@ -633,10 +569,14 @@ let rec to_constr constr_fun lfts v =
633569
| FFlex (ConstKey op) -> mkConstU op
634570
| FInd op -> mkIndU op
635571
| FConstruct op -> mkConstructU op
636-
| FCases (ci,p,c,ve) ->
572+
| FCase (ci,p,c,ve) ->
637573
mkCase (ci, constr_fun lfts p,
638574
constr_fun lfts c,
639575
CArray.Fun1.map constr_fun lfts ve)
576+
| FCaseT (ci,p,c,ve,env) ->
577+
mkCase (ci, constr_fun lfts (mk_clos env p),
578+
constr_fun lfts c,
579+
Array.map (fun b -> constr_fun lfts (mk_clos env b)) ve)
640580
| FFix ((op,(lna,tys,bds)),e) ->
641581
let n = Array.length bds in
642582
let ftys = CArray.Fun1.map mk_clos e tys in
@@ -702,35 +642,24 @@ let rec fstrong unfreeze_fun lfts v =
702642
to_constr (fstrong unfreeze_fun) lfts (unfreeze_fun v)
703643
*)
704644

705-
let rec zip m stk rem = match stk with
706-
| [] ->
707-
begin match rem with
708-
| [] -> m
709-
| stk :: rem -> zip m stk rem
710-
end
711-
| Zapp args :: s -> zip {norm=neutr m.norm; term=FApp(m, args)} s rem
712-
| Zcase(ci,p,br)::s ->
713-
let t = FCases(ci, p, m, br) in
714-
zip {norm=neutr m.norm; term=t} s rem
715-
| Zproj (i,j,cst) :: s ->
716-
zip {norm=neutr m.norm; term=FProj (Projection.make cst true,m)} s rem
717-
| Zfix(fx,par)::s ->
718-
zip fx par ((Zapp [|m|] :: s) :: rem)
719-
| Zshift(n)::s ->
720-
zip (lift_fconstr n m) s rem
721-
| Zupdate(rf)::s ->
722-
zip_update m s rem rf
723-
724-
and zip_update m stk rem rf = match stk with
725-
| [] ->
726-
begin match rem with
727-
| [] -> update rf m.norm m.term
728-
| stk :: rem -> zip_update m stk rem rf
729-
end
730-
| Zupdate rf :: s -> zip_update m s rem rf
731-
| s -> zip (update rf m.norm m.term) s rem
732-
733-
let zip m stk = zip m stk []
645+
let rec zip m stk =
646+
match stk with
647+
| [] -> m
648+
| Zapp args :: s -> zip {norm=neutr m.norm; term=FApp(m, args)} s
649+
| Zcase(ci,p,br)::s ->
650+
let t = FCase(ci, p, m, br) in
651+
zip {norm=neutr m.norm; term=t} s
652+
| ZcaseT(ci,p,br,e)::s ->
653+
let t = FCaseT(ci, p, m, br, e) in
654+
zip {norm=neutr m.norm; term=t} s
655+
| Zproj (i,j,cst) :: s ->
656+
zip {norm=neutr m.norm; term=FProj(Projection.make cst true,m)} s
657+
| Zfix(fx,par)::s ->
658+
zip fx (par @ append_stack [|m|] s)
659+
| Zshift(n)::s ->
660+
zip (lift_fconstr n m) s
661+
| Zupdate(rf)::s ->
662+
zip (update rf m.norm m.term) s
734663

735664
let fapp_stack (m,stk) = zip m stk
736665

@@ -802,7 +731,8 @@ let rec get_args n tys f e stk =
802731

803732
(* Eta expansion: add a reference to implicit surrounding lambda at end of stack *)
804733
let rec eta_expand_stack = function
805-
| (Zapp _ | Zfix _ | Zcase _ | Zshift _ | Zupdate _ | Zproj _ as e) :: s ->
734+
| (Zapp _ | Zfix _ | Zcase _ | ZcaseT _ | Zproj _
735+
| Zshift _ | Zupdate _ as e) :: s ->
806736
e :: eta_expand_stack s
807737
| [] ->
808738
[Zshift 1; Zapp [|{norm=Norm; term= FRel 1}|]]
@@ -930,7 +860,8 @@ let rec knh info m stk =
930860
| FCLOS(t,e) -> knht info e t (zupdate m stk)
931861
| FLOCKED -> assert false
932862
| FApp(a,b) -> knh info a (append_stack b (zupdate m stk))
933-
| FCases(ci,p,t,br) -> knh info t (Zcase(ci,p,br)::zupdate m stk)
863+
| FCase(ci,p,t,br) -> knh info t (Zcase(ci,p,br)::zupdate m stk)
864+
| FCaseT(ci,p,t,br,e) -> knh info t (ZcaseT(ci,p,br,e)::zupdate m stk)
934865
| FFix(((ri,n),(_,_,_)),_) ->
935866
(match get_nth_arg m ri.(n) stk with
936867
(Some(pars,arg),stk') -> knh info arg (Zfix(m,pars)::stk')
@@ -958,7 +889,7 @@ and knht info e t stk =
958889
| App(a,b) ->
959890
knht info e a (append_stack (mk_clos_vect e b) stk)
960891
| Case(ci,p,t,br) ->
961-
knht info e t (Zcase(ci, mk_clos e p, mk_clos_vect e br)::stk)
892+
knht info e t (ZcaseT(ci, p, br, e)::stk)
962893
| Fix _ -> knh info (mk_clos2 e t) stk
963894
| Cast(a,_,_) -> knht info e a stk
964895
| Rel n -> knh info (clos_rel e n) stk
@@ -995,6 +926,10 @@ let rec knr info m stk =
995926
assert (ci.ci_npar>=0);
996927
let rargs = drop_parameters depth ci.ci_npar args in
997928
kni info br.(c-1) (rargs@s)
929+
| (depth, args, ZcaseT(ci,_,br,e)::s) ->
930+
assert (ci.ci_npar>=0);
931+
let rargs = drop_parameters depth ci.ci_npar args in
932+
knit info e br.(c-1) (rargs@s)
998933
| (_, cargs, Zfix(fx,par)::s) ->
999934
let rarg = fapp_stack(m,cargs) in
1000935
let stk' = par @ append_stack [|rarg|] s in
@@ -1007,7 +942,7 @@ let rec knr info m stk =
1007942
| (_,args,s) -> (m,args@s))
1008943
| FCoFix _ when red_set info.i_flags fIOTA ->
1009944
(match strip_update_shift_app m stk with
1010-
(_, args, ((Zcase _::_) as stk')) ->
945+
(_, args, (((Zcase _|ZcaseT _)::_) as stk')) ->
1011946
let (fxe,fxbd) = contract_fix_vect m.term in
1012947
knit info fxe fxbd (args@stk')
1013948
| (_,args,s) -> (m,args@s))
@@ -1039,6 +974,10 @@ let rec zip_term zfun m stk =
1039974
| Zcase(ci,p,br)::s ->
1040975
let t = mkCase(ci, zfun p, m, Array.map zfun br) in
1041976
zip_term zfun t s
977+
| ZcaseT(ci,p,br,e)::s ->
978+
let t = mkCase(ci, zfun (mk_clos e p), m,
979+
Array.map (fun b -> zfun (mk_clos e b)) br) in
980+
zip_term zfun t s
1042981
| Zproj(_,_,p)::s ->
1043982
let t = mkProj (Projection.make p true, m) in
1044983
zip_term zfun t s

kernel/closure.mli

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,8 @@ type fterm =
119119
| FProj of projection * fconstr
120120
| FFix of fixpoint * fconstr subs
121121
| FCoFix of cofixpoint * fconstr subs
122-
| FCases of case_info * fconstr * fconstr * fconstr array
122+
| FCase of case_info * fconstr * fconstr * fconstr array
123+
| FCaseT of case_info * constr * fconstr * constr array * fconstr subs (* predicate and branches are closures *)
123124
| FLambda of int * (Name.t * constr) list * constr * fconstr subs
124125
| FProd of Name.t * fconstr * fconstr
125126
| FLetIn of Name.t * fconstr * fconstr * constr * fconstr subs
@@ -136,6 +137,7 @@ type fterm =
136137
type stack_member =
137138
| Zapp of fconstr array
138139
| Zcase of case_info * fconstr * fconstr array
140+
| ZcaseT of case_info * constr * constr array * fconstr subs
139141
| Zproj of int * int * constant
140142
| Zfix of fconstr * stack
141143
| Zshift of int
@@ -228,6 +230,5 @@ val knr: clos_infos -> fconstr -> stack -> fconstr * stack
228230
val kl : clos_infos -> fconstr -> constr
229231

230232
val to_constr : (lift -> fconstr -> constr) -> lift -> fconstr -> constr
231-
val optimise_closure : fconstr subs -> constr -> fconstr subs * constr
232233

233234
(** End of cbn debug section i*)

kernel/reduction.ml

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ let compare_stack_shape stk1 stk2 =
6464
| (_, Zapp l2::s2) -> compare_rec (bal-Array.length l2) stk1 s2
6565
| (Zproj (n1,m1,p1)::s1, Zproj (n2,m2,p2)::s2) ->
6666
Int.equal bal 0 && compare_rec 0 s1 s2
67-
| (Zcase(c1,_,_)::s1, Zcase(c2,_,_)::s2) ->
67+
| ((Zcase(c1,_,_)|ZcaseT(c1,_,_,_))::s1,
68+
(Zcase(c2,_,_)|ZcaseT(c2,_,_,_))::s2) ->
6869
Int.equal bal 0 (* && c1.ci_ind = c2.ci_ind *) && compare_rec 0 s1 s2
6970
| (Zfix(_,a1)::s1, Zfix(_,a2)::s2) ->
7071
Int.equal bal 0 && compare_rec 0 a1 a2 && compare_rec 0 s1 s2
@@ -97,6 +98,8 @@ let pure_stack lfts stk =
9798
| (Zfix(fx,a),(l,pstk)) ->
9899
let (lfx,pa) = pure_rec l a in
99100
(l, Zlfix((lfx,fx),pa)::pstk)
101+
| (ZcaseT(ci,p,br,e),(l,pstk)) ->
102+
(l,Zlcase(ci,l,mk_clos e p,Array.map (mk_clos e) br)::pstk)
100103
| (Zcase(ci,p,br),(l,pstk)) ->
101104
(l,Zlcase(ci,l,p,br)::pstk)) in
102105
snd (pure_rec lfts stk)
@@ -243,6 +246,7 @@ let rec no_arg_available = function
243246
| Zapp v :: stk -> Int.equal (Array.length v) 0 && no_arg_available stk
244247
| Zproj _ :: _ -> true
245248
| Zcase _ :: _ -> true
249+
| ZcaseT _ :: _ -> true
246250
| Zfix _ :: _ -> true
247251

248252
let rec no_nth_arg_available n = function
@@ -255,6 +259,7 @@ let rec no_nth_arg_available n = function
255259
else false
256260
| Zproj _ :: _ -> true
257261
| Zcase _ :: _ -> true
262+
| ZcaseT _ :: _ -> true
258263
| Zfix _ :: _ -> true
259264

260265
let rec no_case_available = function
@@ -264,11 +269,13 @@ let rec no_case_available = function
264269
| Zapp _ :: stk -> no_case_available stk
265270
| Zproj (_,_,p) :: _ -> false
266271
| Zcase _ :: _ -> false
272+
| ZcaseT _ :: _ -> false
267273
| Zfix _ :: _ -> true
268274

269275
let in_whnf (t,stk) =
270276
match fterm_of t with
271-
| (FLetIn _ | FCases _ | FApp _ | FCLOS _ | FLIFT _ | FCast _) -> false
277+
| (FLetIn _ | FCase _ | FCaseT _ | FApp _
278+
| FCLOS _ | FLIFT _ | FCast _) -> false
272279
| FLambda _ -> no_arg_available stk
273280
| FConstruct _ -> no_case_available stk
274281
| FCoFix _ -> no_case_available stk
@@ -533,8 +540,8 @@ and eqappr cv_pb l2r infos (lft1,st1) (lft2,st2) cuniv =
533540
else raise NotConvertible
534541

535542
(* Should not happen because both (hd1,v1) and (hd2,v2) are in whnf *)
536-
| ( (FLetIn _, _) | (FCases _,_) | (FApp _,_) | (FCLOS _,_) | (FLIFT _,_)
537-
| (_, FLetIn _) | (_,FCases _) | (_,FApp _) | (_,FCLOS _) | (_,FLIFT _)
543+
| ( (FLetIn _, _) | (FCase _,_) | (FCaseT _,_) | (FApp _,_) | (FCLOS _,_) | (FLIFT _,_)
544+
| (_, FLetIn _) | (_,FCase _) | (_,FCaseT _) | (_,FApp _) | (_,FCLOS _) | (_,FLIFT _)
538545
| (FLOCKED,_) | (_,FLOCKED) ) -> assert false
539546

540547
(* In all other cases, terms are not convertible *)

0 commit comments

Comments
 (0)