aboutsummaryrefslogtreecommitdiffhomepage
path: root/interp/constrextern.ml
diff options
context:
space:
mode:
Diffstat (limited to 'interp/constrextern.ml')
-rw-r--r--interp/constrextern.ml360
1 files changed, 360 insertions, 0 deletions
diff --git a/interp/constrextern.ml b/interp/constrextern.ml
new file mode 100644
index 000000000..b9f22ff00
--- /dev/null
+++ b/interp/constrextern.ml
@@ -0,0 +1,360 @@
+(***********************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * INRIA-Rocquencourt & LRI-CNRS-Orsay *)
+(* \VV/ *************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(*i*)
+open Pp
+open Util
+open Univ
+open Names
+open Nameops
+open Term
+open Termops
+open Inductive
+open Sign
+open Environ
+open Libnames
+open Declare
+open Impargs
+open Topconstr
+open Rawterm
+open Pattern
+open Nametab
+(*i*)
+
+(* Translation from rawconstr to front constr *)
+
+(**********************************************************************)
+(* Parametrization *)
+
+(* This governs printing of local context of references *)
+let print_arguments = ref false
+
+(* If true, prints local context of evars, whatever print_arguments *)
+let print_evar_arguments = ref false
+
+(* This forces printing of cast nodes *)
+let print_casts = ref true
+
+(* This governs printing of implicit arguments. When
+ [print_implicits] is on then [print_implicits_explicit_args] tells
+ how implicit args are printed. If on, implicit args are printed
+ prefixed by "!" otherwise the function and not the arguments is
+ prefixed by "!" *)
+let print_implicits = ref false
+let print_implicits_explicit_args = ref false
+
+(* This forces printing of coercions *)
+let print_coercions = ref false
+
+(* This forces printing universe names of Type{.} *)
+let print_universes = ref false
+
+
+let with_option o f x =
+ let old = !o in o:=true;
+ try let r = f x in o := old; r
+ with e -> o := old; raise e
+
+let with_arguments f = with_option print_arguments f
+let with_casts f = with_option print_casts f
+let with_implicits f = with_option print_implicits f
+let with_coercions f = with_option print_coercions f
+let with_universes f = with_option print_universes f
+
+(**********************************************************************)
+(* conversion of references *)
+
+let ids_of_ctxt ctxt =
+ Array.to_list
+ (Array.map
+ (function c -> match kind_of_term c with
+ | Var id -> id
+ | _ ->
+ error
+ "Termast: arbitrary substitution of references not yet implemented")
+ ctxt)
+
+let idopt_of_name = function
+ | Name id -> Some id
+ | Anonymous -> None
+
+let extern_evar loc n = warning "No notation for Meta"; CMeta (loc,n)
+
+let extern_ref r = Qualid (dummy_loc,shortest_qualid_of_global None r)
+
+(**********************************************************************)
+(* conversion of patterns *)
+
+let rec extern_cases_pattern = function (* loc is thrown away for printing *)
+ | PatVar (loc,Name id) -> CPatAtom (loc,Some (Ident (loc,id)))
+ | PatVar (loc,Anonymous) -> CPatAtom (loc, None)
+ | PatCstr(loc,cstrsp,args,na) ->
+ let args = List.map extern_cases_pattern args in
+ let p = CPatCstr (loc,extern_ref (ConstructRef cstrsp),args) in
+ (match na with
+ | Name id -> CPatAlias (loc,p,id)
+ | Anonymous -> p)
+
+let occur_name na aty =
+ match na with
+ | Name id -> occur_var_constr_expr id aty
+ | Anonymous -> false
+
+(* Implicit args indexes are in ascending order *)
+let explicitize impl f args =
+ let n = List.length args in
+ let rec exprec q = function
+ | a::args, imp::impl when is_status_implicit imp ->
+ let tail = exprec (q+1) (args,impl) in
+ let visible =
+ (!print_implicits & !print_implicits_explicit_args)
+ or not (is_inferable_implicit n imp) in
+ if visible then (a,Some q) :: tail else tail
+ | a::args, _::impl -> (a,None) :: exprec (q+1) (args,impl)
+ | args, [] -> List.map (fun a -> (a,None)) args (*In case of polymorphism*)
+ | [], _ -> [] in
+ let args = exprec 1 (args,impl) in
+ if args = [] then f else CApp (dummy_loc, f, args)
+
+let rec skip_coercion dest_ref (f,args as app) =
+ if !print_coercions then app
+ else
+ try
+ match dest_ref f with
+ | Some r ->
+ (match Classops.hide_coercion r with
+ | Some n ->
+ if n >= List.length args then app
+ else (* We skip a coercion *)
+ let _,fargs = list_chop n args in
+ skip_coercion dest_ref (List.hd fargs,List.tl fargs)
+ | None -> app)
+ | None -> app
+ with Not_found -> app
+
+let extern_app impl f args =
+ if !print_implicits & not !print_implicits_explicit_args then
+ CAppExpl (dummy_loc, f, args)
+ else
+ explicitize impl (CRef f) args
+
+let loc = dummy_loc
+
+let rec extern = function
+ | RRef (_,ref) -> CRef (extern_ref ref)
+
+ | RVar (_,id) -> CRef (Ident (loc,id))
+
+ | REvar (_,n) -> extern_evar loc n
+
+ | RMeta (_,n) -> CMeta (loc,n)
+
+ | RApp (_,f,args) ->
+ let (f,args) =
+ skip_coercion (function RRef(_,r) -> Some r | _ -> None) (f,args) in
+ let args = List.map extern args in
+ (match f with
+ | REvar (loc,ev) -> extern_evar loc ev (* we drop args *)
+ | RRef (loc,ref) ->
+ extern_app (implicits_of_global ref) (extern_ref ref) args
+ | _ -> explicitize [] (extern f) args)
+
+ | RProd (_,Anonymous,t,c) ->
+ (* Anonymous product are never factorized *)
+ CArrow (loc,extern t,extern c)
+
+ | RLetIn (_,na,t,c) ->
+ CLetIn (loc,(loc,na),extern t,extern c)
+
+ | RProd (_,na,t,c) ->
+ let t = extern t in
+ let (idl,c) = factorize_prod t c in
+ CProdN (loc,[(loc,na)::idl,t],c)
+
+ | RLambda (_,na,t,c) ->
+ let t = extern t in
+ let (idl,c) = factorize_lambda t c in
+ CLambdaN (loc,[(loc,na)::idl,t],c)
+
+ | RCases (_,typopt,tml,eqns) ->
+ let pred = option_app extern typopt in
+ let tml = List.map extern tml in
+ let eqns = List.map extern_eqn eqns in
+ CCases (loc,pred,tml,eqns)
+
+ | ROrderedCase (_,cs,typopt,tm,bv) ->
+ let bv = Array.to_list (Array.map extern bv) in
+ COrderedCase (loc,cs,option_app extern typopt,extern tm,bv)
+
+ | RRec (_,fk,idv,tyv,bv) ->
+ (match fk with
+ | RFix (nv,n) ->
+ let rec split_lambda binds = function
+ | (0, t) -> (List.rev binds,extern t)
+ | (n, RLambda (_,na,t,b)) ->
+ split_lambda (([loc,na],extern t)::binds) (n-1,b)
+ | _ -> anomaly "extern: ill-formed fixpoint body" in
+ let rec split_product = function
+ | (0, t) -> extern t
+ | (n, RProd (_,na,t,b)) -> split_product (n-1,b)
+ | _ -> anomaly "extern: ill-formed fixpoint type" in
+ let listdecl =
+ Array.mapi
+ (fun i fi ->
+ let (lparams,def) = split_lambda [] (nv.(i)+1,bv.(i)) in
+ let typ = split_product (nv.(i)+1,tyv.(i)) in
+ (fi, lparams, typ, def))
+ idv
+ in
+ CFix (loc,(loc,idv.(n)),Array.to_list listdecl)
+ | RCoFix n ->
+ let listdecl =
+ Array.mapi (fun i fi -> (fi,extern tyv.(i),extern bv.(i))) idv
+ in
+ CCoFix (loc,(loc,idv.(n)),Array.to_list listdecl))
+
+ | RSort (_,s) ->
+ let s = match s with
+ | RProp _ -> s
+ | RType (Some _) when !print_universes -> s
+ | RType _ -> RType None in
+ CSort (loc,s)
+
+ | RHole (_,e) -> CHole loc
+
+ | RCast (_,c,t) -> CCast (loc,extern c,extern t)
+
+ | RDynamic (_,d) -> CDynamic (loc,d)
+
+and factorize_prod aty = function
+ | RProd (_,Name id,ty,c)
+ when aty = extern ty
+ & not (occur_var_constr_expr id aty) (*To avoid na in ty escapes scope*)
+ -> let (nal,c) = factorize_prod aty c in ((loc,Name id)::nal,c)
+ | c -> ([],extern c)
+
+and factorize_lambda aty = function
+ | RLambda (_,na,ty,c)
+ when aty = extern ty
+ & not (occur_name na aty) (* To avoid na in ty' escapes scope *)
+ -> let (nal,c) = factorize_lambda aty c in ((loc,na)::nal,c)
+ | c -> ([],extern c)
+
+and extern_eqn (loc,ids,pl,c) =
+ (loc,List.map extern_cases_pattern pl,extern c)
+(*
+and extern_numerals r =
+ on_numeral (fun p ->
+ match filter p r with
+ | Some f
+
+and extern_symbols r =
+*)
+
+let extern_rawconstr = extern
+
+(******************************************************************)
+(* Main translation function from constr -> constr_expr *)
+
+let extern_constr at_top env t =
+ let t' =
+ if !print_casts then t
+ else Reductionops.local_strong strip_outer_cast t in
+ let avoid = if at_top then ids_of_context env else [] in
+ extern (Detyping.detype env avoid (names_of_rel_context env) t')
+
+(******************************************************************)
+(* Main translation function from pattern -> constr_expr *)
+
+let rec extern_pattern tenv env = function
+ | PRef ref -> CRef (extern_ref ref)
+
+ | PVar id -> CRef (Ident (loc,id))
+
+ | PEvar n -> extern_evar loc n
+
+ | PRel n ->
+ CRef (Ident (loc,
+ try match lookup_name_of_rel n env with
+ | Name id -> id
+ | Anonymous ->
+ anomaly "ast_of_pattern: index to an anonymous variable"
+ with Not_found ->
+ id_of_string ("[REL "^(string_of_int n)^"]")))
+
+ | PMeta None -> CHole loc
+
+ | PMeta (Some n) -> CMeta (loc,n)
+
+ | PApp (f,args) ->
+ let (f,args) =
+ skip_coercion (function PRef r -> Some r | _ -> None)
+ (f,Array.to_list args) in
+ let args = List.map (extern_pattern tenv env) args in
+ (match f with
+ | PRef ref ->
+ extern_app (implicits_of_global ref) (extern_ref ref) args
+ | _ -> explicitize [] (extern_pattern tenv env f) args)
+
+ | PSoApp (n,args) ->
+ let args = List.map (extern_pattern tenv env) args in
+ (* [-n] is the trick to embed a so patten into a regular application *)
+ (* see constrintern.ml and g_constr.ml4 *)
+ explicitize [] (CMeta (loc,-n)) args
+
+ | PProd (Anonymous,t,c) ->
+ (* Anonymous product are never factorized *)
+ CArrow (loc,extern_pattern tenv env t,extern_pattern tenv env c)
+
+ | PLetIn (na,t,c) ->
+ CLetIn (loc,(loc,na),extern_pattern tenv env t,extern_pattern tenv env c)
+
+ | PProd (na,t,c) ->
+ let t = extern_pattern tenv env t in
+ let (idl,c) = factorize_prod_pattern tenv (add_name na env) t c in
+ CProdN (loc,[(loc,na)::idl,t],c)
+
+ | PLambda (na,t,c) ->
+ let t = extern_pattern tenv env t in
+ let (idl,c) = factorize_lambda_pattern tenv (add_name na env) t c in
+ CLambdaN (loc,[(loc,na)::idl,t],c)
+
+ | PCase (cs,typopt,tm,bv) ->
+ let bv = Array.to_list (Array.map (extern_pattern tenv env) bv) in
+ COrderedCase
+ (loc,cs,option_app (extern_pattern tenv env) typopt,
+ extern_pattern tenv env tm,bv)
+
+ | PFix f -> extern (Detyping.detype tenv [] env (mkFix f))
+
+ | PCoFix c -> extern (Detyping.detype tenv [] env (mkCoFix c))
+
+ | PSort s ->
+ let s = match s with
+ | RProp _ -> s
+ | RType (Some _) when !print_universes -> s
+ | RType _ -> RType None in
+ CSort (loc,s)
+
+and factorize_prod_pattern tenv env aty = function
+ | PProd (Name id as na,ty,c)
+ when aty = extern_pattern tenv env ty
+ & not (occur_var_constr_expr id aty) (*To avoid na in ty escapes scope*)
+ -> let (nal,c) = factorize_prod_pattern tenv (na::env) aty c in
+ ((loc,Name id)::nal,c)
+ | c -> ([],extern_pattern tenv env c)
+
+and factorize_lambda_pattern tenv env aty = function
+ | PLambda (na,ty,c)
+ when aty = extern_pattern tenv env ty
+ & not (occur_name na aty) (* To avoid na in ty' escapes scope *)
+ -> let (nal,c) = factorize_lambda_pattern tenv (add_name na env) aty c
+ in ((loc,na)::nal,c)
+ | c -> ([],extern_pattern tenv env c)