aboutsummaryrefslogtreecommitdiff
path: root/typing.ML
blob: bfe84098f85c786a499d9f71d7fa37d62e032ca5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
(********
Isabelle/HoTT: typing.ML
Feb 2019

Functionality for object-level type inference.

********)

signature TYPING =
sig
  type jmt = term
  val term_of_jmt: jmt -> term
  val type_of_jmt: jmt -> term
  val typing_assms: Proof.context -> jmt list
  val get_typing: term -> jmt list -> term option
  val get_global_typing: theory -> Proof.context -> term -> term option
  val tm_of_ptm: Proof.context -> term -> term
end

structure Typing: TYPING =
struct

type jmt = term

(* Functions to extract a and A from propositions "a: A" *)
fun term_of_jmt (@{const has_type} $ t $ _) = t
  | term_of_jmt _ = Exn.error "Not a typing judgment"

fun type_of_jmt (@{const has_type} $ _ $ T) = T
  | type_of_jmt _ = Exn.error "Not a typing judgment"

(* Get the typing assumptions in the current context *)
fun typing_assms ctxt =
  let
    fun is_typing_jmt (@{const has_type} $ _ $ _) = true
      | is_typing_jmt _ = false
  in
    Assumption.all_prems_of ctxt |> map Thm.prop_of |> filter is_typing_jmt
  end

(* Search for a term typing in a list of judgments*)
fun get_typing tm jmts =
  let val find_type =
        fn jmt => if Term.aconv_untyped (tm, term_of_jmt jmt) then SOME (type_of_jmt jmt) else NONE
  in get_first find_type jmts end

(* Private storage space for global typing data *)
structure Typing_Data = Theory_Data
(
  type T = term Symtab.table
  val empty = Symtab.empty
  val extend = I

  fun merge (tbl, tbl') =
    let
      val key_vals = map (Symtab.lookup_key tbl') (Symtab.keys tbl')
      val updates = map (fn SOME kv => Symtab.update kv) key_vals
      fun f u t = u t
    in fold f updates tbl end
)

(* Accessor for the above data *)
fun get_global_typing thy ctxt tm = Symtab.lookup (Typing_Data.get thy) (Syntax.string_of_term ctxt tm)

(* Convert a Pure pre-term to an unchecked Pure term *)
fun tm_of_ptm ctxt ptm =
  let val ptm = Term_Position.strip_positions ptm
  in
  (case ptm of
    Const ("_constrain", _) $ Free (t, _) $ (Const ("\<^type>fun", _) $ Const(n1, _) $ Const (n2, _)) =>
      let
        val typ1 = unprefix "\<^type>" n1
        val typ2 = unprefix "\<^type>" n2
        val typ = typ1 ^ "\<Rightarrow>" ^ typ2 |> Syntax.read_typ ctxt
      in Free (t, typ) end
  | Const ("_constrain", _) $ Free (t, _) $ Const (T, _) =>
      Free (t, Syntax.read_typ ctxt (unprefix "\<^type>" T))
  | ptm1 $ ptm2 =>
      (tm_of_ptm ctxt ptm1) $ (tm_of_ptm ctxt ptm2)
  | Const (t, T) =>
      let val t' =
        unprefix "\<^const>" t handle Fail "unprefix" =>
        unprefix "\<^type>" t handle Fail "unprefix" =>
        t
      in Const (t', T) end
  | Abs (t, T, ptm') =>
      Abs (t, T, tm_of_ptm ctxt ptm')
  | t => t)
  end

end