-
Notifications
You must be signed in to change notification settings - Fork 108
/
Copy pathspec_graph.ML
157 lines (109 loc) · 3.8 KB
/
spec_graph.ML
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
(*
* Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
*
* SPDX-License-Identifier: BSD-2-Clause
*)
signature SPEC_GRAPH =
sig
datatype spec_type =
Definition | Constructor | Case | Locale
type entry = {name : string, def_name: string option, spec_type : spec_type}
val get_graph: theory -> ((entry Int_Graph.T) * (string * typ -> Int_Graph.key option))
val encode_graph: entry Int_Graph.T XML.Encode.T
val decode_graph : entry Int_Graph.T XML.Decode.T
end
structure Spec_Graph : SPEC_GRAPH =
struct
datatype spec_type =
Definition | Constructor | Case | Locale
type entry = {name : string, def_name: string option, spec_type : spec_type}
fun could_match (Ts, Us) =
Option.isSome (SOME (Type.raw_matches (Ts, Us) Vartab.empty) handle Type.TYPE_MATCH => NONE);
fun get_graph thy =
let
val defs = Theory.defs_of thy
val consts = Sign.consts_of thy
val {restricts,reducts} = Defs.dest (Theory.defs_of thy)
fun body_of (nm,args) =
let
val specs = Defs.specifications_of defs nm
val spec_of = find_first (fn {def,description,pos,lhs,rhs} => lhs = args) specs
in
the spec_of
|> (fn s => (#rhs s,#def s))
end
fun add_general nm ls =
let
val c = Consts.the_const consts nm
val args = Consts.typargs consts c
in
if null args orelse exists (fn (args',_) =>
could_match (args',args)) ls
then ls else (ls @ [(args,([],NONE))])
end
val reduct_tab = map (fn ((nm,args),_) => (nm,(args,(body_of (nm,args))))) reducts
|> Symtab.make_list
|> Symtab.map add_general
val id_reduct_tab =
fold_map (fn entry => fn id => ((id,entry),id + 1)) (Symtab.dest_list reduct_tab) 0
|> fst
|> map (fn (id,(nm,entry)) => (nm,(id,entry)))
|> Symtab.make_list
fun id_of (nm,args) = case Symtab.lookup id_reduct_tab nm of SOME e =>
get_first (fn (id,(args',_)) => if could_match (args',args) then SOME id else NONE) e
| NONE => NONE
fun mk_graph_entry (nm,(id,(args,(body,def)))) =
let
val T = Consts.the_constraint consts nm
val case_suffixes = ["_case","_rec","_rec_set","_rep_set","_update","_Tuple_Iso"]
val spec_type = case (Datatype.info_of_constr thy (nm,T)) of
SOME _ => Constructor
| NONE => if Locale.defined thy nm then Locale else
if exists (fn n => String.isSuffix n nm) case_suffixes then Case else Definition
fun clean_def_name nm = if String.isSuffix "_raw" nm then (unsuffix "_raw" nm) else nm
val entry = {name = nm, def_name = Option.map clean_def_name def, spec_type = spec_type}
in
((id,entry),map_filter id_of body)
end
val raw_graph = map mk_graph_entry (Symtab.dest_list id_reduct_tab)
val graph = Int_Graph.make raw_graph
fun lookup_const (nm,T) =
let
val specs = Symtab.lookup id_reduct_tab nm
val args = Consts.typargs consts (nm,T)
in
Option.map (get_first (fn (id,(args',_)) => if could_match (args',args) then SOME id else NONE)) specs
|> Option.join
end
in
(graph,lookup_const)
end
local
open XML.Encode
fun spec_type_tostring spec_type = case spec_type of
Definition => "Definition"
| Constructor => "Constructor"
| Locale => "Locale"
| Case => "Case"
in
fun encode_entry (e as {name, def_name, spec_type} : entry) =
(triple string (option string) string) (name,def_name,spec_type_tostring spec_type)
val encode_graph = Int_Graph.encode XML.Encode.int encode_entry
end
local
open XML.Decode
fun spec_type_fromstring str = case str of
"Definition" => Definition
| "Constructor" => Constructor
| "Locale" => Locale
| "Case" => Case
| _ => error "Unknown spec type"
fun triple_to_entry (name,def_name,spec_type) = ({name = name, def_name = def_name,
spec_type = spec_type_fromstring spec_type} : entry)
in
val decode_entry =
(triple string (option string) string)
fun decode_graph body = Int_Graph.decode XML.Decode.int decode_entry body
|> Int_Graph.map (fn _ => triple_to_entry)
end
end