src/Pure/defs.ML
changeset 16982 4600e74aeb0d
parent 16936 93772bd33871
child 17223 430edc6b7826
equal deleted inserted replaced
16981:2ae3f621d076 16982:4600e74aeb0d
     1 (*  Title:      Pure/General/defs.ML
     1 (*  Title:      Pure/General/defs.ML
     2     ID:         $Id$
     2     ID:         $Id$
     3     Author:     Steven Obua, TU Muenchen
     3     Author:     Steven Obua, TU Muenchen
     4 
     4 
     5     Checks if definitions preserve consistency of logic by enforcing
     5 Checks if definitions preserve consistency of logic by enforcing that
     6     that there are no cyclic definitions. The algorithm is described in
     6 there are no cyclic definitions. The algorithm is described in "An
     7     "An Algorithm for Determining Definitional Cycles in Higher-Order Logic with Overloading",
     7 Algorithm for Determining Definitional Cycles in Higher-Order Logic
     8     Steven Obua, technical report, to be written :-)
     8 with Overloading", Steven Obua, technical report, to be written :-)
     9 *)
     9 *)
    10 
    10 
    11 signature DEFS =
    11 signature DEFS =
    12 sig
    12 sig
       
    13   (*true: record the full chain of definitions that lead to a circularity*)
       
    14   val chain_history: bool ref
    13   type graph
    15   type graph
    14   val empty: graph
    16   val empty: graph
    15   val declare: string * typ -> graph -> graph
    17   val declare: theory -> string * typ -> graph -> graph
    16   val define: Pretty.pp -> string * typ -> string -> (string * typ) list -> graph -> graph
    18   val define: theory -> string * typ -> string -> (string * typ) list -> graph -> graph
    17   val finalize: string * typ -> graph -> graph
    19   val finalize: theory -> string * typ -> graph -> graph
    18   val merge: Pretty.pp -> graph -> graph -> graph
    20   val merge: Pretty.pp -> graph -> graph -> graph
    19 
    21   val finals: graph -> typ list Symtab.table
    20   val finals : graph -> (typ list) Symtab.table
       
    21 
       
    22   (* If set to true then the exceptions CIRCULAR and INFINITE_CHAIN return the full
       
    23      chain of definitions that lead to the exception. In the beginning, chain_history
       
    24      is initialized with the Isabelle environment variable DEFS_CHAIN_HISTORY. *)
       
    25   val set_chain_history : bool -> unit
       
    26   val chain_history : unit -> bool
       
    27 
       
    28   datatype overloadingstate = Open | Closed | Final
    22   datatype overloadingstate = Open | Closed | Final
    29 
    23   val overloading_info: graph -> string -> (typ * (string*typ) list * overloadingstate) option
    30   val overloading_info : graph -> string -> (typ * (string*typ) list * overloadingstate) option
    24   val monomorphic: graph -> string -> bool
    31   val fast_overloading_info : graph -> string -> (typ * int * overloadingstate) option
       
    32 end
    25 end
    33 
    26 
    34 structure Defs :> DEFS = struct
    27 structure Defs :> DEFS = struct
    35 
    28 
    36 type tyenv = Type.tyenv
    29 type tyenv = Type.tyenv
    59 fun get_defnode' graph noderef defname =
    52 fun get_defnode' graph noderef defname =
    60     Symtab.lookup (get_nodedefs (the (Symtab.lookup (graph, noderef))), defname)
    53     Symtab.lookup (get_nodedefs (the (Symtab.lookup (graph, noderef))), defname)
    61 
    54 
    62 fun table_size table = Symtab.foldl (fn (x, _) => x+1) (0, table)
    55 fun table_size table = Symtab.foldl (fn (x, _) => x+1) (0, table)
    63 
    56 
    64 datatype graphaction = Declare of string * typ
    57 datatype graphaction =
    65                      | Define of string * typ * string * string * (string * typ) list
    58     Declare of string * typ
    66                      | Finalize of string * typ
    59   | Define of string * typ * string * string * (string * typ) list
    67 
    60   | Finalize of string * typ
    68 type graph = int * (string Symtab.table) * (graphaction list) * (node Symtab.table)
    61 
    69 
    62 type graph = int * string Symtab.table * graphaction list * node Symtab.table
    70 val CHAIN_HISTORY =
    63 
    71     let
    64 val chain_history = ref true
    72       fun f c = if Char.isSpace c then "" else String.str (Char.toUpper c)
       
    73       val env = String.translate f (getenv "DEFS_CHAIN_HISTORY")
       
    74     in
       
    75       ref (env = "ON" orelse env = "TRUE")
       
    76     end
       
    77 
       
    78 fun set_chain_history b = CHAIN_HISTORY := b
       
    79 fun chain_history () = !CHAIN_HISTORY
       
    80 
    65 
    81 val empty = (0, Symtab.empty, [], Symtab.empty)
    66 val empty = (0, Symtab.empty, [], Symtab.empty)
    82 
    67 
    83 exception DEFS of string;
    68 exception DEFS of string;
    84 exception CIRCULAR of (typ * string * string) list;
    69 exception CIRCULAR of (typ * string * string) list;
    97 fun checkT' (Type (a, Ts)) = Type (a, map checkT' Ts)
    82 fun checkT' (Type (a, Ts)) = Type (a, map checkT' Ts)
    98   | checkT' (TFree (a, _)) = TVar ((a, 0), [])        (* FIXME !? *)
    83   | checkT' (TFree (a, _)) = TVar ((a, 0), [])        (* FIXME !? *)
    99   | checkT' (TVar ((a, 0), _)) = TVar ((a, 0), [])
    84   | checkT' (TVar ((a, 0), _)) = TVar ((a, 0), [])
   100   | checkT' (T as TVar _) = raise TYPE ("Illegal schematic type variable encountered", [T], []);
    85   | checkT' (T as TVar _) = raise TYPE ("Illegal schematic type variable encountered", [T], []);
   101 
    86 
   102 val checkT = Term.compress_type o checkT';
    87 fun checkT thy = Compress.typ thy o checkT';
   103 
    88 
   104 fun rename ty1 ty2 = Logic.incr_tvar ((maxidx_of_typ ty1)+1) ty2;
    89 fun rename ty1 ty2 = Logic.incr_tvar ((maxidx_of_typ ty1)+1) ty2;
   105 
    90 
   106 fun subst_incr_tvar inc t =
    91 fun subst_incr_tvar inc t =
   107     if (inc > 0) then
    92     if (inc > 0) then
   151       case unify ty1 ty2 of
   136       case unify ty1 ty2 of
   152         NONE => NONE
   137         NONE => NONE
   153       | SOME s => SOME (max, merge s1 s, merge s2 s)
   138       | SOME s => SOME (max, merge s1 s, merge s2 s)
   154     end
   139     end
   155 
   140 
   156 fun can_be_unified_r ty1 ty2 =
   141 fun can_be_unified_r ty1 ty2 = is_some (unify ty1 (rename ty1 ty2))
   157     let
   142 fun can_be_unified ty1 ty2 = is_some (unify ty1 ty2)
   158       val ty2 = rename ty1 ty2
       
   159     in
       
   160       case unify ty1 ty2 of
       
   161         NONE => false
       
   162       | _ => true
       
   163     end
       
   164 
       
   165 fun can_be_unified ty1 ty2 =
       
   166     case unify ty1 ty2 of
       
   167       NONE => false
       
   168     | _ => true
       
   169 
   143 
   170 fun normalize_edge_idx (edge as (maxidx, u1, v1, history)) =
   144 fun normalize_edge_idx (edge as (maxidx, u1, v1, history)) =
   171     if maxidx <= 1000000 then edge else
   145     if maxidx <= 1000000 then edge else
   172     let
   146     let
   173 
   147 
   242                g
   216                g
   243              else
   217              else
   244                def_err "constant is already declared with different type"
   218                def_err "constant is already declared with different type"
   245            end
   219            end
   246 
   220 
   247 fun declare'' g (name, ty) = declare' g (name, checkT ty)
   221 fun declare'' thy g (name, ty) = declare' g (name, checkT thy ty)
   248 
   222 
   249 val axcounter = ref (IntInf.fromInt 0)
   223 val axcounter = ref (IntInf.fromInt 0)
   250 fun newaxname axmap axname =
   224 fun newaxname axmap axname =
   251     let
   225     let
   252       val c = !axcounter
   226       val c = !axcounter
   328                         fun connect (maxidx2, alpha2, beta2, history) =
   302                         fun connect (maxidx2, alpha2, beta2, history) =
   329                             case unify_r (Int.max (maxidx1, maxidx2)) beta1 alpha2 of
   303                             case unify_r (Int.max (maxidx1, maxidx2)) beta1 alpha2 of
   330                               NONE => NONE
   304                               NONE => NONE
   331                             | SOME (max, sleft, sright) =>
   305                             | SOME (max, sleft, sright) =>
   332                               SOME (max, subst sleft alpha1, subst sright beta2,
   306                               SOME (max, subst sleft alpha1, subst sright beta2,
   333                                     if !CHAIN_HISTORY then
   307                                     if !chain_history then
   334                                       ((subst sleft beta1, bodyn, defname)::
   308                                       ((subst sleft beta1, bodyn, defname)::
   335                                        (subst_history sright history))
   309                                        (subst_history sright history))
   336                                     else [])
   310                                     else [])
   337                         val links' = List.mapPartial connect links
   311                         val links' = List.mapPartial connect links
   338                       in
   312                       in
   490       val actions' = (Define (mainref, ty, axname, orig_axname, body))::actions
   464       val actions' = (Define (mainref, ty, axname, orig_axname, body))::actions
   491     in
   465     in
   492       (cost+3, axmap, actions', graph)
   466       (cost+3, axmap, actions', graph)
   493     end handle ex => translate_ex axmap ex
   467     end handle ex => translate_ex axmap ex
   494 
   468 
   495 fun define'' (g as (cost, axmap, actions, graph)) (mainref, ty) orig_axname body =
   469 fun define'' thy (g as (cost, axmap, actions, graph)) (mainref, ty) orig_axname body =
   496     let
   470     let
   497       val ty = checkT ty
   471       val ty = checkT thy ty
   498       fun checkbody (n, t) =
   472       fun checkbody (n, t) =
   499           let
   473           let
   500             val (Node (_, _, _,_, closed)) = getnode graph n
   474             val (Node (_, _, _,_, closed)) = getnode graph n
   501           in
   475           in
   502             case closed of
   476             case closed of
   503               Final => NONE
   477               Final => NONE
   504             | _ => SOME (n, checkT t)
   478             | _ => SOME (n, checkT thy t)
   505           end
   479           end
   506       val body = distinct (List.mapPartial checkbody body)
   480       val body = distinct (List.mapPartial checkbody body)
   507       val (axmap, axname) = newaxname axmap orig_axname
   481       val (axmap, axname) = newaxname axmap orig_axname
   508     in
   482     in
   509       define' (cost, axmap, actions, graph) (mainref, ty) axname orig_axname body
   483       define' (cost, axmap, actions, graph) (mainref, ty) axname orig_axname body
   601           in
   575           in
   602             (cost+1, axmap, history', graph')
   576             (cost+1, axmap, history', graph')
   603           end
   577           end
   604       end
   578       end
   605 
   579 
   606 fun finalize'' g (noderef, ty) = finalize' g (noderef, checkT ty)
   580 fun finalize'' thy g (noderef, ty) = finalize' g (noderef, checkT thy ty)
   607 
   581 
   608 fun update_axname ax orig_ax (cost, axmap, history, graph) =
   582 fun update_axname ax orig_ax (cost, axmap, history, graph) =
   609   (cost, Symtab.update ((ax, orig_ax), axmap), history, graph)
   583   (cost, Symtab.update ((ax, orig_ax), axmap), history, graph)
   610 
   584 
   611 fun merge' (Declare cty, g) = declare' g cty
   585 fun merge' (Declare cty, g) = declare' g cty
   638         NONE => NONE
   612         NONE => NONE
   639       | SOME (Node (ty, defnodes, _, _, state)) =>
   613       | SOME (Node (ty, defnodes, _, _, state)) =>
   640         SOME (ty, map translate (Symtab.dest defnodes), state)
   614         SOME (ty, map translate (Symtab.dest defnodes), state)
   641     end
   615     end
   642 
   616 
   643 fun fast_overloading_info (_, _, _, graph) c =
   617 
   644     let
   618 (* monomorphic consts -- neither parametric nor ad-hoc polymorphism *)
   645       fun count (c, _) = c+1
   619 
   646     in
   620 fun monomorphicT (Type (_, Ts)) = forall monomorphicT Ts
   647       case Symtab.lookup (graph, c) of
   621   | monomorphicT _ = false
   648         NONE => NONE
   622 
   649       | SOME (Node (ty, defnodes, _, _, state)) =>
   623 fun monomorphic (_, _, _, graph) c =
   650         SOME (ty, Symtab.foldl count (0, defnodes), state)
   624   (case Symtab.lookup (graph, c) of
   651     end
   625     NONE => true
       
   626   | SOME (Node (ty, defnodes, _, _, _)) =>
       
   627       Symtab.min_key defnodes = Symtab.max_key defnodes andalso
       
   628       monomorphicT ty);
   652 
   629 
   653 
   630 
   654 
   631 
   655 (** diagnostics **)
   632 (** diagnostics **)
   656 
   633 
   661 fun pretty_path pp path = fold_rev (fn (T, c, def) =>
   638 fun pretty_path pp path = fold_rev (fn (T, c, def) =>
   662   fn [] => [Pretty.block (pretty_const pp (c, T))]
   639   fn [] => [Pretty.block (pretty_const pp (c, T))]
   663    | prts => Pretty.block (pretty_const pp (c, T) @
   640    | prts => Pretty.block (pretty_const pp (c, T) @
   664       [Pretty.brk 1, Pretty.str ("depends via " ^ quote def ^ " on")]) :: prts) path [];
   641       [Pretty.brk 1, Pretty.str ("depends via " ^ quote def ^ " on")]) :: prts) path [];
   665 
   642 
   666 fun chain_history_msg s =    (* FIXME huh!? *)
       
   667   if chain_history () then s ^ ": "
       
   668   else s ^ " (set DEFS_CHAIN_HISTORY=ON for full history): ";
       
   669 
       
   670 fun defs_circular pp path =
   643 fun defs_circular pp path =
   671   Pretty.str (chain_history_msg "Cyclic dependency of definitions") :: pretty_path pp path
   644   Pretty.str "Cyclic dependency of definitions: " :: pretty_path pp path
   672   |> Pretty.chunks |> Pretty.string_of;
   645   |> Pretty.chunks |> Pretty.string_of;
   673 
   646 
   674 fun defs_infinite_chain pp path =
   647 fun defs_infinite_chain pp path =
   675   Pretty.str (chain_history_msg "Infinite chain of definitions") :: pretty_path pp path
   648   Pretty.str "Infinite chain of definitions: " :: pretty_path pp path
   676   |> Pretty.chunks |> Pretty.string_of;
   649   |> Pretty.chunks |> Pretty.string_of;
   677 
   650 
   678 fun defs_clash def1 def2 = "Type clash in definitions " ^ quote def1 ^ " and " ^ quote def2;
   651 fun defs_clash def1 def2 = "Type clash in definitions " ^ quote def1 ^ " and " ^ quote def2;
   679 
   652 
   680 fun defs_final pp const =
   653 fun defs_final pp const =
   682   |> Pretty.block |> Pretty.string_of;
   655   |> Pretty.block |> Pretty.string_of;
   683 
   656 
   684 
   657 
   685 (* external interfaces *)
   658 (* external interfaces *)
   686 
   659 
   687 fun declare const defs =
   660 fun declare thy const defs =
   688   if_none (try (declare'' defs) const) defs;
   661   if_none (try (declare'' thy defs) const) defs;
   689 
   662 
   690 fun define pp const name rhs defs =
   663 fun define thy const name rhs defs =
   691   define'' defs const name rhs
   664   define'' thy defs const name rhs
   692     handle DEFS msg => sys_error msg
   665     handle DEFS msg => sys_error msg
   693       | CIRCULAR path => error (defs_circular pp path)
   666       | CIRCULAR path => error (defs_circular (Sign.pp thy) path)
   694       | INFINITE_CHAIN path => error (defs_infinite_chain pp path)
   667       | INFINITE_CHAIN path => error (defs_infinite_chain (Sign.pp thy) path)
   695       | CLASH (_, def1, def2) => error (defs_clash def1 def2)
   668       | CLASH (_, def1, def2) => error (defs_clash def1 def2)
   696       | FINAL const => error (defs_final pp const);
   669       | FINAL const => error (defs_final (Sign.pp thy) const);
   697 
   670 
   698 fun finalize const defs =
   671 fun finalize thy const defs =
   699   finalize'' defs const handle DEFS msg => sys_error msg;
   672   finalize'' thy defs const handle DEFS msg => sys_error msg;
   700 
   673 
   701 fun merge pp defs1 defs2 =
   674 fun merge pp defs1 defs2 =
   702   merge'' defs1 defs2
   675   merge'' defs1 defs2
   703     handle CIRCULAR namess => error (defs_circular pp namess)
   676     handle CIRCULAR namess => error (defs_circular pp namess)
   704       | INFINITE_CHAIN namess => error (defs_infinite_chain pp namess);
   677       | INFINITE_CHAIN namess => error (defs_infinite_chain pp namess);