File ‹~~/src/Tools/Argo/argo_term.ML›
signature ARGO_TERM =
sig
type meta
datatype term = T of meta * Argo_Expr.kind * term list
val id_of: term -> int
val expr_of: term -> Argo_Expr.expr
val type_of: term -> Argo_Expr.typ
val eq_term: term * term -> bool
val term_ord: term ord
type context
val context: context
datatype item = Expr of Argo_Expr.expr | Term of term
datatype identified = New of term | Known of term
val identify_item: item -> context -> identified * context
end
structure Argo_Term: ARGO_TERM =
struct
datatype meta = M of int * Argo_Expr.expr
datatype term = T of meta * Argo_Expr.kind * term list
fun id_of (T (M (id, _), _, _)) = id
fun expr_of (T (M (_, e), _, _)) = e
fun type_of t = Argo_Expr.type_of (expr_of t)
fun eq_term (t1, t2) = (id_of t1 = id_of t2)
fun term_ord (t1, t2) = int_ord (id_of t1, id_of t2)
datatype kind =
Con of string * Argo_Expr.typ |
Num of Rat.rat |
Exp of int list
fun kind_of (Argo_Expr.E (Argo_Expr.Con c, _)) _ = Con c
| kind_of (Argo_Expr.E (Argo_Expr.Num n, _)) _ = Num n
| kind_of (Argo_Expr.E (k, _)) is = Exp (Argo_Expr.int_of_kind k :: is)
fun int_of_kind (Con _) = 1
| int_of_kind (Num _) = 2
| int_of_kind (Exp _) = 3
fun kind_ord (Con c1, Con c2) = Argo_Expr.con_ord (c1, c2)
| kind_ord (Num n1, Num n2) = Rat.ord (n1, n2)
| kind_ord (Exp is1, Exp is2) = dict_ord int_ord (is1, is2)
| kind_ord (k1, k2) = int_ord (int_of_kind k1, int_of_kind k2)
structure Kindtab = Table(type key = kind val ord = kind_ord)
type context = {
next_id: int,
terms: (term * bool) Kindtab.table}
fun mk_context next_id terms: context = {next_id=next_id, terms=terms}
val context = mk_context 1 Kindtab.empty
fun note_atom true kind (t, false) ({next_id, terms}: context) =
mk_context next_id (Kindtab.update (kind, (t, true)) terms)
| note_atom _ _ _ cx = cx
fun with_unique_id kind is_atom (e as Argo_Expr.E (k, _)) ts ({next_id, terms}: context) =
let val t = T (M (next_id, e), k, ts)
in ((t, false), mk_context (next_id + 1) (Kindtab.update (kind, (t, is_atom)) terms)) end
fun unique kind is_atom e ts (cx as {terms, ...}: context) =
(case Kindtab.lookup terms kind of
SOME tp => (tp, note_atom is_atom kind tp cx)
| NONE => with_unique_id kind is_atom e ts cx)
datatype item = Expr of Argo_Expr.expr | Term of term
datatype identified = New of term | Known of term
fun identify_head is_atom e (ts, cx) = unique (kind_of e (map id_of ts)) is_atom e ts cx
fun identify is_atom (e as Argo_Expr.E (_, es)) cx =
identify_head is_atom e (fold_map (apfst fst oo identify false) es cx)
fun identified (t, true) = Known t
| identified (t, false) = New t
fun identify_item (Expr e) cx = identify true e cx |>> identified
| identify_item (Term (t as T (_, _, ts))) cx =
identify_head true (expr_of t) (ts, cx) |>> identified
end
structure Argo_Termtab = Table(type key = Argo_Term.term val ord = Argo_Term.term_ord)