src/Pure/ML/ml_antiquotation.ML
author wenzelm
Sun, 06 Apr 2014 15:43:45 +0200
changeset 56436 30ccec1e82fb
parent 56205 ceb8a93460b7
child 56811 b66639331db5
permissions -rw-r--r--
more source positions;

(*  Title:      Pure/ML/ml_antiquotation.ML
    Author:     Makarius

ML antiquotations.
*)

signature ML_ANTIQUOTATION =
sig
  val variant: string -> Proof.context -> string * Proof.context
  val declaration: binding -> 'a context_parser ->
    (Args.src -> 'a -> Proof.context -> ML_Context.decl * Proof.context) ->
    theory -> theory
  val inline: binding -> string context_parser -> theory -> theory
  val value: binding -> string context_parser -> theory -> theory
end;

structure ML_Antiquotation: ML_ANTIQUOTATION =
struct

(* unique names *)

val init_context = ML_Syntax.reserved |> Name.declare "ML_context";

structure Names = Proof_Data
(
  type T = Name.context;
  fun init _ = init_context;
);

fun variant a ctxt =
  let
    val names = Names.get ctxt;
    val (b, names') = Name.variant (Name.desymbolize false a) names;
    val ctxt' = Names.put names' ctxt;
  in (b, ctxt') end;


(* define antiquotations *)

fun declaration name scan body =
  ML_Context.add_antiquotation name
    (fn src => fn orig_ctxt =>
      let val (x, _) = Args.syntax scan src orig_ctxt
      in body src x orig_ctxt end);

fun inline name scan =
  declaration name scan (fn _ => fn s => fn ctxt => (K ("", s), ctxt));

fun value name scan =
  declaration name scan (fn _ => fn s => fn ctxt =>
    let
      val (a, ctxt') = variant (Binding.name_of name) ctxt;
      val env = "val " ^ a ^ " = " ^ s ^ ";\n";
      val body = "Isabelle." ^ a;
    in (K (env, body), ctxt') end);


(* basic antiquotations *)

val _ = Theory.setup
 (declaration (Binding.make ("here", @{here})) (Scan.succeed ())
    (fn src => fn () => fn ctxt =>
      let
        val (a, ctxt') = variant "position" ctxt;
        val (_, pos) = Args.name_of_src src;
        val env = "val " ^ a ^ " = " ^ ML_Syntax.print_position pos ^ ";\n";
        val body = "Isabelle." ^ a;
      in (K (env, body), ctxt') end) #>

  value (Binding.make ("binding", @{here}))
    (Scan.lift (Parse.position Args.name) >> ML_Syntax.make_binding));

end;