src/Pure/ML/ml_antiquote.ML
author wenzelm
Fri, 16 Mar 2012 18:20:12 +0100
changeset 47836 5c6955f487e5
parent 47822 aae5566d6756
child 47858 15ce93dfe6da
permissions -rw-r--r--
outer syntax command definitions based on formal command_spec derived from theory header declarations;
wenzelm@27340
     1
(*  Title:      Pure/ML/ml_antiquote.ML
wenzelm@27340
     2
    Author:     Makarius
wenzelm@27340
     3
wenzelm@27340
     4
Common ML antiquotations.
wenzelm@27340
     5
*)
wenzelm@27340
     6
wenzelm@27340
     7
signature ML_ANTIQUOTE =
wenzelm@27340
     8
sig
wenzelm@27340
     9
  val variant: string -> Proof.context -> string * Proof.context
wenzelm@44446
    10
  val macro: binding -> Proof.context context_parser -> theory -> theory
wenzelm@44446
    11
  val inline: binding -> string context_parser -> theory -> theory
wenzelm@44446
    12
  val declaration: string -> binding -> string context_parser -> theory -> theory
wenzelm@44446
    13
  val value: binding -> string context_parser -> theory -> theory
wenzelm@27340
    14
end;
wenzelm@27340
    15
wenzelm@27340
    16
structure ML_Antiquote: ML_ANTIQUOTE =
wenzelm@27340
    17
struct
wenzelm@27340
    18
wenzelm@27340
    19
(** generic tools **)
wenzelm@27340
    20
wenzelm@27340
    21
(* ML names *)
wenzelm@27340
    22
wenzelm@37216
    23
structure Names = Proof_Data
wenzelm@27340
    24
(
wenzelm@27340
    25
  type T = Name.context;
wenzelm@27340
    26
  fun init _ = ML_Syntax.reserved;
wenzelm@27340
    27
);
wenzelm@27340
    28
wenzelm@27340
    29
fun variant a ctxt =
wenzelm@27340
    30
  let
wenzelm@37216
    31
    val names = Names.get ctxt;
