aboutsummaryrefslogtreecommitdiffhomepage
path: root/kernel/term_typing.ml
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/term_typing.ml')
-rw-r--r--kernel/term_typing.ml199
1 files changed, 143 insertions, 56 deletions
diff --git a/kernel/term_typing.ml b/kernel/term_typing.ml
index 33a4b55e8..fd31d782a 100644
--- a/kernel/term_typing.ml
+++ b/kernel/term_typing.ml
@@ -23,6 +23,10 @@ open Environ
open Entries
open Typeops
+let debug = false
+let prerr_endline =
+ if debug then prerr_endline else fun _ -> ()
+
let constrain_type env j cst1 = function
| None ->
make_polymorphic_if_constant_for_ind env j, cst1
@@ -33,19 +37,6 @@ let constrain_type env j cst1 = function
let cstrs = union_constraints (union_constraints cst1 cst2) cst3 in
NonPolymorphicType t, cstrs
-let local_constrain_type env j cst1 = function
- | None ->
- j.uj_type, cst1
- | Some t ->
- let (tj,cst2) = infer_type env t in
- let (_,cst3) = judge_of_cast env j DEFAULTcast tj in
- assert (eq_constr t tj.utj_val);
- t, union_constraints (union_constraints cst1 cst2) cst3
-
-let translate_local_def env de =
- let (j,cst) = infer env de.const_entry_body in
- let (typ,cst) = local_constrain_type env j cst de.const_entry_type in
- (j.uj_val,typ,cst)
let translate_local_assum env t =
let (j,cst) = infer env t in
@@ -55,23 +46,89 @@ let translate_local_assum env t =
(* Insertion of constants and parameters in environment. *)
-let infer_declaration env = function
+let handle_side_effects env body side_eff =
+ let handle_sideff t (NewConstant (c,cb)) =
+ let cname =
+ let name = string_of_con c in
+ for i = 0 to String.length name - 1 do
+ if name.[i] = '.' || name.[i] = '#' then name.[i] <- '_' done;
+ Name (id_of_string name) in
+ let rec sub i x = match kind_of_term x with
+ | Const c' when eq_constant c c' -> mkRel i
+ | _ -> map_constr_with_binders ((+) 1) sub i x in
+ match cb.const_body with
+ | Undef _ -> assert false
+ | Def b ->
+ let b = Lazyconstr.force b in
+ let b_ty = Typeops.type_of_constant_type env cb.const_type in
+ let t = sub 1 (Vars.lift 1 t) in
+ mkLetIn (cname, b, b_ty, t)
+ | OpaqueDef b ->
+ let b = Lazyconstr.force_opaque (Future.force b) in
+ let b_ty = Typeops.type_of_constant_type env cb.const_type in
+ let t = sub 1 (Vars.lift 1 t) in
+ mkApp (mkLambda (cname, b_ty, t), [|b|])
+ in
+ (* CAVEAT: we assure a proper order *)
+ Declareops.fold_side_effects handle_sideff body
+ (Declareops.uniquize_side_effects side_eff)
+
+(* what is used for debugging only *)
+let infer_declaration ?(what="UNKNOWN") env dcl =
+ match dcl with
| DefinitionEntry c ->
- let (j,cst) = infer env c.const_entry_body in
- let j =
- {uj_val = hcons_constr j.uj_val;
- uj_type = hcons_constr j.uj_type} in
- let (typ,cst) = constrain_type env j cst c.const_entry_type in
- let def =
- if c.const_entry_opaque
- then OpaqueDef (Lazyconstr.opaque_from_val j.uj_val)
- else Def (Lazyconstr.from_val j.uj_val)
- in
- def, typ, cst, c.const_entry_inline_code, c.const_entry_secctx
+ let ctx, entry_body = c.const_entry_secctx, c.const_entry_body in
+ if c.const_entry_opaque && c.const_entry_type <> None then
+ let _ = prerr_endline ("deferring typing of "^what) in
+ let body_cst = Future.chain ~id:("infer_declaration " ^ what)
+ entry_body (fun entry_body ->
+ let _ = prerr_endline ("forcing deferred typing of "^what) in
+ let body, side_eff = entry_body in
+ let _ = prerr_endline ("... got proof of "^what) in
+ let body = if side_eff = Declareops.no_seff then body else
+ let _ = prerr_endline (" Handling the following side eff:") in
+ Declareops.iter_side_effects (fun e ->
+ prerr_endline(" " ^ Declareops.string_of_side_effect e))
+ side_eff;
+ handle_side_effects env body side_eff in
+ let (j,cst) = infer env body in
+ let _ = prerr_endline ("... typed proof of "^what) in
+ let j =
+ {uj_val = hcons_constr j.uj_val;
+ uj_type = hcons_constr j.uj_type} in
+ let (_typ,cst) = constrain_type env j cst c.const_entry_type in
+ Lazyconstr.opaque_from_val j.uj_val, cst) in
+ let body, cst = Future.split2 body_cst in
+ let def = OpaqueDef body in
+ let typ = match c.const_entry_type with
+ | None -> assert false
+ | Some typ -> NonPolymorphicType typ in
+ (def, typ, cst, c.const_entry_inline_code, ctx)
+ else
+ let _ = prerr_endline ("typing now "^what) in
+ let body, side_eff = Future.force entry_body in
+ let body = if side_eff = Declareops.no_seff then body else
+ let _ = prerr_endline (" Handling the following side eff:") in
+ Declareops.iter_side_effects (fun e ->
+ prerr_endline(" " ^ Declareops.string_of_side_effect e))
+ side_eff;
+ handle_side_effects env body side_eff in
+ let (j,cst) =
+ try infer env body
+ with Not_found as e ->
+ prerr_endline ("infer not found " ^ what);
+ raise e in
+ let j =
+ {uj_val = hcons_constr j.uj_val;
+ uj_type = hcons_constr j.uj_type} in
+ let (typ,cst) = constrain_type env j cst c.const_entry_type in
+ let _ = prerr_endline ("...typed "^what) in
+ let def = Def (Lazyconstr.from_val j.uj_val) in
+ (def, typ, Future.from_val cst, c.const_entry_inline_code, ctx)
| ParameterEntry (ctx,t,nl) ->
let (j,cst) = infer env t in
let t = hcons_constr (Typeops.assumption_of_judgment env j) in
- Undef nl, NonPolymorphicType t, cst, false, ctx
+ Undef nl, NonPolymorphicType t, Future.from_val cst, false, ctx
let global_vars_set_constant_type env = function
| NonPolymorphicType t -> global_vars_set env t
@@ -81,48 +138,78 @@ let global_vars_set_constant_type env = function
(fun t c -> Id.Set.union (global_vars_set env t) c))
ctx ~init:Id.Set.empty
-let check_declared_variables declared inferred =
- let mk_set l = List.fold_right Id.Set.add (List.map pi1 l) Id.Set.empty in
- let undeclared_set = Id.Set.diff (mk_set inferred) (mk_set declared) in
- if not (Id.Set.is_empty undeclared_set) then
- error ("The following section variables are used but not declared:\n"^
- (String.concat ", "
- (List.map Id.to_string (Id.Set.elements undeclared_set))))
-
-let build_constant_declaration env (def,typ,cst,inline_code,ctx) =
- let hyps =
- let inferred =
- let ids_typ = global_vars_set_constant_type env typ in
- let ids_def = match def with
- | Undef _ -> Id.Set.empty
- | Def cs -> global_vars_set env (Lazyconstr.force cs)
- | OpaqueDef lc -> global_vars_set env (Lazyconstr.force_opaque lc)
- in
- keep_hyps env (Id.Set.union ids_typ ids_def)
- in
+let build_constant_declaration kn env (def,typ,cst,inline_code,ctx) =
+ let check declared inferred =
+ let mk_set l = List.fold_right Id.Set.add (List.map pi1 l) Id.Set.empty in
+ let inferred_set, declared_set = mk_set inferred, mk_set declared in
+ if not (Id.Set.subset inferred_set declared_set) then
+ error ("The following section variable are used but not declared:\n"^
+ (String.concat ", " (List.map Id.to_string
+ (Id.Set.elements (Idset.diff inferred_set declared_set))))) in
+ (* We try to postpone the computation of used section variables *)
+ let hyps, def =
match ctx with
- | None -> inferred
- | Some declared ->
- check_declared_variables declared inferred;
- declared
- in
- let tps = Cemitcodes.from_val (compile_constant_body env def) in
+ | None when named_context env <> [] ->
+ (* No declared section vars, and non-empty section context:
+ we must look at the body NOW, if any *)
+ let ids_typ = global_vars_set_constant_type env typ in
+ let ids_def = match def with
+ | Undef _ -> Idset.empty
+ | Def cs -> global_vars_set env (Lazyconstr.force cs)
+ | OpaqueDef lc ->
+ (* we force so that cst are added to the env immediately after *)
+ ignore(Future.join cst);
+ global_vars_set env (Lazyconstr.force_opaque (Future.force lc)) in
+ keep_hyps env (Idset.union ids_typ ids_def), def
+ | None -> [], def (* Empty section context: no need to check *)
+ | Some declared ->
+ (* We use the declared set and chain a check of correctness *)
+ declared,
+ match def with
+ | Undef _ as x -> x (* nothing to check *)
+ | Def cs as x ->
+ let ids_typ = global_vars_set_constant_type env typ in
+ let ids_def = global_vars_set env (Lazyconstr.force cs) in
+ let inferred = keep_hyps env (Idset.union ids_typ ids_def) in
+ check declared inferred;
+ x
+ | OpaqueDef lc -> (* In this case we can postpone the check *)
+ OpaqueDef (Future.chain ~id:(string_of_con kn) lc (fun lc ->
+ let ids_typ = global_vars_set_constant_type env typ in
+ let ids_def =
+ global_vars_set env (Lazyconstr.force_opaque lc) in
+ let inferred = keep_hyps env (Idset.union ids_typ ids_def) in
+ check declared inferred; lc)) in
{ const_hyps = hyps;
const_body = def;
const_type = typ;
- const_body_code = tps;
+ const_body_code = Cemitcodes.from_val (compile_constant_body env def);
const_constraints = cst;
const_native_name = ref NotLinked;
const_inline_code = inline_code }
(*s Global and local constant declaration. *)
-let translate_constant env ce =
- build_constant_declaration env (infer_declaration env ce)
+let translate_constant env kn ce =
+ build_constant_declaration kn env
+ (infer_declaration ~what:(string_of_con kn) env ce)
+
+let translate_recipe env kn r =
+ let def,typ,cst,inline_code,hyps = Cooking.cook_constant env r in
+ build_constant_declaration kn env (def,typ,cst,inline_code,hyps)
-let translate_recipe env r =
- build_constant_declaration env (Cooking.cook_constant env r)
+let translate_local_def env id centry =
+ let def,typ,cst,inline_code,ctx =
+ infer_declaration ~what:(string_of_id id) env (DefinitionEntry centry) in
+ let typ = type_of_constant_type env typ in
+ def, typ, cst
(* Insertion of inductive types. *)
let translate_mind env kn mie = Indtypes.check_inductive env kn mie
+
+let handle_side_effects env ce = { ce with
+ const_entry_body = Future.chain ~id:"handle_side_effects"
+ ce.const_entry_body (fun (body, side_eff) ->
+ handle_side_effects env body side_eff, Declareops.no_seff);
+}