aboutsummaryrefslogtreecommitdiffhomepage
path: root/contrib/subtac/infer.ml
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/subtac/infer.ml')
-rw-r--r--contrib/subtac/infer.ml827
1 files changed, 827 insertions, 0 deletions
diff --git a/contrib/subtac/infer.ml b/contrib/subtac/infer.ml
new file mode 100644
index 000000000..dcca9361a
--- /dev/null
+++ b/contrib/subtac/infer.ml
@@ -0,0 +1,827 @@
+open Natural
+open Names
+open Term
+open Rawterm
+open Util
+open Sast
+open Scoq
+open Pp
+open Ppconstrnew
+
+let ($) f g = fun x -> f (g x)
+
+let app_option f default = function Some x -> f x | None -> default
+
+let concat_map f l =
+ let rec aux accu = function
+ [] -> List.rev accu
+ | hd :: tl ->
+ aux (f hd @ accu) tl
+ in aux [] l
+
+let unique l =
+ let l' = List.sort Pervasives.compare l in
+ let rec aux accu = function
+ [] -> List.rev accu
+ | x :: (y :: _) as tl when x = y ->
+ aux accu tl
+ | hd :: tl ->
+ aux (hd :: accu) tl
+ in aux [] l'
+
+type term_pp = Pp.std_ppcmds
+
+type subtyping_error =
+ | UncoercibleInferType of loc * term_pp * term_pp
+ | UncoercibleInferTerm of loc * term_pp * term_pp * term_pp * term_pp
+ | UncoercibleRewrite of term_pp * term_pp
+
+type typing_error =
+ | NonFunctionalApp of loc * term_pp * term_pp
+ | NonConvertible of loc * term_pp * term_pp
+ | NonSigma of loc * term_pp
+
+exception Subtyping_error of subtyping_error
+exception Typing_error of typing_error
+
+exception Debug_msg of string
+
+let typing_error e = raise (Typing_error e)
+let subtyping_error e = raise (Subtyping_error e)
+
+type sort = Term.sorts
+type sort_loc = sort located
+
+(* Decorated terms *)
+type dterm =
+ DRel of nat
+ | DLambda of (name located * dtype_loc) * dterm_loc * dtype_loc
+ | DApp of dterm_loc * dterm_loc * dtype_loc
+ | DLetIn of (name located) * dterm_loc * dterm_loc * dtype_loc
+ | DLetTuple of (name located * dtype_loc * dtype_loc) list * dterm_loc * dterm_loc * dtype_loc
+ | DIfThenElse of dterm_loc * dterm_loc * dterm_loc * dtype_loc
+ | DSum of ((name located) * dterm_loc) * (dterm_loc * dtype_loc) * dtype_loc
+ | DCoq of constr * dtype_loc
+and dterm_loc = dterm located
+and dtype =
+ | DTApp of dtype_loc * dtype_loc * dtype_loc * sort_loc
+ | DTPi of (name located * dtype_loc) * dtype_loc * sort_loc
+ | DTSigma of (name located * dtype_loc) * dtype_loc * sort_loc
+ | DTSubset of (identifier located * dtype_loc) * dtype_loc * sort_loc
+ | DTRel of nat
+ | DTTerm of dterm_loc * dtype_loc * sort_loc
+ | DTSort of sort_loc
+ | DTInd of (identifier located) * dtype_loc * inductive * sort_loc
+ | DTCoq of types * dtype_loc * sort_loc
+and dtype_loc = dtype located
+
+let print_name = function
+ Name s -> str (string_of_id s)
+ | Anonymous -> str "_"
+
+let print_name_loc (_, n) = print_name n
+
+let string_of_list l =
+ let rec aux = function
+ hd :: ((_ :: _) as tl) ->
+ hd ++ str "," ++ aux tl
+ | hd :: [] -> hd
+ | [] -> mt()
+ in aux l
+
+type context = (name * dtype_loc) list
+
+let print_dtype_locref : (context -> dtype_loc -> std_ppcmds) ref =
+ ref (fun ctx t -> mt())
+
+let print_context ctx =
+ let cmds, _ =
+ List.fold_right
+ (fun (x, t) (acc, ctx) ->
+ let xpr = print_name x ++ str " : " ++ !print_dtype_locref ctx t in
+ (xpr :: acc), ((x, t) :: ctx))
+ ctx ([], [])
+ in string_of_list cmds
+
+let type_of_rel ctx n =
+ try snd (List.nth ctx n)
+ with e ->
+ debug 3 (str "Error in type_of_rel, searching for index " ++ str (string_of_int n)
+ ++ str " in context " ++ print_context ctx ++ str ": " ++
+ str (Printexc.to_string e));
+ raise e
+
+let name_of_rel ctx n =
+ try fst (List.nth ctx n)
+ with e ->
+ debug 3 (str "Error in name_of_rel, searching for index " ++ str (string_of_int n)
+ ++ str " in context " ++ print_context ctx ++ str ": " ++
+ str (Printexc.to_string e));
+ raise e
+
+let rec sort_of_dtype ctx = function
+ | DTApp (_, _, _, x)
+ | DTPi (_, _, x)
+ | DTSigma (_, _, x)
+ | DTSubset (_, _, x)
+ | DTTerm (_, _, x)
+ | DTSort x
+ | DTInd (_, _, _, x)
+ | DTCoq (_, _, x) -> x
+ | DTRel i -> sort_of_dtype_loc ctx (type_of_rel ctx i)
+
+and sort_of_dtype_loc ctx (_, t) = sort_of_dtype ctx t
+
+let rec no_var n (loc, t) =
+ match t with
+ | DTApp (x, y, t, _) -> (no_var n x) && (no_var n y)
+ | DTPi ((_, x), y, _) -> (no_var n x) && (no_var (succ n) y)
+ | DTSigma ((_, x), y, _) -> (no_var n x) && (no_var (succ n) y)
+ | DTSubset ((_, x), y, _) -> (no_var n x) && (no_var (succ n) y)
+ | DTRel i when i <> n -> false
+ | x -> true
+
+
+let rec lift_rec n k (loc, t) =
+ let t' =
+ match t with
+ | DTApp (x, y, t, s) -> DTApp (lift_rec n k x, lift_rec n k y,
+ lift_rec n k t, s)
+ | DTPi ((id, x), y, s) ->
+ DTPi ((id, lift_rec n k x), lift_rec n (succ k) y, s)
+ | DTSigma ((id, x), y, s) ->
+ DTSigma ((id, lift_rec n k x), lift_rec n (succ k) y, s)
+ | DTSubset ((id, x), y, s) ->
+ DTSubset ((id, lift_rec n k x), lift_rec n (succ k) y, s)
+ | (DTRel i) as x ->
+ if i < k then x else DTRel (n + i)
+ | DTTerm (t, tt, s) -> DTTerm (lift_term_rec n k t, lift_rec n k tt, s)
+ | DTCoq (c, t, s) -> DTCoq (Term.liftn n k c, lift_rec n k t, s)
+ | DTSort _
+ | DTInd _ -> t
+ in loc, t'
+
+and lift_term_rec n k (loc, s) =
+ let s' =
+ match s with
+ DRel i ->
+ if i < k then s else DRel (n + i)
+ | DLambda ((nl, dt), dt', dtlam) ->
+ DLambda ((nl, lift_rec n k dt), lift_term_rec n (succ k) dt',
+ lift_rec n k dtlam)
+ | DApp (dte, dte', dt) ->
+ DApp (lift_term_rec n k dte, lift_term_rec n k dte', lift_rec n k dt)
+ | DLetIn (nl, dte, dte', dt) ->
+ DLetIn (nl, lift_term_rec n k dte, lift_term_rec n (succ k) dte',
+ lift_rec n k dt)
+ | DLetTuple (nl, dte, dte', dt) ->
+ DLetTuple (nl, lift_term_rec n k dte,
+ lift_term_rec n (List.length nl + k) dte',
+ lift_rec n k dt)
+ | DIfThenElse (db, de, de', dt) ->
+ DIfThenElse (lift_term_rec n k db, lift_term_rec n k de,
+ lift_term_rec n k de', lift_rec n k dt)
+ | DSum ((x, tx), (ty, dty), dt) ->
+ DSum ((x, lift_term_rec n k tx),
+ (lift_term_rec n (succ k) ty, lift_rec n (succ k) dty),
+ lift_rec n k dt)
+ | DCoq (c, t) -> DCoq (Term.liftn n k c, lift_rec n k t)
+ in loc, s'
+
+let lift n t = lift_rec n 0 t
+let lift_term n t = lift_term_rec n 0 t
+
+let rec unlift_rec n k (loc, t) =
+ let t' =
+ match t with
+ | DTApp (x, y, t, s) -> DTApp (unlift_rec n k x, unlift_rec n k y, unlift_rec n k t, s)
+ | DTPi ((id, x), y, s) ->
+ DTPi ((id, unlift_rec n k x), unlift_rec n (succ k) y, s)
+ | DTSigma ((id, x), y, s) ->
+ DTSigma ((id, unlift_rec n k x), unlift_rec n (succ k) y, s)
+ | DTSubset ((id, x), y, s) ->
+ DTSubset ((id, unlift_rec n k x), unlift_rec n (succ k) y, s)
+ | (DTRel i) as x ->
+ if i < k then x else DTRel (i - n)
+ | DTTerm (t, tt, s) -> DTTerm (unlift_term_rec n k t, unlift_rec n k tt, s)
+ | DTCoq (c, t, s) -> DTCoq (c, unlift_rec n k t, s)
+ | DTSort _
+ | DTInd _ -> t
+ in loc, t'
+
+and unlift_term_rec n k (loc, s) =
+ let s' =
+ match s with
+ DRel i ->
+ if i < k then s else DRel (i - n)
+ | DLambda ((nl, dt), dt', dtlam) ->
+ DLambda ((nl, unlift_rec n k dt), unlift_term_rec n (succ k) dt',
+ unlift_rec n k dtlam)
+ | DApp (dte, dte', dt) ->
+ DApp (unlift_term_rec n k dte, unlift_term_rec n k dte', unlift_rec n k dt)
+ | DLetIn (nl, dte, dte', dt) ->
+ DLetIn (nl, unlift_term_rec n k dte, unlift_term_rec n (succ k) dte',
+ unlift_rec n k dt)
+ | DLetTuple (nl, dte, dte', dt) ->
+ DLetTuple (nl, unlift_term_rec n k dte,
+ unlift_term_rec n (List.length nl + k) dte',
+ unlift_rec n k dt)
+ | DIfThenElse (db, de, de', dt) ->
+ DIfThenElse (unlift_term_rec n k db, unlift_term_rec n k de,
+ unlift_term_rec n k de', unlift_rec n k dt)
+ | DSum ((x, tx), (ty, dty), dt) ->
+ DSum ((x, unlift_term_rec n k tx),
+ (unlift_term_rec n k ty, unlift_rec n k dty),
+ unlift_rec n k dt)
+ | DCoq (c, t) -> DCoq (c, unlift_rec n k t)
+ in loc, s'
+
+let unlift n t = unlift_rec n 0 t
+
+let rec type_of_dterm ctx t =
+ match t with
+ DRel (i) ->
+ (try let t = type_of_rel ctx i in lift (succ i) t
+ with e -> debug 3 (str "Couldn't find type of rel in type_of_dterm");
+ raise e)
+ | DLambda (_, _, dt) -> dt
+ | DApp (dte, dte', dt) -> dt
+ | DLetIn (nl, dte, dte', dt) -> dt
+ | DLetTuple (nl, dte, dte', dt) -> dt
+ | DIfThenElse (db, de, de', dt) -> dt
+ | DSum (_, _, dt) -> dt
+ | DCoq (_, dt) -> dt
+
+let type_of_dterm_loc ctx (_, t) = type_of_dterm ctx t
+
+let rec subst_term_type_rec (loc, s) t k =
+ let s' =
+ match s with
+ DRel i ->
+ if k < i then DRel (pred i)
+ else if k = i then
+ match snd (lift_rec k 0 t) with
+ DTRel i -> DRel i
+ | DTTerm (t, _, _) -> snd t
+ | _ -> failwith ("Substitution of a type in a term")
+ else (* k > i *) s
+ | DLambda ((ln, dt), e, t') ->
+ DLambda ((ln, subst_rec dt t k), subst_term_type_rec e t (succ k),
+ subst_rec t' t k)
+ | DApp (x, y, ta) ->
+ DApp (subst_term_type_rec x t k, subst_term_type_rec y t k, subst_rec ta t k)
+ | DLetIn (nl, e, e', t') ->
+ DLetIn (nl, subst_term_type_rec e t k, subst_term_type_rec e' t (succ k),
+ subst_rec t' t k)
+ | DLetTuple (nl, e, e', t') ->
+ DLetTuple (nl, subst_term_type_rec e t k, subst_term_type_rec e' t (k + List.length nl),
+ subst_rec t' t k)
+ | DIfThenElse (b, e, e', t') ->
+ DIfThenElse (subst_term_type_rec b t k, subst_term_type_rec e t k,
+ subst_term_type_rec e' t k, subst_rec t' t k)
+ | DSum ((nl, dt), (dt', tt'), t') ->
+ DSum ((nl, subst_term_type_rec dt t k),
+ (subst_term_type_rec dt' t (succ k), subst_rec tt' t (succ k)),
+ subst_rec t' t k)
+ | DCoq (c, dt) -> DCoq (c, subst_rec dt t k)
+ in loc, s'
+
+and subst_term_rec (loc, s) t k =
+ let ttype =
+ let dtype = type_of_dterm [] (snd t) in
+ (dummy_loc, (DTTerm (t, dtype, sort_of_dtype_loc [] dtype)))
+ in
+ let s' =
+ match s with
+ DRel i ->
+ if k < i then DRel (pred i)
+ else if k = i then snd (lift_term_rec k 0 t)
+ else (* k > i *) s
+ | DLambda ((ln, dt), e, t') ->
+ (* !!! *)
+ DLambda ((ln, subst_rec dt ttype k),
+ subst_term_rec e t (succ k), subst_rec t' ttype k)
+ | DApp (x, y, ta) ->
+ DApp (subst_term_rec x t k, subst_term_rec y t k, subst_rec ta ttype k)
+ | DLetIn (nl, e, e', t') ->
+ DLetIn (nl, subst_term_rec e t k, subst_term_rec e' t (succ k),
+ subst_rec t' ttype k)
+ | DLetTuple (nl, e, e', t') ->
+ DLetTuple (nl, subst_term_rec e t k, subst_term_rec e' t
+ (k + List.length nl),
+ subst_rec t' ttype k)
+ | DIfThenElse (b, e, e', t') ->
+ DIfThenElse (subst_term_rec b t k, subst_term_rec e t k,
+ subst_term_rec e' t k, subst_rec t' ttype k)
+ | DSum ((nl, dt), (dt', tt'), t') ->
+ DSum ((nl, subst_term_rec dt t k),
+ (subst_term_rec dt' t (succ k), subst_rec tt' tt' (succ k)),
+ subst_rec t' ttype k)
+ | DCoq (c, dt) ->
+
+ DCoq (c, subst_rec dt ttype k)
+ in loc, s'
+
+and subst_rec (loc, s) (t : dtype_loc) k =
+ let s' =
+ match s with
+ DTPi ((id, a), b, s) -> DTPi ((id, subst_rec a t k),
+ subst_rec b t (succ k), s)
+ | DTSigma ((id, a), b, s) -> DTSigma ((id, subst_rec a t k),
+ subst_rec b t (succ k), s)
+ | DTSubset ((id, a), b, s) -> DTSubset ((id, subst_rec a t k),
+ subst_rec b t (succ k), s)
+ | DTRel i ->
+ if k < i then DTRel (pred i)
+ else if k = i then snd (lift k t)
+ else (* k > i *) s
+ | DTApp (x, y, t', s) -> DTApp (subst_rec x t k, subst_rec y t k,
+ subst_rec t' t k, s)
+ | DTTerm (x, tt, s) -> DTTerm (subst_term_type_rec x t k, subst_rec tt t k, s)
+ | DTCoq (c, ct, s) -> DTCoq (c, subst_rec ct t k, s)
+ | DTSort _ | DTInd _ -> s
+ in loc, s'
+
+let subst s t = subst_rec s t 0
+let subst_term s t = subst_term_rec s t 0
+
+let rec print_dterm' ctx = function
+ | DRel n ->
+ (try
+ print_name (name_of_rel ctx n) ++ str ("(" ^ (string_of_int n) ^ ")")
+ with Failure _ -> str ("UNBOUND_REL_" ^ (string_of_int n)))
+ | DLambda ((namel, t), e, _) -> str "fun " ++ print_name (snd namel) ++ spc () ++
+ str ":" ++ spc () ++ print_dtype' ctx (snd t) ++ spc () ++ str "=>" ++ spc ()
+ ++ print_dterm_loc ((snd namel, t) :: ctx) e
+ | DApp (x, y, _) -> (print_dterm_loc ctx x) ++ spc () ++
+ str "(" ++ (print_dterm_loc ctx y) ++ str ")"
+ | DLetIn (n, e, e', _) ->
+ let te =
+ try type_of_dterm_loc ctx e
+ with e -> debug 3 (str "Couldn't find type_of_dterm in print_dterm'");
+ raise e
+ in
+ str "let" ++ spc () ++ print_name_loc n
+ ++ spc () ++ str "=" ++ spc () ++ print_dterm_loc ctx e ++
+ print_dterm_loc ((snd n, te) :: ctx) e'
+ | DLetTuple (nl, t, e, _) ->
+ str "let" ++ spc () ++ str "(" ++
+ string_of_list (List.rev_map (fun (n, _, _) -> print_name_loc n) nl)
+ ++ str ")" ++ spc () ++ str "=" ++ spc () ++
+ print_dterm_loc ctx t ++ str "in" ++ spc () ++
+ print_dterm_loc ((List.map (fun (x, y, z) -> (snd x, y)) nl) @ ctx) e
+ | DIfThenElse (b, t, t', _) ->
+ let ctx' = (Name (id_of_string "H"), (dummy_loc, DTRel 0)) :: ctx in
+ str "if" ++ spc () ++ print_dterm_loc ctx b ++ spc () ++
+ str "then" ++ spc () ++ print_dterm_loc ctx' t ++ spc () ++
+ str "else" ++ spc () ++ print_dterm_loc ctx' t'
+ | DSum ((n, t), (t', tt'), _) ->
+ let ctx' =
+ try (snd n, type_of_dterm_loc ctx t) :: ctx
+ with e -> debug 3 (str "Couldn't find type_of_dterm in print_dterm' (sum)");
+ raise e
+ in
+ str "(" ++ print_name (snd n) ++ str ":="
+ ++ print_dterm_loc ctx t ++ str ","
+ ++ print_dterm_loc ctx' t' ++ str ":"
+ ++ print_dtype_loc ctx' tt' ++ str ")"
+ | DCoq (cstr, t) -> pr_term cstr
+
+and print_dterm_loc ctx (_, x) = print_dterm' ctx x
+ (*debug_msg 1 (str ":" ++ print_dtype_loc ctx (type_of_dterm ctx x))*)
+
+and print_dtype' ctx = function
+ | DTApp (x, y, t, s) -> print_dtype_loc ctx x ++ spc() ++
+ str "(" ++ print_dtype_loc ctx y ++ str ")"
+ | DTPi ((id, x), y, s) ->
+ str "(" ++ print_name_loc id ++ str ":" ++ print_dtype_loc ctx x ++ str ")"
+ ++ spc() ++ print_dtype_loc ((snd id, x) :: ctx) y
+ | DTSigma ((id, x), y, s) ->
+ str "[" ++ print_name_loc id ++ str ":" ++ print_dtype_loc ctx x ++ str "]"
+ ++ spc() ++ print_dtype_loc ((snd id, x) :: ctx) y
+ | DTSubset ((id, x), y, s) ->
+ str "{" ++ str (string_of_id (snd id)) ++ str ":" ++ print_dtype_loc ctx x ++ str "|"
+ ++ spc() ++ print_dtype_loc ((Name (snd id), x) :: ctx) y ++ str "}"
+ | (DTRel i) as x ->
+ (try print_name (name_of_rel ctx i) ++ str ("(" ^ (string_of_int i) ^ ")")
+ with Failure _ -> str ("_UNBOUND_REL_" ^ (string_of_int i)))
+ | DTTerm (t, tt, s) -> str "Term:(" ++ print_dterm_loc ctx t ++ str ")"
+ | DTInd (n, t, i, s) -> str (string_of_id (snd n))
+ | DTCoq (c, t, s) ->
+ debug_msg 1 (str "Coq:(") ++ pr_term c ++
+ debug_msg 1 (str ":" ++ print_dtype_loc ctx t ++ str ")")
+ | DTSort s ->
+ pr_term (mkSort (snd s))
+
+and print_dtype_loc ctx (_, t) = print_dtype' ctx t
+
+let _ = print_dtype_locref := print_dtype_loc
+
+let rec reduce_term t =
+ match t with
+ | DLambda ((n, x), y, dt) -> DLambda ((n, reduce_type_loc x), reduce_term_loc y, reduce_type_loc dt)
+ | DApp (dte, dte', dt) -> snd (subst_term dte' dte)
+ | DLetIn (nl, dte, dte', dt) -> snd (subst_term dte' dte)
+ | DLetTuple (nl, dte, dte', dt) -> t (* TODO *)
+ | DIfThenElse (db, de, de', dt) -> t (* TODO *)
+ | DSum _ | DRel _ | DCoq _ -> t
+
+and reduce_term_loc (loc, t) = (loc, reduce_term t)
+
+and reduce_type = function
+ | DTApp (x, y, t, s) -> snd (subst y x)
+ | DTPi ((id, x), y, s) -> DTPi ((id, reduce_type_loc x), reduce_type_loc y, s)
+ | DTSigma ((id, x), y, s) -> DTSigma ((id, reduce_type_loc x), reduce_type_loc y, s)
+ | DTSubset ((id, x), y, s) -> DTSubset ((id, reduce_type_loc x), reduce_type_loc y, s)
+ | (DTRel i) as x -> x
+ | DTTerm (t, tt, s) -> DTTerm (reduce_term_loc t, reduce_type_loc tt, s)
+ | DTInd (n, t, i, s) as x -> x
+ | DTCoq (c, t, s) as x -> x
+ | DTSort _ as x -> x
+
+and reduce_type_loc (loc, t) = (loc, reduce_type t)
+
+
+let rec type_equiv ctx u v =
+ trace (str "Check type equivalence: " ++ print_dtype_loc ctx u ++ str " and " ++ print_dtype_loc ctx v);
+ match snd u, snd v with
+ DTCoq (_, x, _), y -> type_equiv ctx x v
+ | x, DTCoq (_, y, _) -> type_equiv ctx u y
+
+ | DTApp (_, _, t, _), _ -> type_equiv ctx t v
+ | _, DTApp (_, _, t, _) -> type_equiv ctx u t
+
+ | (DTPi ((_, x), y, _), DTPi ((n', x'), y', _)) ->
+ type_equiv ctx x x' && type_equiv ((snd n', x') :: ctx) y y'
+ | (DTSigma ((_, x), y, _), DTSigma ((n', x'), y', _)) ->
+ type_equiv ctx x x' && type_equiv ((snd n', x') :: ctx) y y'
+ | (DTSubset ((_, x), y, _), DTSubset ((_, x'), y', _)) ->
+ type_equiv ctx x x'
+ | (DTRel x, DTRel y) -> x = y
+ | (DTInd (n, _, i, _), DTInd (n', _, i', _)) -> i == i' || i = i'
+ | _ -> false
+
+let convertible ctx u v =
+ type_equiv ctx (reduce_type_loc u) (reduce_type_loc v)
+
+let rec check_subtype ctx u v =
+ trace (str "Check subtype: " ++ print_dtype_loc ctx u ++ str " and " ++ print_dtype_loc ctx v);
+ match (snd u, snd v) with
+ DTCoq (_, t, _), _ -> check_subtype ctx t v
+ | _, DTCoq (_, t, _) -> check_subtype ctx u t
+
+ | DTInd (_, t, _, _), _ -> check_subtype ctx t v
+ | _, DTInd (_, t, _, _) -> check_subtype ctx u t
+
+ | DTApp (_, _, t, _), _ -> check_subtype ctx t v
+ | _, DTApp (_, _, t, _) -> check_subtype ctx u t
+
+ | DTRel i, _ ->
+ let t =
+ try type_of_rel ctx i
+ with e ->
+ debug 3 (str "Couldn't find type_of_rel in check_subtype");
+ raise e
+ in check_subtype ctx (lift (succ i) t) v
+ | _, DTRel i ->
+ let t =
+ try type_of_rel ctx i
+ with e -> debug 3 (str "Couldn't find type_of_rel in check_subtype");
+ raise e
+ in
+ check_subtype ctx u (lift (succ i) t)
+
+ | (DTPi ((_, x), y, _), DTPi ((n', x'), y', _)) ->
+ check_subtype ctx x' x && check_subtype ((snd n', x') :: ctx) y y'
+
+ | (DTSigma ((_, x), y, _), DTSigma ((n', x'), y', _)) ->
+ check_subtype ctx x x' && check_subtype ((snd n', x') :: ctx) y y'
+
+ | (DTSubset ((_, x), y, _), _) -> check_subtype ctx x v
+ | (_, DTSubset ((_, x), y, _)) -> check_subtype ctx u x
+ | (DTSort s, DTSort s') ->
+ (match snd s, snd s' with
+ Prop _, Type _ -> true
+ | x, y -> x = y)
+ | _ -> convertible ctx u v
+
+let rec mu ctx = function
+ | DTSubset ((_, x), y, _) -> mu ctx (snd x)
+ | DTCoq (_, x, _) -> mu ctx (snd x)
+ | DTInd (_, t, _, _) -> mu ctx (snd t)
+ | DTApp (_, _, t, _) -> mu ctx (snd t)
+ | DTRel i -> mu ctx (snd (type_of_rel ctx i))
+ | x -> x
+
+exception Not_implemented of string
+
+let notimpl s = raise (Not_implemented s)
+
+let type_application ctx ((locx, x) as tx) ((locy, y) as ty) =
+ let narg, targ, tres, sres =
+ match mu ctx x with
+ | DTPi ((n, x), y, z) -> n, x, y, z
+ | x ->
+ typing_error (NonFunctionalApp (locx,
+ (print_dtype_loc ctx tx),
+ (print_dtype' ctx x)))
+ in
+ try
+ if check_subtype ctx ty targ then
+ let dtres = subst tres ty in
+ debug 1 (str "Subst of " ++ print_dtype_loc ctx ty ++ str " in " ++
+ print_dtype_loc ((snd narg, targ) :: ctx) tres);
+ debug 1 (str "Subst in result type: " ++ print_dtype_loc ctx dtres);
+ dummy_loc, DTApp (tx, ty, dtres, sort_of_dtype_loc ctx dtres)
+ else
+ subtyping_error (UncoercibleInferType
+ (locy, print_dtype_loc ctx ty, print_dtype_loc ctx targ))
+
+ with e -> raise e (* Todo check exception etc.. *)
+
+
+let rec dtype_of_types ctx c =
+ let dt =
+ match kind_of_term c with
+ | Rel i ->
+ DTRel (pred i)
+ | Var id ->
+ let ref = Nametab.locate (Libnames.make_short_qualid id) in
+ let t = Libnames.constr_of_global ref in
+ snd (dtype_of_types ctx t)
+ | Meta mv -> notimpl "Meta"
+ | Evar pex -> notimpl "Evar"
+ | Sort s -> DTSort (dummy_loc, s)
+ | Cast (c, t) -> snd (dtype_of_types ctx t)
+ | Prod (n, t, t') ->
+ let dt = dtype_of_types ctx t in
+ let ctx' = (n, dt) :: ctx in
+ let dt' = dtype_of_types ctx' t' in
+ DTPi (((dummy_loc, n), dt), dt', sort_of_dtype_loc ctx' dt')
+ | Lambda (n, t, e) -> notimpl "Lambda"
+ | LetIn (n, e, t, e') -> notimpl "LetIn"
+ | App (f, el) ->
+ snd (List.fold_left
+ (fun acc el ->
+ let tel = dtype_of_types ctx el in
+ type_application ctx acc tel)
+ (dtype_of_types ctx f) (Array.to_list el))
+ | Const cst ->
+ let t = Global.lookup_constant cst in
+ let dt = dtype_of_types ctx t.Declarations.const_type in
+ DTCoq (c, dt, sort_of_dtype_loc ctx dt)
+ | Ind i ->
+ let (_, ind) = Inductive.lookup_mind_specif (Global.env ()) i in
+ DTInd ((dummy_loc, ind.Declarations.mind_typename),
+ dtype_of_types ctx ind.Declarations.mind_nf_arity,
+ i, (dummy_loc, ind.Declarations.mind_sort))
+ (* let t = Inductiveops.type_of_inductive (Global.env ()) i in *)
+(* debug "Lookup inductive"; *)
+ (* let dt = dtype_of_types ctx t in *)
+(* DTCoq (t, dt, sort_of_dtype_loc ctx dt) *)
+
+ | Construct con ->
+ let t = Inductiveops.type_of_constructor (Global.env ()) con in
+ let dt = dtype_of_types ctx t in
+ DTCoq (c, dt, sort_of_dtype_loc ctx dt)
+ | Case _ -> notimpl "Case"
+ | Fix fixpt -> notimpl "Fixpoint"
+ | CoFix cofixpt -> notimpl "CoFixpoint"
+ in dummy_loc, dt
+
+let rec dtype_of_constr ctx c =
+ let dt =
+ match kind_of_term c with
+ | Rel i -> DTRel (pred i)
+ | Var id ->
+ let ref = Nametab.locate (Libnames.make_short_qualid id) in
+ let t = Libnames.constr_of_global ref in
+ snd (dtype_of_constr ctx t)
+ | Meta mv -> notimpl "Meta"
+ | Evar pex -> notimpl "Evar"
+ | Sort s -> DTSort (dummy_loc, s)
+ | Cast (c, t) -> snd (dtype_of_constr ctx t)
+ | Prod (n, t, t') ->
+ let dt = dtype_of_constr ctx t in
+ let ctx' = (n, dt) :: ctx in
+ let dt' = dtype_of_constr ctx' t' in
+ DTPi (((dummy_loc, n), dt), dt', sort_of_dtype_loc ctx' dt')
+ | Lambda (n, t, e) -> notimpl "Lambda"
+ | LetIn (n, e, t, e') -> notimpl "LetIn"
+ | App (f, el) ->
+ snd (List.fold_left
+ (fun acc el ->
+ type_application ctx acc (dtype_of_constr ctx el))
+ (dtype_of_constr ctx f) (Array.to_list el))
+ | Const cst ->
+ let t = Global.lookup_constant cst in
+ let dt = dtype_of_constr ctx t.Declarations.const_type in
+ snd dt
+
+ | Ind i ->
+ let (_, ind) = Inductive.lookup_mind_specif (Global.env ()) i in
+ DTInd ((dummy_loc, ind.Declarations.mind_typename),
+ dtype_of_types ctx ind.Declarations.mind_nf_arity,
+ i, (dummy_loc, ind.Declarations.mind_sort))
+
+ | Construct con ->
+ let t = Inductiveops.type_of_constructor (Global.env ()) con in
+ let dt = dtype_of_constr ctx t in
+ snd dt
+ | Case _ -> notimpl "Case"
+ | Fix fixpt -> notimpl "Fixpoint"
+ | CoFix cofixpt -> notimpl "CoFixpoint"
+ in dummy_loc, dt
+
+let list_assoc_index x l =
+ let rec aux i = function
+ (y, _) :: tl -> if x = y then i else aux (succ i) tl
+ | [] -> debug 2 (str "raising not_found in list_assoc_index");
+ raise Not_found
+ in aux 0 l
+
+let coqref ctx (loc, r) =
+ let qualid = Libnames.make_short_qualid r in
+ try
+ let gr = Nametab.locate qualid in
+ debug 3 (str "Resolved " ++ str (string_of_id r) ++ str " globally");
+ Libnames.constr_of_global gr
+ with Not_found ->
+ debug 3 (str "Error in coqref");
+ Nametab.error_global_not_found_loc loc qualid
+
+let coqtermref ctx r =
+ let constr = coqref ctx r in
+ let dtype = dtype_of_constr ctx constr in
+ DCoq (constr, dtype), dtype
+
+let coqtyperef ctx r =
+ let constr = coqref ctx r in
+ let dtype = dtype_of_types ctx constr in
+ snd dtype, dtype
+
+let debug_loc n (loc, e) =
+ debug n (Toplevel.print_toplevel_error (Stdpp.Exc_located (loc, Debug_msg e)))
+
+let rec dtype n ctx (loc, t) =
+ let t' =
+ match t with
+ TApp (x, y) ->
+ let tx, ty = dtype n ctx x, dtype n ctx y in
+ snd (type_application ctx tx ty)
+ | TPi ((name, t), t') ->
+ let dt = dtype n ctx t in
+ let dt' = dtype (succ n) ((snd name, dt) :: ctx) t' in
+ DTPi ((name, dt), dt', (dummy_loc, type_0))
+ | TSigma ((name, t), t') ->
+ let dt = dtype n ctx t in
+ let dt' = dtype (succ n) ((snd name, dt) :: ctx) t' in
+ DTSigma ((name, dt), dt', (dummy_loc, type_0))
+ | TSubset ((i, t), t') ->
+ let dt = dtype n ctx t in
+ let ctx' = (Name (snd i), dt) :: ctx in
+ let dt' = dtype (succ n) ctx' t' in
+ DTSubset ((i, dt), dt', sort_of_dtype_loc ctx dt)
+ | TIdent (loc, i) ->
+ let name = Name i in
+ if List.mem_assoc name ctx then
+ let typ = List.assoc name ctx in
+ let index = list_assoc_index name ctx in
+ debug 3 (str "Resolved " ++ str (string_of_id i) ++ str " locally");
+ DTRel index
+ else fst (coqtyperef ctx (loc, i))
+ | TTerm t -> let t, tt = dterm n ctx t in DTTerm (t, tt, sort_of_dtype_loc ctx tt)
+ in (loc, t')
+
+and dterm n ctx (loc, t) =
+ let t', tt' =
+ match t with
+ | SIdent li ->
+ begin
+ let name = Name (snd li) in
+ if List.mem_assoc name ctx then
+ let typ = List.assoc name ctx in
+ let index = list_assoc_index name ctx in
+ let typ' = lift (succ index) typ in
+ debug 3 (str "Resolved " ++ str (string_of_id (snd li)) ++ str " locally");
+ DRel index, typ'
+ else coqtermref ctx li
+ end
+
+ | SLambda (((loc, name) as ln, t), e) ->
+ let dt = dtype n ctx t in
+ let name = Name name in
+ let ln = loc, name in
+ let ctx' = (name, dt) :: ctx in
+ let de, te = dterm (succ n) ctx' e in
+ let dpi = dummy_loc, DTPi ((ln, dt), te, sort_of_dtype_loc ctx' te) in
+ DLambda ((ln, dt), de, dpi), dpi
+
+ | SLetIn ((loc, name) as ln, e, e') ->
+ let de, te = dterm n ctx e in
+ let de', te' = dterm (succ n) ((name, te) :: ctx) e' in
+ DLetIn (ln, de, de', te'), te'
+
+ | SApp (f, e) ->
+ let dt, tf = dterm n ctx f in
+ let narg, targ, tres, sres =
+ match mu ctx (snd tf) with
+ | DTPi ((n, x), y, z) -> n, x, y, z
+ | x -> typing_error (NonFunctionalApp
+ (fst f, print_dterm_loc ctx dt,
+ print_dtype' ctx x))
+ in
+ let de, te = dterm n ctx e in
+ (try
+ if check_subtype ctx te targ then
+ let term = (dummy_loc, DTTerm (de, te, sort_of_dtype_loc ctx te)) in
+ let dtres = subst tres term in
+ debug 1 (str "Subst of " ++ print_dtype_loc ctx term ++ str " in " ++
+ print_dtype_loc ((snd narg, targ) :: ctx) tres);
+ debug 1 (str "Subst in result type: " ++ print_dtype_loc ctx dtres);
+ DApp (dt, de, dtres), dtres
+ else
+ subtyping_error
+ (UncoercibleInferTerm (fst e,
+ print_dtype_loc ctx te,
+ print_dtype_loc ctx targ,
+ print_dterm_loc ctx de,
+ print_dterm_loc ctx dt))
+
+
+ with e -> raise e (* Todo check exception etc.. *))
+
+ | SSumDep (((loc, id), t), (t', tt')) ->
+ let dt, tt = dterm n ctx t in
+ let ctx' = (Name id, tt) :: ctx in
+ let tt' = dtype (succ n) ctx' tt' in
+ let dt', _ = dterm (succ n) ctx' t' in
+ let rest = dummy_loc,
+ DTSigma (((loc, Name id), tt), tt', sort_of_dtype_loc ctx' tt')
+ in
+ DSum (((loc, Name id), dt), (dt', tt'), rest), rest
+
+ | SSumInf (t, t') ->
+ let dt, tt = dterm n ctx t in
+ let ctx' = (Anonymous, tt) :: ctx in
+ let dt', tt' = dterm (succ n) ctx' t' in
+ let rest = dummy_loc,
+ DTSigma (((dummy_loc, Anonymous), tt), tt', sort_of_dtype_loc ctx' tt')
+ in
+ DSum (((dummy_loc, Anonymous), dt), (dt', tt'), rest), rest
+
+ | SIfThenElse (b, t, t') ->
+ let dn, tn = dterm n ctx b in
+ let ctx' = (Name (id_of_string "H"),
+ (dummy_loc,
+ DTCoq (Term.mkVar (id_of_string "H"),
+ (dummy_loc, DTSort (dummy_loc, mk_Set)),
+ (dummy_loc, type_0)))) :: ctx
+ in
+ let dt, tt = dterm (succ n) ctx' t
+ and dt', tt' = dterm (succ n) ctx' t' in
+ if convertible ctx' tt tt' then
+ DIfThenElse (dn, dt, dt', tt), (unlift 1 tt)
+ else typing_error (NonConvertible (loc, print_dtype_loc ctx' tt,
+ print_dtype_loc ctx' tt'))
+
+ | SLetTuple (nl, t, t') ->
+ let dt, tt = dterm n ctx t in
+ debug 2 (str "Let tuple e type: " ++ print_dtype_loc ctx tt);
+ let rec aux n lctx tt l =
+ match snd tt, l with
+ DTSigma ((nl, t), t', s), nl' :: ((_ :: _) as tl) ->
+ aux (succ n) ((nl', t, tt) :: lctx) t' tl
+ | _, [nl] ->
+ (nl, tt, tt) :: lctx
+ | _, _ -> typing_error (NonSigma (fst tt, print_dtype_loc ctx tt))
+ in
+ let ctx' = aux 0 [] tt nl in
+ let ctx'' = (List.map (fun (nl, t, t') -> (snd nl, t)) ctx') @ ctx in
+ let dt', tt' = dterm ((List.length nl) + n) ctx'' t' in
+ let t = DLetTuple (ctx', dt, dt', unlift (List.length nl) tt') in
+ debug 2 (str "Parsed let-tuple: " ++ print_dterm' ctx t);
+ debug 2 (str "ctx' = ");
+ debug 2 (str "ctx' = " ++
+ let cmds, _ =
+ (List.fold_right
+ (fun (x, t, t') (acc, ctx) ->
+ let acc' = print_name_loc x ++ str ":" ++
+ print_dtype_loc ctx t
+ in
+ let ctx' = (snd x, t) :: ctx in
+ (acc ++ spc () ++ acc', ctx'))
+ ctx' (mt (), ctx))
+ in cmds);
+
+ debug 2 (str "Parsed let-tuple in-term: " ++ print_dterm_loc ctx'' dt');
+ debug 2 (str "Parsed let-tuple type: " ++
+ print_dtype_loc ((List.map (fun (x, t, _) -> snd x, t) ctx') @ ctx) tt');
+ t, tt'
+
+
+ in (loc, t'), tt'
+
+let infer ctx t = dterm 0 ctx t
+let infer_type ctx t = dtype 0 ctx t
+