src/Pure/ML/ml_antiquotation.ML
changeset 56072 31e427387ab5
parent 56071 2ffdedb0c044
child 56205 ceb8a93460b7
equal deleted inserted replaced
56071:2ffdedb0c044 56072:31e427387ab5
       
     1 (*  Title:      Pure/ML/ml_antiquotation.ML
       
     2     Author:     Makarius
       
     3 
       
     4 Convenience operations for common ML antiquotations.  Miscellaneous
       
     5 predefined antiquotations.
       
     6 *)
       
     7 
       
     8 signature ML_ANTIQUOTATION =
       
     9 sig
       
    10   val variant: string -> Proof.context -> string * Proof.context
       
    11   val inline: binding -> string context_parser -> theory -> theory
       
    12   val value: binding -> string context_parser -> theory -> theory
       
    13 end;
       
    14 
       
    15 structure ML_Antiquotation: ML_ANTIQUOTATION =
       
    16 struct
       
    17 
       
    18 (** generic tools **)
       
    19 
       
    20 (* ML names *)
       
    21 
       
    22 val init_context = ML_Syntax.reserved |> Name.declare "ML_context";
       
    23 
       
    24 structure Names = Proof_Data
       
    25 (
       
    26   type T = Name.context;
       
    27   fun init _ = init_context;
       
    28 );
       
    29 
       
    30 fun variant a ctxt =
       
    31   let
       
    32     val names = Names.get ctxt;
       
    33     val (b, names') = Name.variant (Name.desymbolize false a) names;
       
    34     val ctxt' = Names.put names' ctxt;
       
    35   in (b, ctxt') end;
       
    36 
       
    37 
       
    38 (* specific antiquotations *)
       
    39 
       
    40 fun inline name scan =
       
    41   ML_Context.antiquotation name scan (fn _ => fn s => fn ctxt => (K ("", s), ctxt));
       
    42 
       
    43 fun value name scan =
       
    44   ML_Context.antiquotation name scan (fn _ => fn s => fn ctxt =>
       
    45     let
       
    46       val (a, ctxt') = variant (Binding.name_of name) ctxt;
       
    47       val env = "val " ^ a ^ " = " ^ s ^ ";\n";
       
    48       val body = "Isabelle." ^ a;
       
    49     in (K (env, body), ctxt') end);
       
    50 
       
    51 
       
    52 
       
    53 (** misc antiquotations **)
       
    54 
       
    55 val _ = Theory.setup
       
    56  (ML_Context.antiquotation (Binding.name "here") (Scan.succeed ())
       
    57     (fn src => fn () => fn ctxt =>
       
    58       let
       
    59         val (a, ctxt') = variant "position" ctxt;
       
    60         val (_, pos) = Args.name_of_src src;
       
    61         val env = "val " ^ a ^ " = " ^ ML_Syntax.print_position pos ^ ";\n";
       
    62         val body = "Isabelle." ^ a;
       
    63       in (K (env, body), ctxt') end) #>
       
    64 
       
    65   inline (Binding.name "assert")
       
    66     (Scan.succeed "(fn b => if b then () else raise General.Fail \"Assertion failed\")") #>
       
    67 
       
    68   inline (Binding.name "make_string") (Scan.succeed ml_make_string) #>
       
    69 
       
    70   value (Binding.name "option") (Scan.lift (Parse.position Args.name) >> (fn (name, pos) =>
       
    71     (Options.default_typ name handle ERROR msg => error (msg ^ Position.here pos);
       
    72      ML_Syntax.print_string name))) #>
       
    73 
       
    74   value (Binding.name "binding")
       
    75     (Scan.lift (Parse.position Args.name) >> ML_Syntax.make_binding) #>
       
    76 
       
    77   value (Binding.name "theory")
       
    78     (Args.context -- Scan.lift (Parse.position Args.name) >> (fn (ctxt, (name, pos)) =>
       
    79       (Context_Position.report ctxt pos
       
    80         (Theory.get_markup (Context.get_theory (Proof_Context.theory_of ctxt) name));
       
    81        "Context.get_theory (Proof_Context.theory_of ML_context) " ^ ML_Syntax.print_string name))
       
    82     || Scan.succeed "Proof_Context.theory_of ML_context") #>
       
    83 
       
    84   value (Binding.name "theory_context")
       
    85     (Args.context -- Scan.lift (Parse.position Args.name) >> (fn (ctxt, (name, pos)) =>
       
    86       (Context_Position.report ctxt pos
       
    87         (Theory.get_markup (Context.get_theory (Proof_Context.theory_of ctxt) name));
       
    88        "Proof_Context.get_global (Proof_Context.theory_of ML_context) " ^
       
    89         ML_Syntax.print_string name))) #>
       
    90 
       
    91   inline (Binding.name "context") (Scan.succeed "Isabelle.ML_context") #>
       
    92 
       
    93   inline (Binding.name "typ") (Args.typ >> (ML_Syntax.atomic o ML_Syntax.print_typ)) #>
       
    94   inline (Binding.name "term") (Args.term >> (ML_Syntax.atomic o ML_Syntax.print_term)) #>
       
    95   inline (Binding.name "prop") (Args.prop >> (ML_Syntax.atomic o ML_Syntax.print_term)) #>
       
    96 
       
    97   value (Binding.name "ctyp") (Args.typ >> (fn T =>
       
    98     "Thm.ctyp_of (Proof_Context.theory_of ML_context) " ^
       
    99       ML_Syntax.atomic (ML_Syntax.print_typ T))) #>
       
   100 
       
   101   value (Binding.name "cterm") (Args.term >> (fn t =>
       
   102     "Thm.cterm_of (Proof_Context.theory_of ML_context) " ^
       
   103      ML_Syntax.atomic (ML_Syntax.print_term t))) #>
       
   104 
       
   105   value (Binding.name "cprop") (Args.prop >> (fn t =>
       
   106     "Thm.cterm_of (Proof_Context.theory_of ML_context) " ^
       
   107      ML_Syntax.atomic (ML_Syntax.print_term t))) #>
       
   108 
       
   109   value (Binding.name "cpat")
       
   110     (Args.context --
       
   111       Scan.lift Args.name_inner_syntax >> uncurry Proof_Context.read_term_pattern >> (fn t =>
       
   112         "Thm.cterm_of (Proof_Context.theory_of ML_context) " ^
       
   113           ML_Syntax.atomic (ML_Syntax.print_term t))));
       
   114 
       
   115 
       
   116 (* type classes *)
       
   117 
       
   118 fun class syn = Args.context -- Scan.lift Args.name_inner_syntax >> (fn (ctxt, s) =>
       
   119   Proof_Context.read_class ctxt s
       
   120   |> syn ? Lexicon.mark_class
       
   121   |> ML_Syntax.print_string);
       
   122 
       
   123 val _ = Theory.setup
       
   124  (inline (Binding.name "class") (class false) #>
       
   125   inline (Binding.name "class_syntax") (class true) #>
       
   126 
       
   127   inline (Binding.name "sort")
       
   128     (Args.context -- Scan.lift Args.name_inner_syntax >> (fn (ctxt, s) =>
       
   129       ML_Syntax.atomic (ML_Syntax.print_sort (Syntax.read_sort ctxt s)))));
       
   130 
       
   131 
       
   132 (* type constructors *)
       
   133 
       
   134 fun type_name kind check = Args.context -- Scan.lift (Parse.position Args.name_inner_syntax)
       
   135   >> (fn (ctxt, (s, pos)) =>
       
   136     let
       
   137       val Type (c, _) = Proof_Context.read_type_name {proper = true, strict = false} ctxt s;
       
   138       val decl = Type.the_decl (Proof_Context.tsig_of ctxt) (c, pos);
       
   139       val res =
       
   140         (case try check (c, decl) of
       
   141           SOME res => res
       
   142         | NONE => error ("Not a " ^ kind ^ ": " ^ quote c ^ Position.here pos));
       
   143     in ML_Syntax.print_string res end);
       
   144 
       
   145 val _ = Theory.setup
       
   146  (inline (Binding.name "type_name")
       
   147     (type_name "logical type" (fn (c, Type.LogicalType _) => c)) #>
       
   148   inline (Binding.name "type_abbrev")
       
   149     (type_name "type abbreviation" (fn (c, Type.Abbreviation _) => c)) #>
       
   150   inline (Binding.name "nonterminal")
       
   151     (type_name "nonterminal" (fn (c, Type.Nonterminal) => c)) #>
       
   152   inline (Binding.name "type_syntax")
       
   153     (type_name "type" (fn (c, _) => Lexicon.mark_type c)));
       
   154 
       
   155 
       
   156 (* constants *)
       
   157 
       
   158 fun const_name check = Args.context -- Scan.lift (Parse.position Args.name_inner_syntax)
       
   159   >> (fn (ctxt, (s, pos)) =>
       
   160     let
       
   161       val Const (c, _) = Proof_Context.read_const {proper = true, strict = false} ctxt s;
       
   162       val res = check (Proof_Context.consts_of ctxt, c)
       
   163         handle TYPE (msg, _, _) => error (msg ^ Position.here pos);
       
   164     in ML_Syntax.print_string res end);
       
   165 
       
   166 val _ = Theory.setup
       
   167  (inline (Binding.name "const_name")
       
   168     (const_name (fn (consts, c) => (Consts.the_const consts c; c))) #>
       
   169   inline (Binding.name "const_abbrev")
       
   170     (const_name (fn (consts, c) => (Consts.the_abbreviation consts c; c))) #>
       
   171   inline (Binding.name "const_syntax")
       
   172     (const_name (fn (_, c) => Lexicon.mark_const c)) #>
       
   173 
       
   174   inline (Binding.name "syntax_const")
       
   175     (Args.context -- Scan.lift (Parse.position Args.name) >> (fn (ctxt, (c, pos)) =>
       
   176       if is_some (Syntax.lookup_const (Proof_Context.syn_of ctxt) c)
       
   177       then ML_Syntax.print_string c
       
   178       else error ("Unknown syntax const: " ^ quote c ^ Position.here pos))) #>
       
   179 
       
   180   inline (Binding.name "const")
       
   181     (Args.context -- Scan.lift Args.name_inner_syntax -- Scan.optional
       
   182         (Scan.lift (Args.$$$ "(") |-- Parse.enum1' "," Args.typ --| Scan.lift (Args.$$$ ")")) []
       
   183       >> (fn ((ctxt, raw_c), Ts) =>
       
   184         let
       
   185           val Const (c, _) =
       
   186             Proof_Context.read_const {proper = true, strict = true} ctxt raw_c;
       
   187           val consts = Proof_Context.consts_of ctxt;
       
   188           val n = length (Consts.typargs consts (c, Consts.type_scheme consts c));
       
   189           val _ = length Ts <> n andalso
       
   190             error ("Constant requires " ^ string_of_int n ^ " type argument(s): " ^
       
   191               quote c ^ enclose "(" ")" (commas (replicate n "_")));
       
   192           val const = Const (c, Consts.instance consts (c, Ts));
       
   193         in ML_Syntax.atomic (ML_Syntax.print_term const) end)));
       
   194 
       
   195 
       
   196 (* outer syntax *)
       
   197 
       
   198 fun with_keyword f =
       
   199   Args.theory -- Scan.lift (Parse.position Parse.string) >> (fn (thy, (name, pos)) =>
       
   200     (f ((name, Thy_Header.the_keyword thy name), pos)
       
   201       handle ERROR msg => error (msg ^ Position.here pos)));
       
   202 
       
   203 val _ = Theory.setup
       
   204  (value (Binding.name "keyword")
       
   205     (with_keyword
       
   206       (fn ((name, NONE), _) => "Parse.$$$ " ^ ML_Syntax.print_string name
       
   207         | ((name, SOME _), pos) =>
       
   208             error ("Expected minor keyword " ^ quote name ^ Position.here pos))) #>
       
   209   value (Binding.name "command_spec")
       
   210     (with_keyword
       
   211       (fn ((name, SOME kind), pos) =>
       
   212           "Keyword.command_spec " ^ ML_Syntax.atomic
       
   213             ((ML_Syntax.print_pair
       
   214               (ML_Syntax.print_pair ML_Syntax.print_string
       
   215                 (ML_Syntax.print_pair
       
   216                   (ML_Syntax.print_pair ML_Syntax.print_string
       
   217                     (ML_Syntax.print_list ML_Syntax.print_string))
       
   218                   (ML_Syntax.print_list ML_Syntax.print_string)))
       
   219               ML_Syntax.print_position) ((name, kind), pos))
       
   220         | ((name, NONE), pos) =>
       
   221             error ("Expected command keyword " ^ quote name ^ Position.here pos))));
       
   222 
       
   223 end;
       
   224