wenzelm@44208
    32
    val (b, names') = Name.variant a names;
wenzelm@37216
    33
    val ctxt' = Names.put names' ctxt;
wenzelm@27340
    34
  in (b, ctxt') end;
wenzelm@27340
    35
wenzelm@27340
    36
wenzelm@27340
    37
(* specific antiquotations *)
wenzelm@27340
    38
wenzelm@27379
    39
fun macro name scan = ML_Context.add_antiq name
wenzelm@27868
    40
  (fn _ => scan :|-- (fn ctxt => Scan.depend (fn _ => Scan.succeed
wenzelm@35019
    41
    (Context.Proof ctxt, fn background => (K ("", ""), background)))));
wenzelm@27379
    42
wenzelm@27340
    43
fun inline name scan = ML_Context.add_antiq name
wenzelm@35019
    44
  (fn _ => scan >> (fn s => fn background => (K ("", s), background)));
wenzelm@27340
    45
wenzelm@27340
    46
fun declaration kind name scan = ML_Context.add_antiq name
wenzelm@35019
    47
  (fn _ => scan >> (fn s => fn background =>
wenzelm@27340
    48
    let
wenzelm@44446
    49
      val (a, background') =
wenzelm@44446
    50
        variant (translate_string (fn "." => "_" | c => c) (Binding.name_of name)) background;
wenzelm@27340
    51
      val env = kind ^ " " ^ a ^ " = " ^ s ^ ";\n";
wenzelm@41734
    52
      val body = "Isabelle." ^ a;
wenzelm@27340
    53
    in (K (env, body), background') end));
wenzelm@27340
    54
wenzelm@27340
    55
val value = declaration "val";
wenzelm@27340
    56
wenzelm@27340
    57
wenzelm@27340
    58
wenzelm@30231
    59
(** misc antiquotations **)
wenzelm@27340
    60
wenzelm@44446
    61
val _ = Context.>> (Context.map_theory
wenzelm@40369
    62
wenzelm@44446
    63
 (inline (Binding.name "assert")
wenzelm@44446
    64
    (Scan.succeed "(fn b => if b then () else raise General.Fail \"Assertion failed\")") #>
wenzelm@36162
    65
wenzelm@44446
    66
  inline (Binding.name "make_string") (Scan.succeed ml_make_string) #>
wenzelm@27340
    67
wenzelm@44446
    68
  value (Binding.name "binding")
wenzelm@47836
    69
    (Scan.lift (Parse.position Args.name) >> ML_Syntax.make_binding) #>
wenzelm@27340
    70
wenzelm@44446
    71
  value (Binding.name "theory")
wenzelm@44446
    72
    (Scan.lift Args.name >> (fn name =>
wenzelm@44446
    73
      "Context.get_theory (ML_Context.the_global_context ()) " ^ ML_Syntax.print_string name)
wenzelm@44446
    74
    || Scan.succeed "ML_Context.the_global_context ()") #>
wenzelm@27340
    75
wenzelm@44446
    76
  value (Binding.name "context") (Scan.succeed "ML_Context.the_local_context ()") #>
wenzelm@27340
    77
wenzelm@44446
    78
  inline (Binding.name "typ") (Args.typ >> (ML_Syntax.atomic o ML_Syntax.print_typ)) #>
wenzelm@44446
    79
  inline (Binding.name "term") (Args.term >> (ML_Syntax.atomic o ML_Syntax.print_term)) #>
wenzelm@44446
    80
  inline (Binding.name "prop") (Args.prop >> (ML_Syntax.atomic o ML_Syntax.print_term)) #>
wenzelm@27379
    81
wenzelm@44446
    82
  macro (Binding.name "let")
wenzelm@44446
    83
    (Args.context --
wenzelm@44446
    84
      Scan.lift
wenzelm@44446
    85
        (Parse.and_list1 (Parse.and_list1 Args.name_source -- (Args.$$$ "=" |-- Args.name_source)))
wenzelm@44446
    86
        >> (fn (ctxt, args) => #2 (Proof_Context.match_bind true args ctxt))) #>
wenzelm@27379
    87
wenzelm@44446
    88
  macro (Binding.name "note")
wenzelm@44446
    89
    (Args.context :|-- (fn ctxt =>
wenzelm@44446
    90
      Parse.and_list1' (Scan.lift (Args.opt_thm_name I "=") -- Attrib.thms
wenzelm@44446
    91
        >> (fn ((a, srcs), ths) =>
wenzelm@44446
    92
          ((a, map (Attrib.attribute (Proof_Context.theory_of ctxt)) srcs), [(ths, [])])))
wenzelm@44446
    93
      >> (fn args => #2 (Proof_Context.note_thmss "" args ctxt)))) #>
wenzelm@27340
    94
wenzelm@44446
    95
  value (Binding.name "ctyp") (Args.typ >> (fn T =>
wenzelm@44446
    96
    "Thm.ctyp_of (ML_Context.the_global_context ()) " ^ ML_Syntax.atomic (ML_Syntax.print_typ T))) #>
wenzelm@27340
    97
wenzelm@44446
    98
  value (Binding.name "cterm") (Args.term >> (fn t =>
wenzelm@47836
    99
    "Thm.cterm_of (ML_Context.the_global_context ()) " ^ ML_Syntax.atomic (ML_Syntax.print_term t))) #>
wenzelm@27340
   100
wenzelm@44446
   101
  value (Binding.name "cprop") (Args.prop >> (fn t =>
wenzelm@47836
   102
    "Thm.cterm_of (ML_Context.the_global_context ()) " ^ ML_Syntax.atomic (ML_Syntax.print_term t))) #>
wenzelm@44446
   103
wenzelm@44446
   104
  value (Binding.name "cpat")
wenzelm@44446
   105
    (Args.context --
wenzelm@44446
   106
      Scan.lift Args.name_source >> uncurry Proof_Context.read_term_pattern >> (fn t =>
wenzelm@44446
   107
        "Thm.cterm_of (ML_Context.the_global_context ()) " ^
wenzelm@44446
   108
          ML_Syntax.atomic (ML_Syntax.print_term t)))));
wenzelm@27340
   109
wenzelm@27340
   110
wenzelm@35396
   111
(* type classes *)
wenzelm@35396
   112
wenzelm@35677
   113
fun class syn = Args.context -- Scan.lift Args.name_source >> (fn (ctxt, s) =>
wenzelm@43231
   114
  Proof_Context.read_class ctxt s
wenzelm@43162
   115
  |> syn ? Lexicon.mark_class
wenzelm@35396
   116
  |> ML_Syntax.print_string);
wenzelm@35396
   117
wenzelm@44446
   118
val _ = Context.>> (Context.map_theory
wenzelm@44446
   119
 (inline (Binding.name "class") (class false) #>
wenzelm@44446
   120
  inline (Binding.name "class_syntax") (class true) #>
wenzelm@35396
   121
wenzelm@44446
   122
  inline (Binding.name "sort")
wenzelm@44446
   123
    (Args.context -- Scan.lift Args.name_source >> (fn (ctxt, s) =>
wenzelm@44446
   124
      ML_Syntax.atomic (ML_Syntax.print_sort (Syntax.read_sort ctxt s))))));
wenzelm@35396
   125
wenzelm@35396
   126
wenzelm@35361
   127
(* type constructors *)
wenzelm@27340
   128
wenzelm@36950
   129
fun type_name kind check = Args.context -- Scan.lift (Parse.position Args.name_source)
wenzelm@35401
   130
  >> (fn (ctxt, (s, pos)) =>
wenzelm@35401
   131
    let
wenzelm@43231
   132
      val Type (c, _) = Proof_Context.read_type_name_proper ctxt false s;
wenzelm@43339
   133
      val decl = Type.the_decl (Proof_Context.tsig_of ctxt) (c, pos);
wenzelm@35401
   134
      val res =
wenzelm@35401
   135
        (case try check (c, decl) of
wenzelm@35401
   136
          SOME res => res
wenzelm@35401
   137
        | NONE => error ("Not a " ^ kind ^ ": " ^ quote c ^ Position.str_of pos));
wenzelm@35401
   138
    in ML_Syntax.print_string res end);
wenzelm@27340
   139
wenzelm@44446
   140
val _ = Context.>> (Context.map_theory
wenzelm@44446
   141
 (inline (Binding.name "type_name")
wenzelm@44446
   142
    (type_name "logical type" (fn (c, Type.LogicalType _) => c)) #>
wenzelm@44446
   143
  inline (Binding.name "type_abbrev")
wenzelm@44446
   144
    (type_name "type abbreviation" (fn (c, Type.Abbreviation _) => c)) #>
wenzelm@44446
   145
  inline (Binding.name "nonterminal")
wenzelm@44446
   146
    (type_name "nonterminal" (fn (c, Type.Nonterminal) => c)) #>
wenzelm@44446
   147
  inline (Binding.name "type_syntax")
wenzelm@44446
   148
    (type_name "type" (fn (c, _) => Lexicon.mark_type c))));
wenzelm@35361
   149
wenzelm@35361
   150
wenzelm@35361
   151
(* constants *)
wenzelm@27340
   152
wenzelm@36950
   153
fun const_name check = Args.context -- Scan.lift (Parse.position Args.name_source)
wenzelm@35401
   154
  >> (fn (ctxt, (s, pos)) =>
wenzelm@35401
   155
    let
wenzelm@43231
   156
      val Const (c, _) = Proof_Context.read_const_proper ctxt false s;
wenzelm@43231
   157
      val res = check (Proof_Context.consts_of ctxt, c)
wenzelm@35401
   158
        handle TYPE (msg, _, _) => error (msg ^ Position.str_of pos);
wenzelm@35401
   159
    in ML_Syntax.print_string res end);
wenzelm@27340
   160
wenzelm@44446
   161
val _ = Context.>> (Context.map_theory
wenzelm@44446
   162
 (inline (Binding.name "const_name")
wenzelm@44702
   163
    (const_name (fn (consts, c) => (Consts.the_const consts c; c))) #>
wenzelm@44446
   164
  inline (Binding.name "const_abbrev")
wenzelm@44446
   165
    (const_name (fn (consts, c) => (Consts.the_abbreviation consts c; c))) #>
wenzelm@44446
   166
  inline (Binding.name "const_syntax")
wenzelm@44446
   167
    (const_name (fn (_, c) => Lexicon.mark_const c)) #>
wenzelm@35401
   168
wenzelm@44446
   169
  inline (Binding.name "syntax_const")
wenzelm@44446
   170
    (Args.context -- Scan.lift (Parse.position Args.name) >> (fn (ctxt, (c, pos)) =>
wenzelm@44446
   171
      if is_some (Syntax.lookup_const (Proof_Context.syn_of ctxt) c)
wenzelm@44446
   172
      then ML_Syntax.print_string c
wenzelm@44446
   173
      else error ("Unknown syntax const: " ^ quote c ^ Position.str_of pos))) #>
wenzelm@35401
   174
wenzelm@44446
   175
  inline (Binding.name "const")
wenzelm@44446
   176
    (Args.context -- Scan.lift Args.name_source -- Scan.optional
wenzelm@44446
   177
        (Scan.lift (Args.$$$ "(") |-- Parse.enum1' "," Args.typ --| Scan.lift (Args.$$$ ")")) []
wenzelm@44446
   178
      >> (fn ((ctxt, raw_c), Ts) =>
wenzelm@44446
   179
        let
wenzelm@44446
   180
          val Const (c, _) = Proof_Context.read_const_proper ctxt true raw_c;
wenzelm@44446
   181
          val const = Const (c, Consts.instance (Proof_Context.consts_of ctxt) (c, Ts));
wenzelm@44446
   182
        in ML_Syntax.atomic (ML_Syntax.print_term const) end))));
wenzelm@27340
   183
wenzelm@47822
   184
wenzelm@47822
   185
(* outer syntax *)
wenzelm@47822
   186
wenzelm@47836
   187
fun with_keyword f =
wenzelm@47836
   188
  Args.theory -- Scan.lift (Parse.position Parse.string) >> (fn (thy, (name, pos)) =>
wenzelm@47836
   189
    (f (name, Thy_Header.the_keyword thy name)
wenzelm@47836
   190
      handle ERROR msg => error (msg ^ Position.str_of pos)));
wenzelm@47836
   191
wenzelm@47822
   192
val _ = Context.>> (Context.map_theory
wenzelm@47836
   193
 (value (Binding.name "keyword")
wenzelm@47836
   194
    (with_keyword
wenzelm@47836
   195
      (fn (name, NONE) => "Parse.$$$ " ^ ML_Syntax.print_string name
wenzelm@47836
   196
        | (name, SOME _) => error ("Expected minor keyword " ^ quote name))) #>
wenzelm@47836
   197
  value (Binding.name "command_spec")
wenzelm@47836
   198
    (with_keyword
wenzelm@47836
   199
      (fn (name, SOME kind) =>
wenzelm@47836
   200
          "Keyword.command_spec " ^ ML_Syntax.atomic
wenzelm@47836
   201
            (ML_Syntax.print_pair ML_Syntax.print_string
wenzelm@47836
   202
              (ML_Syntax.print_pair ML_Syntax.print_string
wenzelm@47836
   203
                (ML_Syntax.print_list ML_Syntax.print_string)) (name, kind))
wenzelm@47836
   204
        | (name, NONE) => error ("Expected command keyword " ^ quote name)))));
wenzelm@47822
   205
wenzelm@27340
   206
end;
wenzelm@27340
   207