src/Tools/Code/code_eval.ML
author haftmann
Mon, 07 Dec 2009 16:27:48 +0100
changeset 34026 1e6206763036
parent 33989 src/Tools/Code/code_ml.ML@bf22ff4f3d19
child 34030 f13b5c023e65
permissions -rw-r--r--
split off evaluation mechanisms in separte module Code_Eval
haftmann@34026
     1
(*  Title:      Tools/code/code_eval.ML_
haftmann@28054
     2
    Author:     Florian Haftmann, TU Muenchen
haftmann@28054
     3
haftmann@34026
     4
Runtime services building on code generation into implementation language SML.
haftmann@28054
     5
*)
haftmann@28054
     6
haftmann@34026
     7
signature CODE_EVAL =
haftmann@28054
     8
sig
haftmann@34026
     9
  val target: string
wenzelm@32740
    10
  val eval: string option -> string * (unit -> 'a) option Unsynchronized.ref
haftmann@30970
    11
    -> ((term -> term) -> 'a -> 'a) -> theory -> term -> string list -> 'a
haftmann@34026
    12
  val evaluation_code: theory -> string list -> string list
haftmann@34026
    13
    -> string * ((string * string) list * (string * string) list)
haftmann@28054
    14
  val setup: theory -> theory
haftmann@28054
    15
end;
haftmann@28054
    16
haftmann@34026
    17
structure Code_Eval : CODE_EVAL =
haftmann@28054
    18
struct
haftmann@28054
    19
haftmann@33989
    20
(** generic **)
haftmann@33989
    21
haftmann@34026
    22
val target = "Eval";
haftmann@28054
    23
haftmann@33989
    24
val eval_struct_name = "Code"
haftmann@33989
    25
haftmann@34026
    26
fun evaluation_code thy tycos consts =
haftmann@33989
    27
  let
haftmann@34026
    28
    val (consts', (naming, program)) = Code_Thingol.consts_program thy consts;
haftmann@34026
    29
    val tycos' = map (the o Code_Thingol.lookup_tyco naming) tycos;
haftmann@34026
    30
    val (ml_code, target_names) = Code_ML.evaluation_code_of thy target
haftmann@34026
    31
      (SOME eval_struct_name) naming program (consts' @ tycos');
haftmann@34026
    32
    val (consts'', tycos'') = chop (length consts') target_names;
haftmann@34026
    33
    val consts_map = map2 (fn const => fn NONE =>
haftmann@34026
    34
        error ("Constant " ^ (quote o Code.string_of_const thy) const
haftmann@34026
    35
          ^ "\nhas a user-defined serialization")
haftmann@34026
    36
      | SOME const'' => (const, const'')) consts consts''
haftmann@34026
    37
    val tycos_map = map2 (fn tyco => fn NONE =>
haftmann@34026
    38
        error ("Type " ^ (quote o Sign.extern_type thy) tyco
haftmann@34026
    39
          ^ "\nhas a user-defined serialization")
haftmann@34026
    40
      | SOME tyco'' => (tyco, tyco'')) tycos tycos'';
haftmann@34026
    41
  in (ml_code, (tycos_map, consts_map)) end;
haftmann@28054
    42
haftmann@28054
    43
haftmann@34026
    44
(** evaluation **)
haftmann@28054
    45
haftmann@30970
    46
fun eval some_target reff postproc thy t args =
haftmann@28054
    47
  let
wenzelm@28275
    48
    val ctxt = ProofContext.init thy;
haftmann@31063
    49
    fun evaluator naming program ((_, (_, ty)), t) deps =
haftmann@28054
    50
      let
haftmann@28054
    51
        val _ = if Code_Thingol.contains_dictvar t then
haftmann@28724
    52
          error "Term to be evaluated contains free dictionaries" else ();
haftmann@28663
    53
        val value_name = "Value.VALUE.value"
haftmann@28054
    54
        val program' = program
haftmann@28663
    55
          |> Graph.new_node (value_name,
haftmann@28663
    56
              Code_Thingol.Fun (Term.dummy_patternN, (([], ty), [(([], t), (Drule.dummy_thm, true))])))
haftmann@28663
    57
          |> fold (curry Graph.add_edge value_name) deps;
haftmann@34026
    58
        val (value_code, [SOME value_name']) = Code_ML.evaluation_code_of thy
haftmann@34026
    59
          (the_default target some_target) NONE naming program' [value_name];
haftmann@28054
    60
        val sml_code = "let\n" ^ value_code ^ "\nin " ^ value_name'
haftmann@28054
    61
          ^ space_implode " " (map (enclose "(" ")") args) ^ " end";
wenzelm@30687
    62
      in ML_Context.evaluate ctxt false reff sml_code end;
haftmann@32101
    63
  in Code_Thingol.eval thy postproc evaluator t end;
haftmann@28054
    64
haftmann@28054
    65
haftmann@34026
    66
(** instrumentalization by antiquotation **)
haftmann@28054
    67
haftmann@28054
    68
local
haftmann@28054
    69
wenzelm@33519
    70
structure CodeAntiqData = Proof_Data
haftmann@28054
    71
(
haftmann@30962
    72
  type T = (string list * string list) * (bool * (string
haftmann@30962
    73
    * (string * ((string * string) list * (string * string) list)) lazy));
haftmann@30962
    74
  fun init _ = (([], []), (true, ("", Lazy.value ("", ([], [])))));
haftmann@28054
    75
);
haftmann@28054
    76
haftmann@28054
    77
val is_first_occ = fst o snd o CodeAntiqData.get;
haftmann@28054
    78
haftmann@30962
    79
fun register_code new_tycos new_consts ctxt =
haftmann@28054
    80
  let
haftmann@30962
    81
    val ((tycos, consts), (_, (struct_name, _))) = CodeAntiqData.get ctxt;
haftmann@30962
    82
    val tycos' = fold (insert (op =)) new_tycos tycos;
haftmann@30962
    83
    val consts' = fold (insert (op =)) new_consts consts;
haftmann@28054
    84
    val (struct_name', ctxt') = if struct_name = ""
haftmann@33989
    85
      then ML_Antiquote.variant eval_struct_name ctxt
haftmann@28054
    86
      else (struct_name, ctxt);
haftmann@34026
    87
    val acc_code = Lazy.lazy (fn () => evaluation_code (ProofContext.theory_of ctxt) tycos' consts');
haftmann@30962
    88
  in CodeAntiqData.put ((tycos', consts'), (false, (struct_name', acc_code))) ctxt' end;
haftmann@28054
    89
haftmann@30962
    90
fun register_const const = register_code [] [const];
haftmann@30962
    91
haftmann@30962
    92
fun register_datatype tyco constrs = register_code [tyco] constrs;
haftmann@30962
    93
haftmann@30962
    94
fun print_const const all_struct_name tycos_map consts_map =
haftmann@30962
    95
  (Long_Name.append all_struct_name o the o AList.lookup (op =) consts_map) const;
haftmann@30962
    96
haftmann@30962
    97
fun print_datatype tyco constrs all_struct_name tycos_map consts_map =
haftmann@28054
    98
  let
haftmann@30962
    99
    val upperize = implode o nth_map 0 Symbol.to_ascii_upper o explode;
haftmann@30962
   100
    fun check_base name name'' =
haftmann@30962
   101
      if upperize (Long_Name.base_name name) = upperize name''
haftmann@30962
   102
      then () else error ("Name as printed " ^ quote name''
haftmann@30962
   103
        ^ "\ndiffers from logical base name " ^ quote (Long_Name.base_name name) ^ "; sorry.");
haftmann@30962
   104
    val tyco'' = (the o AList.lookup (op =) tycos_map) tyco;
haftmann@30962
   105
    val constrs'' = map (the o AList.lookup (op =) consts_map) constrs;
haftmann@30962
   106
    val _ = check_base tyco tyco'';
haftmann@30962
   107
    val _ = map2 check_base constrs constrs'';
haftmann@30962
   108
  in "datatype " ^ tyco'' ^ " = datatype " ^ Long_Name.append all_struct_name tyco'' end;
haftmann@30962
   109
haftmann@30962
   110
fun print_code struct_name is_first print_it ctxt =
haftmann@30962
   111
  let
haftmann@30962
   112
    val (_, (_, (struct_code_name, acc_code))) = CodeAntiqData.get ctxt;
haftmann@33989
   113
    val (ml_code, (tycos_map, consts_map)) = Lazy.force acc_code;
haftmann@33989
   114
    val ml_code = if is_first then ml_code
haftmann@28054
   115
      else "";
haftmann@30962
   116
    val all_struct_name = Long_Name.append struct_name struct_code_name;
haftmann@30962
   117
  in (ml_code, print_it all_struct_name tycos_map consts_map) end;
haftmann@28054
   118
haftmann@28054
   119
in
haftmann@28054
   120
haftmann@28054
   121
fun ml_code_antiq raw_const {struct_name, background} =
haftmann@28054
   122
  let
haftmann@31156
   123
    val const = Code.check_const (ProofContext.theory_of background) raw_const;
haftmann@28054
   124
    val is_first = is_first_occ background;
haftmann@28054
   125
    val background' = register_const const background;
haftmann@30962
   126
  in (print_code struct_name is_first (print_const const), background') end;
haftmann@30962
   127
haftmann@30962
   128
fun ml_code_datatype_antiq (raw_tyco, raw_constrs) {struct_name, background} =
haftmann@30962
   129
  let
haftmann@30962
   130
    val thy = ProofContext.theory_of background;
haftmann@30962
   131
    val tyco = Sign.intern_type thy raw_tyco;
haftmann@31156
   132
    val constrs = map (Code.check_const thy) raw_constrs;
haftmann@30962
   133
    val constrs' = (map fst o snd o Code.get_datatype thy) tyco;
haftmann@33038
   134
    val _ = if eq_set (op =) (constrs, constrs') then ()
haftmann@30962
   135
      else error ("Type " ^ quote tyco ^ ": given constructors diverge from real constructors")
haftmann@30962
   136
    val is_first = is_first_occ background;
haftmann@30962
   137
    val background' = register_datatype tyco constrs background;
haftmann@30962
   138
  in (print_code struct_name is_first (print_datatype tyco constrs), background') end;
haftmann@28054
   139
haftmann@28054
   140
end; (*local*)
haftmann@28054
   141
haftmann@28054
   142
haftmann@28054
   143
(** Isar setup **)
haftmann@28054
   144
haftmann@28054
   145
val _ = ML_Context.add_antiq "code" (fn _ => Args.term >> ml_code_antiq);
haftmann@30962
   146
val _ = ML_Context.add_antiq "code_datatype" (fn _ =>
haftmann@30962
   147
  (Args.tyname --| Scan.lift (Args.$$$ "=")
haftmann@30962
   148
    -- (Args.term ::: Scan.repeat (Scan.lift (Args.$$$ "|") |-- Args.term)))
haftmann@30962
   149
      >> ml_code_datatype_antiq);
haftmann@28054
   150
haftmann@34026
   151
val setup = Code_Target.extend_target (target, (Code_ML.target_SML, K I));
haftmann@28054
   152
haftmann@28054
   153
end; (*struct*)