(* identity_relocation_list_for_metavariable i canonical_context *) (* returns the identity relocation list, which is the list [1 ; ... ; n] *) (* where n = List.length [canonical_context] *) (*CSC: ma mi basta la lunghezza del contesto canonico!!!*) let identity_relocation_list_for_metavariable canonical_context = let canonical_context_length = List.length canonical_context in let rec aux = function (_,[]) -> [] | (n,None::tl) -> None::(aux ((n+1),tl)) | (n,_::tl) -> (Some (Cic.Rel n))::(aux ((n+1),tl)) in aux (1,canonical_context) (* Returns the first meta whose number is above the *) (* number of the higher meta. *) let new_meta metasenv = let rec aux = function None,[] -> 1 | Some n,[] -> n | None,(n,_,_)::tl -> aux (Some n,tl) | Some m,(n,_,_)::tl -> if n > m then aux (Some n,tl) else aux (Some m,tl) in 1 + aux (None,metasenv) let mk_implicit metasenv context = let newmeta = new_meta metasenv in let irl = identity_relocation_list_for_metavariable context in ([ newmeta, context, Cic.Sort Cic.Type ; newmeta + 1, context, Cic.Meta (newmeta, irl); newmeta + 2, context, Cic.Meta (newmeta + 1,irl) ] @ metasenv, newmeta + 2) let n_fresh_metas metasenv context n = if n = 0 then metasenv, [] else let irl = identity_relocation_list_for_metavariable context in let newmeta = new_meta metasenv in let rec aux newmeta n = if n = 0 then metasenv, [] else let metasenv', l = aux (newmeta + 3) (n-1) in (newmeta, context, Cic.Sort Cic.Type):: (newmeta + 1, context, Cic.Meta (newmeta, irl)):: (newmeta + 2, context, Cic.Meta (newmeta + 1,irl))::metasenv', Cic.Meta(newmeta+2,irl)::l in aux newmeta n let fresh_subst metasenv context uris = let irl = identity_relocation_list_for_metavariable context in let newmeta = new_meta metasenv in let rec aux newmeta = function [] -> metasenv, [] | uri::tl -> let metasenv', l = aux (newmeta + 3) tl in (newmeta, context, Cic.Sort Cic.Type):: (newmeta + 1, context, Cic.Meta (newmeta, irl)):: (newmeta + 2, context, Cic.Meta (newmeta + 1,irl))::metasenv', (uri,Cic.Meta(newmeta+2,irl))::l in aux newmeta uris let mk_implicit' metasenv context = let (metasenv, index) = mk_implicit metasenv context in (metasenv, index - 1, index) let mk_implicit_type metasenv context = let newmeta = new_meta metasenv in let irl = identity_relocation_list_for_metavariable context in ([ newmeta, context, Cic.Sort Cic.Type ; newmeta + 1, context, Cic.Meta (newmeta, irl) ] @metasenv, newmeta + 1) let expand_implicits metasenv context term = let rec aux metasenv context = function | (Cic.Rel _) as t -> metasenv, t | (Cic.Sort _) as t -> metasenv, t | Cic.Const (uri, subst) -> let metasenv', subst' = do_subst metasenv context subst in metasenv', Cic.Const (uri, subst') | Cic.Var (uri, subst) -> let metasenv', subst' = do_subst metasenv context subst in metasenv', Cic.Var (uri, subst') | Cic.MutInd (uri, i, subst) -> let metasenv', subst' = do_subst metasenv context subst in metasenv', Cic.MutInd (uri, i, subst') | Cic.MutConstruct (uri, i, j, subst) -> let metasenv', subst' = do_subst metasenv context subst in metasenv', Cic.MutConstruct (uri, i, j, subst') | Cic.Meta (n,l) -> let metasenv', l' = do_local_context metasenv context l in metasenv', Cic.Meta (n, l') | Cic.Implicit -> let (metasenv', type_index, _) = mk_implicit' metasenv context in let irl = identity_relocation_list_for_metavariable context in metasenv', Cic.Meta (type_index, irl) | Cic.Cast (te, ty) -> let metasenv', ty' = aux metasenv context ty in let metasenv'', te' = aux metasenv' context te in metasenv'', Cic.Cast (te', ty') | Cic.Prod (name, s, t) -> let metasenv', s' = aux metasenv context s in let metasenv'', t' = aux metasenv' (Some (name, Cic.Decl s') :: context) t in metasenv'', Cic.Prod (name, s', t') | Cic.Lambda (name, s, t) -> let metasenv', s' = aux metasenv context s in let metasenv'', t' = aux metasenv' (Some (name, Cic.Decl s') :: context) t in metasenv'', Cic.Lambda (name, s', t') | Cic.LetIn (name, s, t) -> let metasenv', s' = aux metasenv context s in let metasenv'', t' = aux metasenv' (Some (name, Cic.Def (s', None)) :: context) t in metasenv'', Cic.LetIn (name, s', t') | Cic.Appl l when List.length l > 1 -> let metasenv', l' = List.fold_right (fun term (metasenv, terms) -> let new_metasenv, term = aux metasenv context term in new_metasenv, term :: terms) l (metasenv, []) in metasenv', Cic.Appl l' | Cic.Appl _ -> assert false | Cic.MutCase (uri, i, outtype, term, patterns) -> let metasenv', l' = List.fold_right (fun term (metasenv, terms) -> let new_metasenv, term = aux metasenv context term in new_metasenv, term :: terms) (outtype :: term :: patterns) (metasenv, []) in let outtype', term', patterns' = match l' with | outtype' :: term' :: patterns' -> outtype', term', patterns' | _ -> assert false in metasenv', Cic.MutCase (uri, i, outtype', term', patterns') | Cic.Fix (i, funs) -> let metasenv', types = List.fold_right (fun (name, _, typ, _) (metasenv, types) -> let new_metasenv, new_type = aux metasenv context typ in (new_metasenv, (name, new_type) :: types)) funs (metasenv, []) in let context' = (List.rev_map (fun (name, t) -> Some (Cic.Name name, Cic.Decl t)) types) @ context in let metasenv'', bodies = List.fold_right (fun (_, _, _, body) (metasenv, bodies) -> let new_metasenv, new_body = aux metasenv context' body in (new_metasenv, new_body :: bodies)) funs (metasenv', []) in let rec combine = function | ((name, index, _, _) :: funs_tl), ((_, typ) :: typ_tl), (body :: body_tl) -> (name, index, typ, term) :: combine (funs_tl, typ_tl, body_tl) | [], [], [] -> [] | _ -> assert false in let funs' = combine (funs, types, bodies) in metasenv'', Cic.Fix (i, funs') | Cic.CoFix (i, funs) -> let metasenv', types = List.fold_right (fun (name, typ, _) (metasenv, types) -> let new_metasenv, new_type = aux metasenv context typ in (new_metasenv, (name, new_type) :: types)) funs (metasenv, []) in let context' = (List.rev_map (fun (name, t) -> Some (Cic.Name name, Cic.Decl t)) types) @ context in let metasenv'', bodies = List.fold_right (fun (_, _, body) (metasenv, bodies) -> let new_metasenv, new_body = aux metasenv context' body in (new_metasenv, new_body :: bodies)) funs (metasenv', []) in let rec combine = function | ((name, _, _) :: funs_tl), ((_, typ) :: typ_tl), (body :: body_tl) -> (name, typ, term) :: combine (funs_tl, typ_tl, body_tl) | [], [], [] -> [] | _ -> assert false in let funs' = combine (funs, types, bodies) in metasenv'', Cic.CoFix (i, funs') and do_subst metasenv context subst = List.fold_right (fun (uri, term) (metasenv, substs) -> let metasenv', term' = aux metasenv context term in (metasenv', (uri, term') :: substs)) subst (metasenv, []) and do_local_context metasenv context local_context = List.fold_right (fun term (metasenv, local_context) -> let metasenv', term' = match term with | None -> metasenv, None | Some term -> let metasenv', term' = aux metasenv context term in metasenv', Some term' in metasenv', term' :: local_context) local_context (metasenv, []) in aux metasenv context term