detect incorrect situations; better error messages; sanity check for quot_thm in setup_lifting_infr
authorkuncar
Thu, 05 Apr 2012 23:22:54 +0200
changeset 48237075d22b3a32f
parent 48236 96e920e0d09a
child 48238 c608111857d1
detect incorrect situations; better error messages; sanity check for quot_thm in setup_lifting_infr
src/HOL/Tools/Lifting/lifting_def.ML
src/HOL/Tools/Lifting/lifting_setup.ML
src/HOL/Tools/Lifting/lifting_term.ML
     1.1 --- a/src/HOL/Tools/Lifting/lifting_def.ML	Thu Apr 05 22:00:27 2012 +0200
     1.2 +++ b/src/HOL/Tools/Lifting/lifting_def.ML	Thu Apr 05 23:22:54 2012 +0200
     1.3 @@ -6,6 +6,8 @@
     1.4  
     1.5  signature LIFTING_DEF =
     1.6  sig
     1.7 +  exception FORCE_RTY of typ * term
     1.8 +
     1.9    val add_lift_def:
    1.10      (binding * mixfix) -> typ -> term -> thm -> local_theory -> local_theory
    1.11  
    1.12 @@ -26,6 +28,8 @@
    1.13  
    1.14  fun ants MRSL thm = fold (fn rl => fn thm => rl RS thm) ants thm
    1.15  
    1.16 +exception FORCE_RTY of typ * term
    1.17 +
    1.18  fun get_body_types (Type ("fun", [_, U]), Type ("fun", [_, V])) = get_body_types (U, V)
    1.19    | get_body_types (U, V)  = (U, V)
    1.20  
    1.21 @@ -38,6 +42,7 @@
    1.22      val rhs_schematic = singleton (Variable.polymorphic ctxt) rhs
    1.23      val rty_schematic = fastype_of rhs_schematic
    1.24      val match = Sign.typ_match thy (rty_schematic, rty) Vartab.empty
    1.25 +      handle Type.TYPE_MATCH => raise FORCE_RTY (rty, rhs)
    1.26    in
    1.27      Envir.subst_term_types match rhs_schematic
    1.28    end
    1.29 @@ -283,6 +288,46 @@
    1.30        | NONE =>  Proof.theorem NONE after_qed [[(readable_rsp_tm,[])]] lthy
    1.31    end
    1.32  
    1.33 +fun quot_thm_err ctxt (rty, qty) pretty_msg =
    1.34 +  let
    1.35 +    val error_msg = cat_lines
    1.36 +       ["Lifting failed for the following types:",
    1.37 +        Pretty.string_of (Pretty.block
    1.38 +         [Pretty.str "Raw type:", Pretty.brk 2, Syntax.pretty_typ ctxt rty]),
    1.39 +        Pretty.string_of (Pretty.block
    1.40 +         [Pretty.str "Abstract type:", Pretty.brk 2, Syntax.pretty_typ ctxt qty]),
    1.41 +        "",
    1.42 +        (Pretty.string_of (Pretty.block
    1.43 +         [Pretty.str "Reason:", Pretty.brk 2, pretty_msg]))]
    1.44 +  in
    1.45 +    error error_msg
    1.46 +  end
    1.47 +
    1.48 +fun force_rty_err ctxt rty rhs =
    1.49 +  let
    1.50 +    val error_msg = cat_lines
    1.51 +       ["Lifting failed for the following term:",
    1.52 +        Pretty.string_of (Pretty.block
    1.53 +         [Pretty.str "Term:", Pretty.brk 2, Syntax.pretty_term ctxt rhs]),
    1.54 +        Pretty.string_of (Pretty.block
    1.55 +         [Pretty.str "Type:", Pretty.brk 2, Syntax.pretty_typ ctxt (fastype_of rhs)]),
    1.56 +        "",
    1.57 +        (Pretty.string_of (Pretty.block
    1.58 +         [Pretty.str "Reason:", 
    1.59 +          Pretty.brk 2, 
    1.60 +          Pretty.str "The type of the term cannot be instancied to",
    1.61 +          Pretty.brk 1,
    1.62 +          Pretty.quote (Syntax.pretty_typ ctxt rty),
    1.63 +          Pretty.str "."]))]
    1.64 +    in
    1.65 +      error error_msg
    1.66 +    end
    1.67 +
    1.68 +fun lift_def_cmd_with_err_handling (raw_var, rhs_raw) lthy =
    1.69 +  (lift_def_cmd (raw_var, rhs_raw) lthy
    1.70 +    handle Lifting_Term.QUOT_THM (rty, qty, msg) => quot_thm_err lthy (rty, qty) msg)
    1.71 +    handle FORCE_RTY (rty, rhs) => force_rty_err lthy rty rhs
    1.72 +
    1.73  (* parser and command *)
    1.74  val liftdef_parser =
    1.75    ((Parse.binding -- (@{keyword "::"} |-- (Parse.typ >> SOME) -- Parse.opt_mixfix')) >> Parse.triple2)
    1.76 @@ -291,7 +336,7 @@
    1.77  val _ =
    1.78    Outer_Syntax.local_theory_to_proof @{command_spec "lift_definition"}
    1.79      "definition for constants over the quotient type"
    1.80 -      (liftdef_parser >> lift_def_cmd)
    1.81 +      (liftdef_parser >> lift_def_cmd_with_err_handling)
    1.82  
    1.83  
    1.84  end; (* structure *)
     2.1 --- a/src/HOL/Tools/Lifting/lifting_setup.ML	Thu Apr 05 22:00:27 2012 +0200
     2.2 +++ b/src/HOL/Tools/Lifting/lifting_setup.ML	Thu Apr 05 23:22:54 2012 +0200
     2.3 @@ -50,8 +50,35 @@
     2.4    else
     2.5      lthy
     2.6  
     2.7 +fun quot_thm_sanity_check ctxt quot_thm =
     2.8 +  let
     2.9 +    val ((_, [quot_thm_fixed]), ctxt') = Variable.importT [quot_thm] ctxt 
    2.10 +    val (rty, qty) = Lifting_Term.quot_thm_rty_qty quot_thm_fixed
    2.11 +    val rty_tfreesT = Term.add_tfree_namesT rty []
    2.12 +    val qty_tfreesT = Term.add_tfree_namesT qty []
    2.13 +    val extra_rty_tfrees =
    2.14 +      (case subtract (op =) qty_tfreesT rty_tfreesT of
    2.15 +        [] => []
    2.16 +      | extras => [Pretty.block ([Pretty.str "Extra variables in the raw type:",
    2.17 +                                 Pretty.brk 1] @ 
    2.18 +                                 ((Pretty.commas o map (Pretty.str o quote)) extras) @
    2.19 +                                 [Pretty.str "."])])
    2.20 +    val not_type_constr = 
    2.21 +      (case qty of
    2.22 +         Type _ => []
    2.23 +         | _ => [Pretty.block [Pretty.str "The quotient type ",
    2.24 +                                Pretty.quote (Syntax.pretty_typ ctxt' qty),
    2.25 +                                Pretty.brk 1,
    2.26 +                                Pretty.str "is not a type constructor."]])
    2.27 +    val errs = extra_rty_tfrees @ not_type_constr
    2.28 +  in
    2.29 +    if null errs then () else error (cat_lines (["Sanity check of the quotient theorem failed:",""] 
    2.30 +                                                @ (map Pretty.string_of errs)))
    2.31 +  end
    2.32 +
    2.33  fun setup_lifting_infr quot_thm equiv_thm lthy =
    2.34    let
    2.35 +    val _ = quot_thm_sanity_check lthy quot_thm
    2.36      val (_, qtyp) = Lifting_Term.quot_thm_rty_qty quot_thm
    2.37      val qty_full_name = (fst o dest_Type) qtyp
    2.38      val quotients = { quot_thm = quot_thm }
     3.1 --- a/src/HOL/Tools/Lifting/lifting_term.ML	Thu Apr 05 22:00:27 2012 +0200
     3.2 +++ b/src/HOL/Tools/Lifting/lifting_term.ML	Thu Apr 05 23:22:54 2012 +0200
     3.3 @@ -6,6 +6,8 @@
     3.4  
     3.5  signature LIFTING_TERM =
     3.6  sig
     3.7 +  exception QUOT_THM of typ * typ * Pretty.T
     3.8 +
     3.9    val prove_quot_theorem: Proof.context -> typ * typ -> thm
    3.10  
    3.11    val absrep_fun: Proof.context -> typ * typ -> term
    3.12 @@ -24,7 +26,10 @@
    3.13  structure Lifting_Term: LIFTING_TERM =
    3.14  struct
    3.15  
    3.16 -exception LIFT_MATCH of string
    3.17 +(* generation of the Quotient theorem  *)
    3.18 +
    3.19 +exception QUOT_THM_INTERNAL of Pretty.T
    3.20 +exception QUOT_THM of typ * typ * Pretty.T
    3.21  
    3.22  (* matches a type pattern with a type *)
    3.23  fun match ctxt err ty_pat ty =
    3.24 @@ -40,21 +45,24 @@
    3.25      val ty_pat_str = Syntax.string_of_typ ctxt ty_pat
    3.26      val ty_str = Syntax.string_of_typ ctxt ty
    3.27    in
    3.28 -    raise LIFT_MATCH (space_implode " "
    3.29 -      ["equiv_relation (Types ", quote ty_pat_str, "and", quote ty_str, " do not match.)"])
    3.30 +    raise QUOT_THM_INTERNAL (Pretty.block
    3.31 +      [Pretty.str ("The quotient type " ^ quote ty_str),
    3.32 +       Pretty.brk 1,
    3.33 +       Pretty.str ("and the quotient type pattern " ^ quote ty_pat_str),
    3.34 +       Pretty.brk 1,
    3.35 +       Pretty.str "don't match."])
    3.36    end
    3.37  
    3.38 -(* generation of the Quotient theorem  *)
    3.39 -
    3.40 -exception QUOT_THM of string
    3.41 -
    3.42  fun get_quot_thm ctxt s =
    3.43    let
    3.44      val thy = Proof_Context.theory_of ctxt
    3.45    in
    3.46      (case Lifting_Info.lookup_quotients ctxt s of
    3.47        SOME qdata => Thm.transfer thy (#quot_thm qdata)
    3.48 -    | NONE => raise QUOT_THM ("No quotient type " ^ quote s ^ " found."))
    3.49 +    | NONE => raise QUOT_THM_INTERNAL (Pretty.block 
    3.50 +      [Pretty.str ("No quotient type " ^ quote s), 
    3.51 +       Pretty.brk 1, 
    3.52 +       Pretty.str "found."]))
    3.53    end
    3.54  
    3.55  fun get_rel_quot_thm ctxt s =
    3.56 @@ -63,7 +71,10 @@
    3.57    in
    3.58      (case Lifting_Info.lookup_quotmaps ctxt s of
    3.59        SOME map_data => Thm.transfer thy (#quot_thm map_data)
    3.60 -    | NONE => raise QUOT_THM ("get_relmap (no relation map function found for type " ^ s ^ ")"))
    3.61 +    | NONE => raise QUOT_THM_INTERNAL (Pretty.block 
    3.62 +      [Pretty.str ("No relator for the type " ^ quote s), 
    3.63 +       Pretty.brk 1,
    3.64 +       Pretty.str "found."]))
    3.65    end
    3.66  
    3.67  fun is_id_quot thm = (prop_of thm = prop_of @{thm identity_quotient})
    3.68 @@ -106,8 +117,19 @@
    3.69      (domain_type abs_type, range_type abs_type)
    3.70    end
    3.71  
    3.72 +fun check_raw_types (provided_rty_name, rty_of_qty_name) qty_name =
    3.73 +  if provided_rty_name <> rty_of_qty_name then
    3.74 +    raise QUOT_THM_INTERNAL (Pretty.block 
    3.75 +        [Pretty.str ("The type " ^ quote provided_rty_name),
    3.76 +         Pretty.brk 1,
    3.77 +         Pretty.str ("is not a raw type for the quotient type " ^ quote qty_name ^ ";"),
    3.78 +         Pretty.brk 1,
    3.79 +         Pretty.str ("the correct raw type is " ^ quote rty_of_qty_name ^ ".")])
    3.80 +  else
    3.81 +    ()
    3.82 +
    3.83  fun prove_quot_theorem' ctxt (rty, qty) =
    3.84 -  case (rty, qty) of
    3.85 +  (case (rty, qty) of
    3.86      (Type (s, tys), Type (s', tys')) =>
    3.87        if s = s'
    3.88        then
    3.89 @@ -123,7 +145,8 @@
    3.90        else
    3.91          let
    3.92            val quot_thm = get_quot_thm ctxt s'
    3.93 -          val (Type (_, rtys), qty_pat) = quot_thm_rty_qty quot_thm
    3.94 +          val (Type (rs, rtys), qty_pat) = quot_thm_rty_qty quot_thm
    3.95 +          val _ = check_raw_types (s, rs) s'
    3.96            val qtyenv = match ctxt equiv_match_err qty_pat qty
    3.97            val rtys' = map (Envir.subst_type qtyenv) rtys
    3.98            val args = map (prove_quot_theorem' ctxt) (tys ~~ rtys')
    3.99 @@ -138,7 +161,8 @@
   3.100                [rel_quot_thm, quot_thm] MRSL @{thm Quotient_compose}
   3.101             end
   3.102          end
   3.103 -  | _ => @{thm identity_quotient}
   3.104 +  | _ => @{thm identity_quotient})
   3.105 +    handle QUOT_THM_INTERNAL pretty_msg => raise QUOT_THM (rty, qty, pretty_msg)
   3.106  
   3.107  fun force_qty_type thy qty quot_thm =
   3.108    let