diff options
author | barras <barras@85f007b7-540e-0410-9357-904b9bb8a0f7> | 2010-03-11 19:08:46 +0000 |
---|---|---|
committer | barras <barras@85f007b7-540e-0410-9357-904b9bb8a0f7> | 2010-03-11 19:08:46 +0000 |
commit | dba2ae9fa1eb01d795d36b209aee6045967ba00a (patch) | |
tree | e8c2ce9a5fb8f7a0150458d7a2a5a585ccdca2f9 /kernel | |
parent | 8a944fd93df07453cba53b752670ae451c370a65 (diff) |
introduced lazy computation of size info in the guard condition
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/coq/trunk@12862 85f007b7-540e-0410-9357-904b9bb8a0f7
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/inductive.ml | 71 | ||||
-rw-r--r-- | kernel/inductive.mli | 4 |
2 files changed, 43 insertions, 32 deletions
diff --git a/kernel/inductive.ml b/kernel/inductive.ml index 8b5649dfb..d806c39a0 100644 --- a/kernel/inductive.ml +++ b/kernel/inductive.ml @@ -418,14 +418,16 @@ type subterm_spec = | Dead_code | Not_subterm -let spec_of_tree t = - if Rtree.eq_rtree (=) t mk_norec then Not_subterm else Subterm(Strict,t) +let spec_of_tree t = lazy + (if Rtree.eq_rtree (=) (Lazy.force t) mk_norec + then Not_subterm + else Subterm(Strict,Lazy.force t)) let subterm_spec_glb = - let glb2 s1 s2 = - match s1,s2 with - _, Dead_code -> s1 - | Dead_code, _ -> s2 + let glb2 s1 s2 = + match s1, s2 with + s1, Dead_code -> s1 + | Dead_code, s2 -> s2 | Not_subterm, _ -> Not_subterm | _, Not_subterm -> Not_subterm | Subterm (a1,t1), Subterm (a2,t2) -> @@ -443,7 +445,7 @@ type guard_env = (* the recarg information of inductive family *) recvec : wf_paths array; (* dB of variables denoting subterms *) - genv : subterm_spec list; + genv : subterm_spec Lazy.t list; } let make_renv env minds recarg (kn,tyi) = @@ -454,7 +456,7 @@ let make_renv env minds recarg (kn,tyi) = rel_min = recarg+2; inds = minds; recvec = mind_recvec; - genv = [Subterm(Large,mind_recvec.(tyi))] } + genv = [Lazy.lazy_from_val(Subterm(Large,mind_recvec.(tyi)))] } let push_var renv (x,ty,spec) = { renv with @@ -466,11 +468,11 @@ let assign_var_spec renv (i,spec) = { renv with genv = list_assign renv.genv (i-1) spec } let push_var_renv renv (x,ty) = - push_var renv (x,ty,Not_subterm) + push_var renv (x,ty,lazy Not_subterm) (* Fetch recursive information about a variable p *) let subterm_var p renv = - try List.nth renv.genv (p-1) + try Lazy.force (List.nth renv.genv (p-1)) with Failure _ | Invalid_argument _ -> Not_subterm (* Add a variable and mark it as strictly smaller with information [spec]. *) @@ -482,14 +484,14 @@ let push_ctxt_renv renv ctxt = { renv with env = push_rel_context ctxt renv.env; rel_min = renv.rel_min+n; - genv = iterate (fun ge -> Not_subterm::ge) n renv.genv } + genv = iterate (fun ge -> lazy Not_subterm::ge) n renv.genv } let push_fix_renv renv (_,v,_ as recdef) = let n = Array.length v in { renv with env = push_rec_types recdef renv.env; rel_min = renv.rel_min+n; - genv = iterate (fun ge -> Not_subterm::ge) n renv.genv } + genv = iterate (fun ge -> lazy Not_subterm::ge) n renv.genv } (******************************) @@ -518,7 +520,8 @@ let lookup_subterms env ind = associated to its own subterms. Rq: if branch is not eta-long, then the recursive information is not propagated to the missing abstractions *) -let case_branches_specif renv c_spec ind lbr = +let case_branches_specif renv c_spec ci lbr = + let ind = ci.ci_ind in let rec push_branch_args renv lrec c = match lrec with ra::lr -> @@ -530,17 +533,21 @@ let case_branches_specif renv c_spec ind lbr = | _ -> (* branch not in eta-long form: cannot perform rec. calls *) (renv,c')) | [] -> (renv, c) in - match c_spec with - Subterm (_,t) -> - let sub_spec = Array.map (List.map spec_of_tree) (dest_subterms t) in - assert (Array.length sub_spec = Array.length lbr); - array_map2 (push_branch_args renv) sub_spec lbr - | Dead_code -> - let t = dest_subterms (lookup_subterms renv.env ind) in - let sub_spec = Array.map (List.map (fun _ -> Dead_code)) t in - assert (Array.length sub_spec = Array.length lbr); - array_map2 (push_branch_args renv) sub_spec lbr - | Not_subterm -> Array.map (fun c -> (renv,c)) lbr + + let sub_spec = + Array.mapi + (fun i nca -> (* i+1-th cstructor has arity nca *) + let cs = lazy + (match Lazy.force c_spec with + Subterm (_,t) -> + Array.map (fun t -> spec_of_tree (lazy t)) + (Array.of_list (dest_subterms t).(i)) + | Dead_code -> Array.create nca (lazy Dead_code) + | Not_subterm -> Array.create nca (lazy Not_subterm)) in + list_tabulate (fun j -> (Lazy.force cs).(j)) nca) + ci.ci_cstr_nargs in + assert (Array.length sub_spec = Array.length lbr); + array_map2 (push_branch_args renv) sub_spec lbr (* [subterm_specif renv t] computes the recursive structure of [t] and compare its size with the size of the initial recursive argument of @@ -582,7 +589,8 @@ let rec subterm_specif renv t = let renv' = (* Why Strict here ? To be general, it could also be Large... *) - assign_var_spec renv' (nbfix-i, Subterm(Strict,recargs)) in + assign_var_spec renv' + (nbfix-i, lazy (Subterm(Strict,recargs))) in let decrArg = recindxs.(i) in let theBody = bodies.(i) in let nbOfAbst = decrArg+1 in @@ -593,7 +601,7 @@ let rec subterm_specif renv t = if List.length l < nbOfAbst then renv'' else let theDecrArg = List.nth l decrArg in - let arg_spec = subterm_specif renv theDecrArg in + let arg_spec = lazy_subterm_specif renv theDecrArg in assign_var_spec renv'' (1, arg_spec) in subterm_specif renv'' strippedBody) @@ -607,11 +615,14 @@ let rec subterm_specif renv t = (* Other terms are not subterms *) | _ -> Not_subterm +and lazy_subterm_specif renv t = + lazy (subterm_specif renv t) + and case_subterm_specif renv ci c lbr = if Array.length lbr = 0 then [||] else - let c_spec = subterm_specif renv c in - case_branches_specif renv c_spec ci.ci_ind lbr + let c_spec = lazy_subterm_specif renv c in + case_branches_specif renv c_spec ci lbr (* Check term c can be applied to one of the mutual fixpoints. *) let check_is_subterm renv c = @@ -627,7 +638,7 @@ let error_illegal_rec_call renv fx arg = let (_,le_vars,lt_vars) = List.fold_left (fun (i,le,lt) sbt -> - match sbt with + match Lazy.force sbt with (Subterm(Strict,_) | Dead_code) -> (i+1, le, i::lt) | (Subterm(Large,_)) -> (i+1, i::le, lt) | _ -> (i+1, le ,lt)) @@ -709,7 +720,7 @@ let check_one_fix renv recpos def = (fun j body -> if i=j then let theDecrArg = List.nth l decrArg in - let arg_spec = subterm_specif renv theDecrArg in + let arg_spec = lazy_subterm_specif renv theDecrArg in check_nested_fix_body renv' (decrArg+1) arg_spec body else check_rec_call renv' body) bodies diff --git a/kernel/inductive.mli b/kernel/inductive.mli index 9f8d10900..8fe8eb11f 100644 --- a/kernel/inductive.mli +++ b/kernel/inductive.mli @@ -109,9 +109,9 @@ type guard_env = (* the recarg information of inductive family *) recvec : wf_paths array; (* dB of variables denoting subterms *) - genv : subterm_spec list; + genv : subterm_spec Lazy.t list; } val subterm_specif : guard_env -> constr -> subterm_spec -val case_branches_specif : guard_env -> subterm_spec -> inductive -> +val case_branches_specif : guard_env -> subterm_spec Lazy.t -> case_info -> constr array -> (guard_env * constr) array |