1 (* Title: Tools/code/code_thingol.ML
3 Author: Florian Haftmann, TU Muenchen
5 Intermediate language ("Thin-gol") representing executable code.
16 signature BASIC_CODE_THINGOL =
20 DictConst of string * dict list list
21 | DictVar of string list * (vname * (int * int));
23 `%% of string * itype list
25 type const = string * (dict list list * itype list (*types of arguments*))
30 | `|-> of (vname * itype) * iterm
31 | ICase of ((iterm * itype) * (iterm * iterm) list) * iterm;
32 (*((term, type), [(selector pattern, body term )]), primitive term)*)
33 val `-> : itype * itype -> itype;
34 val `--> : itype list * itype -> itype;
35 val `$$ : iterm * iterm list -> iterm;
36 val `|--> : (vname * itype) list * iterm -> iterm;
37 type typscheme = (vname * sort) list * itype;
40 signature CODE_THINGOL =
42 include BASIC_CODE_THINGOL;
43 val unfoldl: ('a -> ('a * 'b) option) -> 'a -> 'a * 'b list;
44 val unfoldr: ('a -> ('b * 'a) option) -> 'a -> 'b list * 'a;
45 val unfold_fun: itype -> itype list * itype;
46 val unfold_app: iterm -> iterm * iterm list;
47 val split_abs: iterm -> (((vname * iterm option) * itype) * iterm) option;
48 val unfold_abs: iterm -> ((vname * iterm option) * itype) list * iterm;
49 val split_let: iterm -> (((iterm * itype) * iterm) * iterm) option;
50 val unfold_let: iterm -> ((iterm * itype) * iterm) list * iterm;
51 val unfold_const_app: iterm ->
52 ((string * (dict list list * itype list)) * iterm list) option;
53 val collapse_let: ((vname * itype) * iterm) * iterm
54 -> (iterm * itype) * (iterm * iterm) list;
55 val eta_expand: (string * (dict list list * itype list)) * iterm list -> int -> iterm;
56 val contains_dictvar: iterm -> bool;
57 val fold_constnames: (string -> 'a -> 'a) -> iterm -> 'a -> 'a;
58 val fold_varnames: (string -> 'a -> 'a) -> iterm -> 'a -> 'a;
59 val fold_unbound_varnames: (string -> 'a -> 'a) -> iterm -> 'a -> 'a;
63 | Fun of typscheme * ((iterm list * iterm) * thm) list
64 | Datatype of (vname * sort) list * (string * itype list) list
65 | Datatypecons of string
66 | Class of vname * ((class * string) list * (string * itype) list)
67 | Classrel of class * class
69 | Classinst of (class * (string * (vname * sort) list))
70 * ((class * (string * (string * dict list list))) list
71 * ((string * const) * thm) list);
72 type code = def Graph.T;
75 val merge_code: code * code -> code;
76 val project_code: bool (*delete empty funs*)
77 -> string list (*hidden*) -> string list option (*selected*)
79 val empty_funs: code -> string list;
80 val is_cons: code -> string -> bool;
81 val add_eval_def: string (*bind name*) * (iterm * itype) -> code -> code;
83 val ensure_def: (string -> string) -> (transact -> def * transact) -> string
84 -> transact -> transact;
85 val start_transact: (transact -> 'a * transact) -> code -> 'a * code;
88 structure CodeThingol: CODE_THINGOL =
97 let val (x', xs') = unfoldl dest x1 in (x', xs' @ [x2]) end;
103 let val (xs', x') = unfoldr dest x2 in (x1::xs', x') end;
106 (** language core - types, pattern, expressions **)
108 (* language representation *)
113 DictConst of string * dict list list
114 | DictVar of string list * (vname * (int * int));
117 `%% of string * itype list
120 type const = string * (dict list list * itype list (*types of arguments*))
125 | `$ of iterm * iterm
126 | `|-> of (vname * itype) * iterm
127 | ICase of ((iterm * itype) * (iterm * iterm) list) * iterm;
128 (*see also signature*)
131 variable naming conventions
136 type constructor names tyco
138 const names (general) c (const)
140 class parameter names classparam
143 v, c, co, classparam also annotated with types etc.
152 instance (class, tyco) inst
155 fun ty1 `-> ty2 = "fun" `%% [ty1, ty2];
156 val op `--> = Library.foldr (op `->);
157 val op `$$ = Library.foldl (op `$);
158 val op `|--> = Library.foldr (op `|->);
160 val unfold_fun = unfoldr
161 (fn "fun" `%% [ty1, ty2] => SOME (ty1, ty2)
164 val unfold_app = unfoldl
165 (fn op `$ t => SOME t
169 (fn (v, ty) `|-> (t as ICase (((IVar w, _), [(p, t')]), _)) =>
170 if v = w then SOME (((v, SOME p), ty), t') else SOME (((v, NONE), ty), t)
171 | (v, ty) `|-> t => SOME (((v, NONE), ty), t)
174 val unfold_abs = unfoldr split_abs;
177 (fn ICase (((td, ty), [(p, t)]), _) => SOME (((p, ty), td), t)
180 val unfold_let = unfoldr split_let;
182 fun unfold_const_app t =
184 of (IConst c, ts) => SOME (c, ts)
187 fun fold_aiterms f (t as IConst _) = f t
188 | fold_aiterms f (t as IVar _) = f t
189 | fold_aiterms f (t1 `$ t2) = fold_aiterms f t1 #> fold_aiterms f t2
190 | fold_aiterms f (t as _ `|-> t') = f t #> fold_aiterms f t'
191 | fold_aiterms f (ICase (_, t)) = fold_aiterms f t;
193 fun fold_constnames f =
195 fun add (IConst (c, _)) = f c
197 in fold_aiterms add end;
199 fun fold_varnames f =
201 fun add (IVar v) = f v
202 | add ((v, _) `|-> _) = f v
204 in fold_aiterms add end;
206 fun fold_unbound_varnames f =
208 fun add _ (IConst _) = I
209 | add vs (IVar v) = if not (member (op =) vs v) then f v else I
210 | add vs (t1 `$ t2) = add vs t1 #> add vs t2
211 | add vs ((v, _) `|-> t) = add (insert (op =) v vs) t
212 | add vs (ICase (_, t)) = add vs t;
215 fun collapse_let (((v, ty), se), be as ICase (((IVar w, _), ds), _)) =
217 fun exists_v t = fold_unbound_varnames (fn w => fn b =>
218 b orelse v = w) t false;
219 in if v = w andalso forall (fn (t1, t2) =>
220 exists_v t1 orelse not (exists_v t2)) ds
222 else ((se, ty), [(IVar v, be)])
224 | collapse_let (((v, ty), se), be) =
225 ((se, ty), [(IVar v, be)])
227 fun eta_expand (c as (_, (_, tys)), ts) k =
231 val ctxt = (fold o fold_varnames) Name.declare ts Name.context;
232 val vs_tys = Name.names ctxt "a" ((curry Library.take l o curry Library.drop j) tys);
233 in vs_tys `|--> IConst c `$$ ts @ map (fn (v, _) => IVar v) vs_tys end;
235 fun contains_dictvar t =
237 fun contains (DictConst (_, dss)) = (fold o fold) contains dss
238 | contains (DictVar _) = K true;
241 (fn IConst (_, (dss, _)) => (fold o fold) contains dss | _ => I) t false
245 (** definitions, transactions **)
247 type typscheme = (vname * sort) list * itype;
250 | Fun of typscheme * ((iterm list * iterm) * thm) list
251 | Datatype of (vname * sort) list * (string * itype list) list
252 | Datatypecons of string
253 | Class of vname * ((class * string) list * (string * itype) list)
254 | Classrel of class * class
255 | Classparam of class
256 | Classinst of (class * (string * (vname * sort) list))
257 * ((class * (string * (string * dict list list))) list
258 * ((string * const) * thm) list);
260 type code = def Graph.T;
265 val empty_code = Graph.empty : code; (*read: "depends on"*)
267 fun ensure_bot name = Graph.default_node (name, Bot);
269 fun add_def_incr (name, Bot) code =
270 (case the_default Bot (try (Graph.get_node code) name)
271 of Bot => error "Attempted to add Bot to code"
273 | add_def_incr (name, def) code =
274 (case try (Graph.get_node code) name
275 of NONE => Graph.new_node (name, def) code
276 | SOME Bot => Graph.map_node name (K def) code
277 | SOME _ => error ("Tried to overwrite definition " ^ quote name));
279 fun add_dep (NONE, _) = I
280 | add_dep (SOME name1, name2) =
281 if name1 = name2 then I else Graph.add_edge (name1, name2);
283 val merge_code : code * code -> code = Graph.merge (K true);
285 fun project_code delete_empty_funs hidden raw_selected code =
287 fun is_empty_fun name = case Graph.get_node code name
288 of Fun (_, []) => true
290 val names = subtract (op =) hidden (Graph.keys code);
291 val deleted = Graph.all_preds code (filter is_empty_fun names);
292 val selected = case raw_selected
293 of NONE => names |> subtract (op =) deleted
295 |> delete_empty_funs ? subtract (op =) deleted
296 |> subtract (op =) hidden
297 |> Graph.all_succs code
298 |> delete_empty_funs ? subtract (op =) deleted
299 |> subtract (op =) hidden;
302 |> Graph.subgraph (member (op =) selected)
305 fun empty_funs code =
306 Graph.fold (fn (name, (Fun (_, []), _)) => cons name
309 fun is_cons code name = case Graph.get_node code name
310 of Datatypecons _ => true
314 (* transaction protocol *)
316 type transact = Graph.key option * code;
318 fun ensure_def labelled_name defgen name (dep, code) =
322 #> add_dep (dep, name)
323 #> curry defgen (SOME name)
325 #-> (fn def => add_def_incr (name, def))
330 |> add_def (can (Graph.get_node code) name)
334 fun start_transact f code =
337 |-> (fn x => fn (_, code) => (x, code));
339 fun add_eval_def (name, (t, ty)) code =
341 |> Graph.new_node (name, Fun (([], ty), [(([], t), Drule.dummy_thm)]))
342 |> fold (curry Graph.add_edge name) (Graph.keys code);
347 structure BasicCodeThingol: BASIC_CODE_THINGOL = CodeThingol;