src/Pure/Isar/keyword.ML
author wenzelm
Fri, 16 Mar 2012 20:33:33 +0100
changeset 47838 499d9bbd8de9
parent 47836 5c6955f487e5
child 47839 38aaa08fb37f
permissions -rw-r--r--
uniform keyword names within ML/Scala -- produce elisp names via external conversion;
discontinued obsolete Keyword.thy_switch;
     1 (*  Title:      Pure/Isar/keyword.ML
     2     Author:     Makarius
     3 
     4 Isar command keyword classification and global keyword tables.
     5 *)
     6 
     7 signature KEYWORD =
     8 sig
     9   type T
    10   val kind_of: T -> string
    11   val control: T
    12   val diag: T
    13   val thy_begin: T
    14   val thy_end: T
    15   val thy_heading: T
    16   val thy_decl: T
    17   val thy_script: T
    18   val thy_goal: T
    19   val thy_schematic_goal: T
    20   val qed: T
    21   val qed_block: T
    22   val qed_global: T
    23   val prf_heading: T
    24   val prf_goal: T
    25   val prf_block: T
    26   val prf_open: T
    27   val prf_close: T
    28   val prf_chain: T
    29   val prf_decl: T
    30   val prf_asm: T
    31   val prf_asm_goal: T
    32   val prf_script: T
    33   val kinds: string list
    34   val tag: string -> T -> T
    35   val tags_of: T -> string list
    36   val tag_theory: T -> T
    37   val tag_proof: T -> T
    38   val tag_ml: T -> T
    39   type spec = string * string list
    40   val spec: spec -> T
    41   val command_spec: string * spec -> string * T
    42   val get_lexicons: unit -> Scan.lexicon * Scan.lexicon
    43   val is_keyword: string -> bool
    44   val command_keyword: string -> T option
    45   val command_tags: string -> string list
    46   val dest: unit -> string list * string list
    47   val keyword_statusN: string
    48   val status: unit -> unit
    49   val define: string * T option -> unit
    50   val is_diag: string -> bool
    51   val is_control: string -> bool
    52   val is_regular: string -> bool
    53   val is_heading: string -> bool
    54   val is_theory_begin: string -> bool
    55   val is_theory: string -> bool
    56   val is_proof: string -> bool
    57   val is_theory_goal: string -> bool
    58   val is_proof_goal: string -> bool
    59   val is_schematic_goal: string -> bool
    60   val is_qed: string -> bool
    61   val is_qed_global: string -> bool
    62 end;
    63 
    64 structure Keyword: KEYWORD =
    65 struct
    66 
    67 (** keyword classification **)
    68 
    69 datatype T = Keyword of string * string list;  (*kind, tags (in canonical reverse order)*)
    70 
    71 fun kind s = Keyword (s, []);
    72 fun kind_of (Keyword (s, _)) = s;
    73 
    74 
    75 (* kinds *)
    76 
    77 val control = kind "control";
    78 val diag = kind "diag";
    79 val thy_begin = kind "thy_begin";
    80 val thy_end = kind "thy_end";
    81 val thy_heading = kind "thy_heading";
    82 val thy_decl = kind "thy_decl";
    83 val thy_script = kind "thy_script";
    84 val thy_goal = kind "thy_goal";
    85 val thy_schematic_goal = kind "thy_schematic_goal";
    86 val qed = kind "qed";
    87 val qed_block = kind "qed_block";
    88 val qed_global = kind "qed_global";
    89 val prf_heading = kind "prf_heading";
    90 val prf_goal = kind "prf_goal";
    91 val prf_block = kind "prf_block";
    92 val prf_open = kind "prf_open";
    93 val prf_close = kind "prf_close";
    94 val prf_chain = kind "prf_chain";
    95 val prf_decl = kind "prf_decl";
    96 val prf_asm = kind "prf_asm";
    97 val prf_asm_goal = kind "prf_asm_goal";
    98 val prf_script = kind "prf_script";
    99 
   100 val kinds =
   101   [control, diag, thy_begin, thy_end, thy_heading, thy_decl, thy_script, thy_goal,
   102     thy_schematic_goal, qed, qed_block, qed_global, prf_heading, prf_goal, prf_block, prf_open,
   103     prf_close, prf_chain, prf_decl, prf_asm, prf_asm_goal, prf_script]
   104  |> map kind_of;
   105 
   106 
   107 (* tags *)
   108 
   109 fun tag t (Keyword (s, ts)) = Keyword (s, update (op =) t ts);
   110 fun tags_of (Keyword (_, ts)) = ts;
   111 
   112 val tag_theory = tag "theory";
   113 val tag_proof = tag "proof";
   114 val tag_ml = tag "ML";
   115 
   116 
   117 (* external names *)
   118 
   119 val name_table = Symtab.make
   120   [("control",            control),
   121    ("diag",               diag),
   122    ("thy_begin",          thy_begin),
   123    ("thy_end",            thy_end),
   124    ("thy_heading",        thy_heading),
   125    ("thy_decl",           thy_decl),
   126    ("thy_script",         thy_script),
   127    ("thy_goal",           thy_goal),
   128    ("thy_schematic_goal", thy_schematic_goal),
   129    ("qed",                qed),
   130    ("qed_block",          qed_block),
   131    ("qed_global",         qed_global),
   132    ("prf_heading",        prf_heading),
   133    ("prf_goal",           prf_goal),
   134    ("prf_block",          prf_block),
   135    ("prf_open",           prf_open),
   136    ("prf_close",          prf_close),
   137    ("prf_chain",          prf_chain),
   138    ("prf_decl",           prf_decl),
   139    ("prf_asm",            prf_asm),
   140    ("prf_asm_goal",       prf_asm_goal),
   141    ("prf_script",         prf_script)];
   142 
   143 type spec = string * string list;
   144 
   145 fun spec (kind, tags) =
   146   (case Symtab.lookup name_table kind of
   147     SOME k => k |> fold tag tags
   148   | NONE => error ("Unknown outer syntax keyword kind " ^ quote kind));
   149 
   150 fun command_spec (name, s) = (name, spec s);
   151 
   152 
   153 
   154 (** global keyword tables **)
   155 
   156 type keywords =
   157  {lexicons: Scan.lexicon * Scan.lexicon,  (*minor, major*)
   158   commands: T Symtab.table};  (*command classification*)
   159 
   160 fun make_keywords (lexicons, commands) : keywords =
   161   {lexicons = lexicons, commands = commands};
   162 
   163 local
   164 
   165 val global_keywords =
   166   Unsynchronized.ref (make_keywords ((Scan.empty_lexicon, Scan.empty_lexicon), Symtab.empty));
   167 
   168 in
   169 
   170 fun get_keywords () = ! global_keywords;
   171 
   172 fun change_keywords f = CRITICAL (fn () =>
   173   Unsynchronized.change global_keywords
   174     (fn {lexicons, commands} => make_keywords (f (lexicons, commands))));
   175 
   176 end;
   177 
   178 fun get_lexicons () = #lexicons (get_keywords ());
   179 fun get_commands () = #commands (get_keywords ());
   180 
   181 
   182 (* lookup *)
   183 
   184 fun is_keyword s =
   185   let
   186     val (minor, major) = get_lexicons ();
   187     val syms = Symbol.explode s;
   188   in Scan.is_literal minor syms orelse Scan.is_literal major syms end;
   189 
   190 fun command_keyword name = Symtab.lookup (get_commands ()) name;
   191 fun command_tags name = these (Option.map tags_of (command_keyword name));
   192 
   193 fun dest () = pairself (sort_strings o Scan.dest_lexicon) (get_lexicons ());
   194 
   195 
   196 (* status *)
   197 
   198 val keyword_statusN = "keyword_status";
   199 
   200 fun status_message m s =
   201   Position.setmp_thread_data Position.none
   202     (if print_mode_active keyword_statusN then Output.protocol_message m else writeln) s;
   203 
   204 fun keyword_status name =
   205   status_message (Isabelle_Markup.keyword_decl name)
   206     ("Outer syntax keyword " ^ quote name);
   207 
   208 fun command_status (name, kind) =
   209   status_message (Isabelle_Markup.command_decl name (kind_of kind))
   210     ("Outer syntax keyword " ^ quote name ^ " :: " ^ kind_of kind);
   211 
   212 fun status () =
   213   let
   214     val {lexicons = (minor, _), commands} = get_keywords ();
   215     val _ = List.app keyword_status (sort_strings (Scan.dest_lexicon minor));
   216     val _ = List.app command_status (sort_wrt #1 (Symtab.dest commands));
   217   in () end;
   218 
   219 
   220 (* define *)
   221 
   222 fun define (name, NONE) =
   223      (change_keywords (fn ((minor, major), commands) =>
   224         let
   225           val minor' = Scan.extend_lexicon (Symbol.explode name) minor;
   226         in ((minor', major), commands) end);
   227       keyword_status name)
   228   | define (name, SOME kind) =
   229      (change_keywords (fn ((minor, major), commands) =>
   230         let
   231           val major' = Scan.extend_lexicon (Symbol.explode name) major;
   232           val commands' = Symtab.update (name, kind) commands;
   233         in ((minor, major'), commands') end);
   234       command_status (name, kind));
   235 
   236 
   237 (* command categories *)
   238 
   239 fun command_category ks name =
   240   (case command_keyword name of
   241     NONE => false
   242   | SOME k => member (op = o pairself kind_of) ks k);
   243 
   244 val is_diag = command_category [diag];
   245 val is_control = command_category [control];
   246 val is_regular = not o command_category [diag, control];
   247 
   248 val is_heading = command_category [thy_heading, prf_heading];
   249 
   250 val is_theory_begin = command_category [thy_begin];
   251 
   252 val is_theory = command_category
   253   [thy_begin, thy_end, thy_heading, thy_decl, thy_script, thy_goal, thy_schematic_goal];
   254 
   255 val is_proof = command_category
   256   [qed, qed_block, qed_global, prf_heading, prf_goal, prf_block, prf_open, prf_close,
   257     prf_chain, prf_decl, prf_asm, prf_asm_goal, prf_script];
   258 
   259 val is_theory_goal = command_category [thy_goal, thy_schematic_goal];
   260 val is_proof_goal = command_category [prf_goal, prf_asm_goal];
   261 val is_schematic_goal = command_category [thy_schematic_goal];
   262 val is_qed = command_category [qed, qed_block];
   263 val is_qed_global = command_category [qed_global];
   264 
   265 end;
   266