35 string (* name of constant *) |
41 string (* name of constant *) |
36 * typ (* most general type of constant *) |
42 * typ (* most general type of constant *) |
37 * defnode Symtab.table (* a table of defnodes, each corresponding to 1 definition of the constant for a particular type, |
43 * defnode Symtab.table (* a table of defnodes, each corresponding to 1 definition of the constant for a particular type, |
38 indexed by axiom name *) |
44 indexed by axiom name *) |
39 * backref Symtab.table (* a table of all back references to this node, indexed by node name *) |
45 * backref Symtab.table (* a table of all back references to this node, indexed by node name *) |
|
46 * typ list (* a list of all finalized types *) |
40 |
47 |
41 and defnode = Defnode of |
48 and defnode = Defnode of |
42 typ (* type of the constant in this particular definition *) |
49 typ (* type of the constant in this particular definition *) |
43 * ((noderef * (string option * edgelabel list) list) Symtab.table) (* The edges, grouped by nodes. *) |
50 * ((noderef * (string option * edgelabel list) list) Symtab.table) (* The edges, grouped by nodes. *) |
44 |
51 |
45 and backref = Backref of |
52 and backref = Backref of |
46 noderef (* a reference to the node that has defnodes which reference a certain node A *) |
53 noderef (* the name of the node that has defnodes which reference a certain node A *) |
47 * (unit Symtab.table) (* the names of the defnodes that DIRECTLY reference A. *) |
54 * (unit Symtab.table) (* the names of the defnodes that DIRECTLY reference A. *) |
48 |
55 |
49 fun getnode graph noderef = the (Symtab.lookup (graph, noderef)) |
56 fun getnode graph noderef = the (Symtab.lookup (graph, noderef)) |
50 fun get_nodename (Node (n, _, _ ,_)) = n |
57 fun get_nodename (Node (n, _, _ ,_, _)) = n |
51 fun get_nodedefs (Node (_, _, defs, _)) = defs |
58 fun get_nodedefs (Node (_, _, defs, _, _)) = defs |
52 fun get_defnode (Node (_, _, defs, _)) defname = Symtab.lookup (defs, defname) |
59 fun get_defnode (Node (_, _, defs, _, _)) defname = Symtab.lookup (defs, defname) |
53 fun get_defnode' graph noderef defname = Symtab.lookup (get_nodedefs (the (Symtab.lookup (graph, noderef))), defname) |
60 fun get_defnode' graph noderef defname = Symtab.lookup (get_nodedefs (the (Symtab.lookup (graph, noderef))), defname) |
54 fun get_nodename (Node (n, _, _ ,_)) = n |
61 fun get_nodename (Node (n, _, _ , _, _)) = n |
55 |
62 |
56 |
63 datatype graphaction = Declare of string * typ |
57 (*fun t2list t = rev (Symtab.foldl (fn (l, d) => d::l) ([], t)) |
64 | Define of string * typ * string * (string * typ) list |
58 fun tmap f t = map (fn (a,b) => (a, f b)) t |
65 | Finalize of string * typ |
59 fun defnode2data (Defnode (typ, table)) = ("Defnode", typ, t2list table) |
|
60 fun backref2data (Backref (noderef, table)) = ("Backref", noderef, map fst (t2list table)) |
|
61 fun node2data (Node (s, t, defs, backs)) = ("Node", ("nodename", s), ("nodetyp", t), |
|
62 ("defs", tmap defnode2data (t2list defs)), ("backs", tmap backref2data (t2list backs))) |
|
63 fun graph2data g = ("Graph", tmap node2data (t2list g)) |
|
64 *) |
|
65 |
|
66 datatype graphaction = Declare of string * typ | Define of string * typ * string * (string * typ) list |
|
67 |
66 |
68 type graph = (graphaction list) * (node Symtab.table) |
67 type graph = (graphaction list) * (node Symtab.table) |
69 |
68 |
70 val empty = ([], Symtab.empty) |
69 val empty = ([], Symtab.empty) |
71 |
70 |
72 exception DEFS of string; |
71 exception DEFS of string; |
73 exception CIRCULAR of (typ * string * string) list; |
72 exception CIRCULAR of (typ * string * string) list; |
74 exception INFINITE_CHAIN of (typ * string * string) list; |
73 exception INFINITE_CHAIN of (typ * string * string) list; |
75 exception CLASH of string * string * string; |
74 exception CLASH of string * string * string; |
|
75 exception FINAL of string * typ; |
76 |
76 |
77 fun def_err s = raise (DEFS s) |
77 fun def_err s = raise (DEFS s) |
78 |
78 |
79 fun declare (actions, g) name ty = |
79 fun declare (actions, g) (cty as (name, ty)) = |
80 ((Declare (name, ty))::actions, |
80 ((Declare cty)::actions, |
81 Symtab.update_new ((name, Node (name, Type.varifyT(Type.strip_sorts ty), Symtab.empty, Symtab.empty)), g)) |
81 Symtab.update_new ((name, Node (name, Type.varifyT(Type.strip_sorts ty), Symtab.empty, Symtab.empty, [])), g)) |
82 handle Symtab.DUP _ => def_err "declare: constant is already defined" |
82 handle Symtab.DUP _ => def_err "constant is already declared" |
83 |
83 |
84 fun rename ty1 ty2 = incr_tvar ((maxidx_of_typ ty1)+1) ty2; |
84 fun rename ty1 ty2 = incr_tvar ((maxidx_of_typ ty1)+1) ty2; |
85 |
85 |
86 fun subst_incr_tvar inc t = |
86 fun subst_incr_tvar inc t = |
87 if (inc > 0) then |
87 if (inc > 0) then |
214 labelled_edges |
214 labelled_edges |
215 in |
215 in |
216 Symtab.foldl g (a, def_edges) |
216 Symtab.foldl g (a, def_edges) |
217 end |
217 end |
218 |
218 |
219 fun define (actions, graph) name ty axname body = |
219 fun define (actions, graph) (name, ty) axname body = |
220 let |
220 let |
221 val ty = checkT ty |
221 val ty = checkT ty |
222 val body = map (fn (n,t) => (n, checkT t)) body |
222 val body = map (fn (n,t) => (n, checkT t)) body |
223 val mainref = name |
223 val mainref = name |
224 val mainnode = (case Symtab.lookup (graph, mainref) of |
224 val mainnode = (case Symtab.lookup (graph, mainref) of |
225 NONE => def_err ("constant "^(quote mainref)^" is not declared") |
225 NONE => def_err ("constant "^(quote mainref)^" is not declared") |
226 | SOME n => n) |
226 | SOME n => n) |
227 val (Node (n, gty, defs, backs)) = mainnode |
227 val (Node (n, gty, defs, backs, finals)) = mainnode |
228 val _ = (if is_instance_r ty gty then () else def_err "type of constant does not match declared type") |
228 val _ = (if is_instance_r ty gty then () else def_err "type of constant does not match declared type") |
229 fun check_def (s, Defnode (ty', _)) = |
229 fun check_def (s, Defnode (ty', _)) = |
230 (if can_be_unified_r ty ty' then |
230 (if can_be_unified_r ty ty' then |
231 raise (CLASH (mainref, axname, s)) |
231 raise (CLASH (mainref, axname, s)) |
232 else if s = axname then |
232 else if s = axname then |
233 def_err "name of axiom is already used for another definition of this constant" |
233 def_err "name of axiom is already used for another definition of this constant" |
234 else true) |
234 else true) |
235 val _ = forall_table check_def defs |
235 val _ = forall_table check_def defs |
|
236 fun check_final finalty = |
|
237 (if can_be_unified_r finalty ty then |
|
238 raise (FINAL (mainref, finalty)) |
|
239 else |
|
240 true) |
|
241 val _ = forall check_final finals |
|
242 |
236 (* now we know that the only thing that can prevent acceptance of the definition is a cyclic dependency *) |
243 (* now we know that the only thing that can prevent acceptance of the definition is a cyclic dependency *) |
237 |
244 |
238 (* body contains the constants that this constant definition depends on. For each element of body, |
245 (* body contains the constants that this constant definition depends on. For each element of body, |
239 the function make_edges_to calculates a group of edges that connect this constant with |
246 the function make_edges_to calculates a group of edges that connect this constant with |
240 the constant that is denoted by the element of the body *) |
247 the constant that is denoted by the element of the body *) |
258 (swallowed, l) |
265 (swallowed, l) |
259 else |
266 else |
260 (case unify_r 0 bodyty def_ty of |
267 (case unify_r 0 bodyty def_ty of |
261 NONE => (swallowed, l) |
268 NONE => (swallowed, l) |
262 | SOME (maxidx, sigma1, sigma2) => |
269 | SOME (maxidx, sigma1, sigma2) => |
263 (is_instance bodyty def_ty, |
270 (is_instance_r bodyty def_ty, |
264 merge_labelled_edges l [(SOME def_name,[(maxidx, subst sigma1 ty, subst sigma2 def_ty, [])])])) |
271 merge_labelled_edges l [(SOME def_name,[(maxidx, subst sigma1 ty, subst sigma2 def_ty, [])])])) |
265 val (swallowed, edges) = Symtab.foldl make_edges ((false, []), bdefs) |
272 val (swallowed, edges) = Symtab.foldl make_edges ((false, []), bdefs) |
266 in |
273 in |
267 if swallowed then |
274 if swallowed orelse (exists (is_instance_r bodyty) bfinals) then |
268 (bodyn, edges) |
275 (bodyn, edges) |
269 else |
276 else |
270 (bodyn, [(NONE, [(maxidx, subst sigma1 ty, subst sigma2 general_btyp,[])])]@edges) |
277 (bodyn, [(NONE, [(maxidx, subst sigma1 ty, subst sigma2 general_btyp,[])])]@edges) |
271 end) |
278 end) |
272 end |
279 end |
273 |
280 |
274 fun update_edges (b as (bodyn, bodyty), edges) = |
281 fun update_edges (b as (bodyn, bodyty), edges) = |
337 fun hasNONElink ((NONE, _)::_) = true |
344 fun hasNONElink ((NONE, _)::_) = true |
338 | hasNONElink _ = false |
345 | hasNONElink _ = false |
339 |
346 |
340 fun install_backref graph noderef pointingnoderef pointingdefname = |
347 fun install_backref graph noderef pointingnoderef pointingdefname = |
341 let |
348 let |
342 val (Node (pname, _, _, _)) = getnode graph pointingnoderef |
349 val (Node (pname, _, _, _, _)) = getnode graph pointingnoderef |
343 val (Node (name, ty, defs, backs)) = getnode graph noderef |
350 val (Node (name, ty, defs, backs, finals)) = getnode graph noderef |
344 in |
351 in |
345 case Symtab.lookup (backs, pname) of |
352 case Symtab.lookup (backs, pname) of |
346 NONE => |
353 NONE => |
347 let |
354 let |
348 val defnames = Symtab.update ((pointingdefname, ()), Symtab.empty) |
355 val defnames = Symtab.update ((pointingdefname, ()), Symtab.empty) |
349 val backs = Symtab.update ((pname, Backref (pointingnoderef, defnames)), backs) |
356 val backs = Symtab.update ((pname, Backref (pointingnoderef, defnames)), backs) |
350 in |
357 in |
351 Symtab.update ((name, Node (name, ty, defs, backs)), graph) |
358 Symtab.update ((name, Node (name, ty, defs, backs, finals)), graph) |
352 end |
359 end |
353 | SOME (Backref (pointingnoderef, defnames)) => |
360 | SOME (Backref (pointingnoderef, defnames)) => |
354 let |
361 let |
355 val defnames = Symtab.update_new ((pointingdefname, ()), defnames) |
362 val defnames = Symtab.update_new ((pointingdefname, ()), defnames) |
356 val backs = Symtab.update ((pname, Backref (pointingnoderef, defnames)), backs) |
363 val backs = Symtab.update ((pname, Backref (pointingnoderef, defnames)), backs) |
357 in |
364 in |
358 Symtab.update ((name, Node (name, ty, defs, backs)), graph) |
365 Symtab.update ((name, Node (name, ty, defs, backs, finals)), graph) |
359 end |
366 end |
360 handle Symtab.DUP _ => graph |
367 handle Symtab.DUP _ => graph |
361 end |
368 end |
362 |
369 |
363 fun install_backrefs (graph, (_, (noderef, labelled_edges))) = |
370 fun install_backrefs (graph, (_, (noderef, labelled_edges))) = |
366 else |
373 else |
367 graph |
374 graph |
368 |
375 |
369 val graph = Symtab.foldl install_backrefs (graph, edges) |
376 val graph = Symtab.foldl install_backrefs (graph, edges) |
370 |
377 |
371 val (Node (_, _, _, backs)) = getnode graph mainref |
378 val (Node (_, _, _, backs, _)) = getnode graph mainref |
372 val graph = Symtab.update ((mainref, Node (n, gty, Symtab.update_new ((axname, thisDefnode), defs), backs)), graph) |
379 val graph = Symtab.update ((mainref, Node (n, gty, Symtab.update_new |
|
380 ((axname, thisDefnode), defs), backs, finals)), graph) |
373 |
381 |
374 (* Now we have to check all backreferences to this node and inform them about the new defnode. |
382 (* Now we have to check all backreferences to this node and inform them about the new defnode. |
375 In this section we also check for circularity. *) |
383 In this section we also check for circularity. *) |
376 fun update_backrefs ((backs, newedges), (nodename, Backref (noderef, defnames))) = |
384 fun update_backrefs ((backs, newedges), (nodename, Backref (noderef, defnames))) = |
377 let |
385 let |
438 |
446 |
439 val (backs, newedges) = Symtab.foldl update_backrefs ((Symtab.empty, []), backs) |
447 val (backs, newedges) = Symtab.foldl update_backrefs ((Symtab.empty, []), backs) |
440 |
448 |
441 (* If a Circular exception is thrown then we never reach this point. *) |
449 (* If a Circular exception is thrown then we never reach this point. *) |
442 (* Ok, the definition is consistent, let's update this node. *) |
450 (* Ok, the definition is consistent, let's update this node. *) |
443 val graph = Symtab.update ((mainref, Node (n, gty, Symtab.update ((axname, thisDefnode), defs), backs)), graph) |
451 val graph = Symtab.update ((mainref, Node (n, gty, Symtab.update |
|
452 ((axname, thisDefnode), defs), backs, finals)), graph) |
444 |
453 |
445 (* Furthermore, update all the other nodes that backreference this node. *) |
454 (* Furthermore, update all the other nodes that backreference this node. *) |
446 fun final_update_backrefs graph noderef defname none_edges this_edges = |
455 fun final_update_backrefs graph noderef defname none_edges this_edges = |
447 let |
456 let |
448 val node = getnode graph noderef |
457 val node = getnode graph noderef |
449 val (Node (nodename, nodety, defs, backs)) = node |
458 val (Node (nodename, nodety, defs, backs, finals)) = node |
450 val (Defnode (defnode_ty, defnode_edges)) = the (get_defnode node defname) |
459 val (Defnode (defnode_ty, defnode_edges)) = the (get_defnode node defname) |
451 val (_, defnode_links) = the (Symtab.lookup (defnode_edges, n)) |
460 val (_, defnode_links) = the (Symtab.lookup (defnode_edges, n)) |
452 |
461 |
453 fun update edges none_edges this_edges = |
462 fun update edges none_edges this_edges = |
454 let |
463 let |
465 ((NONE, _) :: edges) => update edges none_edges this_edges |
474 ((NONE, _) :: edges) => update edges none_edges this_edges |
466 | edges => update edges none_edges this_edges |
475 | edges => update edges none_edges this_edges |
467 val defnode_edges' = Symtab.update ((n, (mainref, defnode_links')), defnode_edges) |
476 val defnode_edges' = Symtab.update ((n, (mainref, defnode_links')), defnode_edges) |
468 val defs' = Symtab.update ((defname, Defnode (defnode_ty, defnode_edges')), defs) |
477 val defs' = Symtab.update ((defname, Defnode (defnode_ty, defnode_edges')), defs) |
469 in |
478 in |
470 Symtab.update ((nodename, Node (nodename, nodety, defs', backs)), graph) |
479 Symtab.update ((nodename, Node (nodename, nodety, defs', backs, finals)), graph) |
471 end |
480 end |
472 |
481 |
473 val graph = foldl (fn ((noderef, newedges),graph) => foldl (fn ((defname, none_edges, this_edges), graph) => |
482 val graph = foldl (fn ((noderef, newedges),graph) => foldl (fn ((defname, none_edges, this_edges), graph) => |
474 final_update_backrefs graph noderef defname none_edges this_edges) graph newedges) graph newedges |
483 final_update_backrefs graph noderef defname none_edges this_edges) graph newedges) graph newedges |
475 |
484 |
476 in |
485 in |
477 ((Define (name, ty, axname, body))::actions, graph) |
486 ((Define (name, ty, axname, body))::actions, graph) |
478 end |
487 end |
479 |
488 |
|
489 fun finalize' ((c, ty), graph) = |
|
490 case Symtab.lookup (graph, c) of |
|
491 NONE => def_err ("finalize: constant "^(quote c)^" is not declared") |
|
492 | SOME (Node (noderef, nodety, defs, backs, finals)) => |
|
493 let |
|
494 val nodety = checkT nodety |
|
495 in |
|
496 if (not (is_instance_r ty nodety)) then |
|
497 def_err ("finalize: only type instances of the declared constant "^(quote c)^" can be finalized") |
|
498 else if exists (is_instance_r ty) finals then |
|
499 graph |
|
500 else |
|
501 let |
|
502 val finals = ty :: finals |
|
503 val graph = Symtab.update ((noderef, Node(noderef, nodety, defs, backs, finals)), graph) |
|
504 fun update_backref ((graph, backs), (backrefname, Backref (_, backdefnames))) = |
|
505 let |
|
506 fun update_backdef ((graph, defnames), (backdefname, _)) = |
|
507 let |
|
508 val (backnode as Node (_, backty, backdefs, backbacks, backfinals)) = getnode graph backrefname |
|
509 val (Defnode (def_ty, all_edges)) = the (get_defnode backnode backdefname) |
|
510 val (defnames', all_edges') = |
|
511 case Symtab.lookup (all_edges, noderef) of |
|
512 NONE => sys_error "finalize: corrupt backref" |
|
513 | SOME (_, (NONE, edges)::rest) => |
|
514 let |
|
515 val edges' = List.filter (fn (_, _, beta, _) => not (is_instance_r beta ty)) edges |
|
516 in |
|
517 if edges' = [] then |
|
518 (defnames, Symtab.update ((noderef, (noderef, rest)), all_edges)) |
|
519 else |
|
520 (Symtab.update ((backdefname, ()), defnames), |
|
521 Symtab.update ((noderef, (noderef, (NONE, edges')::rest)), all_edges)) |
|
522 end |
|
523 val defnode' = Defnode (def_ty, all_edges') |
|
524 val backnode' = Node (backrefname, backty, Symtab.update ((backdefname, defnode'), backdefs), |
|
525 backbacks, backfinals) |
|
526 in |
|
527 (Symtab.update ((backrefname, backnode'), graph), defnames') |
|
528 end |
|
529 |
|
530 val (graph', defnames') = Symtab.foldl update_backdef ((graph, Symtab.empty), backdefnames) |
|
531 in |
|
532 (graph', if Symtab.is_empty defnames' then backs |
|
533 else Symtab.update ((backrefname, Backref (backrefname, defnames')), backs)) |
|
534 end |
|
535 val (graph', backs') = Symtab.foldl update_backref ((graph, Symtab.empty), backs) |
|
536 val Node (_, _, defs, _, _) = getnode graph' noderef |
|
537 in |
|
538 Symtab.update ((noderef, Node (noderef, nodety, defs, backs', finals)), graph') |
|
539 end |
|
540 end |
|
541 |
|
542 fun finalize (history, graph) c_ty = ((Finalize c_ty)::history, finalize' (c_ty, graph)) |
480 |
543 |
481 fun merge' (Declare (name, ty), g) = (declare g name ty handle _ => g) |
544 fun merge' (Declare cty, g) = (declare g cty handle _ => g) |
482 | merge' (Define (name, ty, axname, body), g as (_, graph)) = |
545 | merge' (Define (name, ty, axname, body), g as (_, graph)) = |
483 (case Symtab.lookup (graph, name) of |
546 (case Symtab.lookup (graph, name) of |
484 NONE => define g name ty axname body |
547 NONE => define g (name, ty) axname body |
485 | SOME (Node (_, _, defs, _)) => |
548 | SOME (Node (_, _, defs, _, _)) => |
486 (case Symtab.lookup (defs, axname) of |
549 (case Symtab.lookup (defs, axname) of |
487 NONE => define g name ty axname body |
550 NONE => define g (name, ty) axname body |
488 | SOME _ => g)) |
551 | SOME _ => g)) |
|
552 | merge' (Finalize finals, g) = (finalize g finals handle _ => g) |
489 |
553 |
490 fun merge (actions, _) g = foldr merge' g actions |
554 fun merge (actions, _) g = foldr merge' g actions |
|
555 |
|
556 fun finals (history, graph) = |
|
557 Symtab.foldl |
|
558 (fn (finals, (_, Node(name, _, _, _, ftys))) => Symtab.update_new ((name, ftys), finals)) |
|
559 (Symtab.empty, graph) |
491 |
560 |
492 end; |
561 end; |
493 |
562 |
494 |
563 |
495 |
564 |