src/Tools/Code/code_runtime.ML
changeset 64957 3faa9b31ff78
parent 64956 de7ce0fad5bc
child 64958 85b87da722ab
equal deleted inserted replaced
64956:de7ce0fad5bc 64957:3faa9b31ff78
    43 structure Code_Runtime : CODE_RUNTIME =
    43 structure Code_Runtime : CODE_RUNTIME =
    44 struct
    44 struct
    45 
    45 
    46 open Basic_Code_Symbol;
    46 open Basic_Code_Symbol;
    47 
    47 
    48 (** computation **)
    48 (** ML compiler as evaluation environment **)
    49 
    49 
    50 (* technical prerequisites *)
    50 (* technical prerequisites *)
    51 
    51 
    52 val this = "Code_Runtime";
    52 val this = "Code_Runtime";
    53 val s_truth = Long_Name.append this "truth";
    53 val s_truth = Long_Name.append this "truth";
    80   let
    80   let
    81     val code =
    81     val code =
    82       prelude ^ "\nval _ = Context.put_generic_context (SOME (Context.map_proof (" ^
    82       prelude ^ "\nval _ = Context.put_generic_context (SOME (Context.map_proof (" ^
    83       put_ml ^ " (fn () => " ^ value ^ ")) (Context.the_generic_context ())))";
    83       put_ml ^ " (fn () => " ^ value ^ ")) (Context.the_generic_context ())))";
    84     val ctxt' = ctxt
    84     val ctxt' = ctxt
    85       |> put (fn () => error ("Bad computation for " ^ quote put_ml))
    85       |> put (fn () => error ("Bad compilation for " ^ quote put_ml))
    86       |> Context.proof_map (compile_ML false code);
    86       |> Context.proof_map (compile_ML false code);
    87     val computator = get ctxt';
    87     val computator = get ctxt';
    88   in Code_Preproc.timed_exec "running ML" computator ctxt' end;
    88   in Code_Preproc.timed_exec "running ML" computator ctxt' end;
    89 
    89 
    90 
    90 
    91 (* computation as evaluation into ML language values *)
    91 (* evaluation into ML language values *)
    92 
    92 
    93 type 'a cookie = (Proof.context -> unit -> 'a) * ((unit -> 'a) -> Proof.context -> Proof.context) * string;
    93 type 'a cookie = (Proof.context -> unit -> 'a) * ((unit -> 'a) -> Proof.context -> Proof.context) * string;
    94 
    94 
    95 fun reject_vars ctxt t =
    95 fun reject_vars ctxt t =
    96   ((Sign.no_frees ctxt o Sign.no_vars ctxt o map_types (K dummyT)) t; t);
    96   ((Sign.no_frees ctxt o Sign.no_vars ctxt o map_types (K dummyT)) t; t);
    97 
    97 
    98 fun build_computation_text ctxt some_target program consts =
    98 fun build_compilation_text ctxt some_target program consts =
    99   Code_Target.computation_text ctxt (the_default target some_target) program consts false
    99   Code_Target.compilation_text ctxt (the_default target some_target) program consts false
   100   #>> (fn ml_modules => space_implode "\n\n" (map snd ml_modules));
   100   #>> (fn ml_modules => space_implode "\n\n" (map snd ml_modules));
   101 
   101 
   102 fun run_computation_text cookie ctxt comp vs_t args =
   102 fun run_compilation_text cookie ctxt comp vs_t args =
   103   let
   103   let
   104     val (program_code, value_name) = comp vs_t;
   104     val (program_code, value_name) = comp vs_t;
   105     val value_code = space_implode " "
   105     val value_code = space_implode " "
   106       (value_name :: "()" :: map (enclose "(" ")") args);
   106       (value_name :: "()" :: map (enclose "(" ")") args);
   107   in Exn.interruptible_capture (value ctxt cookie) (program_code, value_code) end;
   107   in Exn.interruptible_capture (value ctxt cookie) (program_code, value_code) end;
   116     val _ = reject_vars ctxt t;
   116     val _ = reject_vars ctxt t;
   117     val _ = if Config.get ctxt trace
   117     val _ = if Config.get ctxt trace
   118       then tracing ("Evaluation of term " ^ quote (Syntax.string_of_term ctxt t))
   118       then tracing ("Evaluation of term " ^ quote (Syntax.string_of_term ctxt t))
   119       else ()
   119       else ()
   120     fun comp program _ vs_ty_t deps =
   120     fun comp program _ vs_ty_t deps =
   121       run_computation_text cookie ctxt (build_computation_text ctxt some_target program deps) vs_ty_t args;
   121       run_compilation_text cookie ctxt (build_compilation_text ctxt some_target program deps) vs_ty_t args;
   122   in Code_Thingol.dynamic_value ctxt (Exn.map_res o postproc) comp t end;
   122   in Code_Thingol.dynamic_value ctxt (Exn.map_res o postproc) comp t end;
   123 
   123 
   124 fun dynamic_value_strict cookie ctxt some_target postproc t args =
   124 fun dynamic_value_strict cookie ctxt some_target postproc t args =
   125   Exn.release (dynamic_value_exn cookie ctxt some_target postproc t args);
   125   Exn.release (dynamic_value_exn cookie ctxt some_target postproc t args);
   126 
   126 
   127 fun dynamic_value cookie ctxt some_target postproc t args =
   127 fun dynamic_value cookie ctxt some_target postproc t args =
   128   partiality_as_none (dynamic_value_exn cookie ctxt some_target postproc t args);
   128   partiality_as_none (dynamic_value_exn cookie ctxt some_target postproc t args);
   129 
   129 
   130 fun static_value_exn cookie { ctxt, target, lift_postproc, consts } =
   130 fun static_value_exn cookie { ctxt, target, lift_postproc, consts } =
   131   let
   131   let
   132     fun computation' { program, deps } =
   132     fun compilation' { program, deps } =
   133       let
   133       let
   134         val computation'' = run_computation_text cookie ctxt
   134         val compilation'' = run_compilation_text cookie ctxt
   135           (build_computation_text ctxt target program (map Constant deps));
   135           (build_compilation_text ctxt target program (map Constant deps));
   136       in fn _ => fn _ => fn vs_ty_t => fn _ => computation'' vs_ty_t [] end;
   136       in fn _ => fn _ => fn vs_ty_t => fn _ => compilation'' vs_ty_t [] end;
   137     val computation = Code_Thingol.static_value { ctxt = ctxt,
   137     val compilation = Code_Thingol.static_value { ctxt = ctxt,
   138       lift_postproc = Exn.map_res o lift_postproc, consts = consts }
   138       lift_postproc = Exn.map_res o lift_postproc, consts = consts }
   139       computation';
   139       compilation';
   140   in fn ctxt' => computation ctxt' o reject_vars ctxt' end;
   140   in fn ctxt' => compilation ctxt' o reject_vars ctxt' end;
   141 
   141 
   142 fun static_value_strict cookie x = Exn.release oo static_value_exn cookie x;
   142 fun static_value_strict cookie x = Exn.release oo static_value_exn cookie x;
   143 
   143 
   144 fun static_value cookie x = partiality_as_none oo static_value_exn cookie x;
   144 fun static_value cookie x = partiality_as_none oo static_value_exn cookie x;
   145 
   145 
   164     val t = Thm.term_of ct;
   164     val t = Thm.term_of ct;
   165     val _ = if fastype_of t <> propT
   165     val _ = if fastype_of t <> propT
   166       then error ("Not a proposition: " ^ Syntax.string_of_term ctxt t)
   166       then error ("Not a proposition: " ^ Syntax.string_of_term ctxt t)
   167       else ();
   167       else ();
   168     val iff = Thm.cterm_of ctxt (Term.Const (@{const_name Pure.eq}, propT --> propT --> propT));
   168     val iff = Thm.cterm_of ctxt (Term.Const (@{const_name Pure.eq}, propT --> propT --> propT));
   169     val result = case partiality_as_none (run_computation_text truth_cookie ctxt evaluator vs_t [])
   169     val result = case partiality_as_none (run_compilation_text truth_cookie ctxt evaluator vs_t [])
   170      of SOME Holds => true
   170      of SOME Holds => true
   171       | _ => false;
   171       | _ => false;
   172   in
   172   in
   173     Thm.mk_binop iff ct (if result then @{cprop "PROP Code_Generator.holds"} else ct)
   173     Thm.mk_binop iff ct (if result then @{cprop "PROP Code_Generator.holds"} else ct)
   174   end;
   174   end;
   182 
   182 
   183 in
   183 in
   184 
   184 
   185 fun dynamic_holds_conv ctxt = Code_Thingol.dynamic_conv ctxt
   185 fun dynamic_holds_conv ctxt = Code_Thingol.dynamic_conv ctxt
   186   (fn program => fn vs_t => fn deps =>
   186   (fn program => fn vs_t => fn deps =>
   187     check_holds_oracle ctxt (build_computation_text ctxt NONE program deps) vs_t)
   187     check_holds_oracle ctxt (build_compilation_text ctxt NONE program deps) vs_t)
   188       o reject_vars ctxt;
   188       o reject_vars ctxt;
   189 
   189 
   190 fun static_holds_conv (ctxt_consts as { ctxt, ... }) =
   190 fun static_holds_conv (ctxt_consts as { ctxt, ... }) =
   191   Code_Thingol.static_conv_thingol ctxt_consts (fn { program, deps } => fn ctxt' => fn vs_t =>
   191   Code_Thingol.static_conv_thingol ctxt_consts (fn { program, deps } => fn ctxt' => fn vs_t =>
   192     K (check_holds_oracle ctxt' (build_computation_text ctxt NONE program (map Constant deps)) vs_t o reject_vars ctxt'));
   192     K (check_holds_oracle ctxt' (build_compilation_text ctxt NONE program (map Constant deps)) vs_t o reject_vars ctxt'));
   193 
   193 
   194 end; (*local*)
   194 end; (*local*)
   195 
   195 
   196 
   196 
   197 (** computations -- experimental! **)
   197 (** generator for computations -- partial implementations of the universal morphism from Isabelle to ML terms **)
   198 
   198 
   199 fun monomorphic T = fold_atyps ((K o K) false) T true;
   199 (* auxiliary *)
       
   200 
       
   201 val generated_computationN = "Generated_Computation";
       
   202 
       
   203 
       
   204 (* possible type signatures of constants *)
   200 
   205 
   201 fun typ_signatures_for T =
   206 fun typ_signatures_for T =
   202   let
   207   let
   203     val (Ts, T') = strip_type T;
   208     val (Ts, T') = strip_type T;
   204   in map_range (fn n => (drop n Ts ---> T', take n Ts)) (length Ts + 1) end;
   209   in map_range (fn n => (drop n Ts ---> T', take n Ts)) (length Ts + 1) end;
   211   in
   216   in
   212     Typtab.empty
   217     Typtab.empty
   213     |> fold add cTs
   218     |> fold add cTs
   214     |> Typtab.lookup_list
   219     |> Typtab.lookup_list
   215   end;
   220   end;
       
   221 
       
   222 
       
   223 (* name mangling *)
       
   224 
       
   225 local
       
   226 
       
   227 fun tycos_of (Type (tyco, Ts)) = maps tycos_of Ts @ [tyco]
       
   228   | tycos_of _ = [];
       
   229 
       
   230 val ml_name_of = Name.desymbolize NONE o Long_Name.base_name;
       
   231 
       
   232 in
       
   233 
       
   234 fun of_term_for_typ Ts =
       
   235   let
       
   236     val names = Ts
       
   237       |> map (suffix "_of_term" o space_implode "_" o map ml_name_of o tycos_of)
       
   238       |> Name.variant_list [];
       
   239   in the o AList.lookup (op =) (Ts ~~ names) end;
       
   240 
       
   241 fun eval_for_const ctxt cTs =
       
   242   let
       
   243     fun symbol_list (c, T) = c :: maps tycos_of (Sign.const_typargs (Proof_Context.theory_of ctxt) (c, T))
       
   244     val names = cTs
       
   245       |> map (prefix "eval_" o space_implode "_" o map ml_name_of o symbol_list)
       
   246       |> Name.variant_list [];
       
   247   in the o AList.lookup (op =) (cTs ~~ names) end;
       
   248 
       
   249 end;
       
   250 
       
   251 
       
   252 (* checks for input terms *)
       
   253 
       
   254 fun monomorphic T = fold_atyps ((K o K) false) T true;
       
   255 
       
   256 fun check_typ ctxt T t =
       
   257   Syntax.check_term ctxt (Type.constraint T t);
       
   258 
       
   259 fun check_computation_input ctxt cTs t =
       
   260   let
       
   261     fun check t = check_comb (strip_comb t)
       
   262     and check_comb (t as Abs _, _) =
       
   263           error ("Bad term, contains abstraction: " ^ Syntax.string_of_term ctxt t)
       
   264       | check_comb (t as Const (cT as (c, T)), ts) =
       
   265           let
       
   266             val _ = if not (member (op =) cTs cT)
       
   267               then error ("Bad term, computation cannot proceed on constant " ^ Syntax.string_of_term ctxt t)
       
   268               else ();
       
   269             val _ = if not (monomorphic T)
       
   270               then error ("Bad term, contains polymorphic constant " ^ Syntax.string_of_term ctxt t)
       
   271               else ();
       
   272             val _ = map check ts;
       
   273           in () end;
       
   274     val _ = check t;
       
   275   in t end;
       
   276 
       
   277 
       
   278 (* code generation for of the universal morphism *)
   216 
   279 
   217 fun print_of_term_funs { typ_sign_for, eval_for_const, of_term_for_typ } Ts =
   280 fun print_of_term_funs { typ_sign_for, eval_for_const, of_term_for_typ } Ts =
   218   let
   281   let
   219     val var_names = map_range (fn n => "t" ^ string_of_int (n + 1));
   282     val var_names = map_range (fn n => "t" ^ string_of_int (n + 1));
   220     fun print_lhs c xs = "Const (" ^ quote c ^ ", _)"
   283     fun print_lhs c xs = "Const (" ^ quote c ^ ", _)"
   240     map print_eqs Ts
   303     map print_eqs Ts
   241     |> space_implode "\nand "
   304     |> space_implode "\nand "
   242     |> prefix "fun "
   305     |> prefix "fun "
   243   end;
   306   end;
   244 
   307 
   245 local
       
   246 
       
   247 fun tycos_of (Type (tyco, Ts)) = maps tycos_of Ts @ [tyco]
       
   248   | tycos_of _ = [];
       
   249 
       
   250 val ml_name_of = Name.desymbolize NONE o Long_Name.base_name;
       
   251 
       
   252 in
       
   253 
       
   254 fun of_term_for_typ Ts =
       
   255   let
       
   256     val names = Ts
       
   257       |> map (suffix "_of_term" o space_implode "_" o map ml_name_of o tycos_of)
       
   258       |> Name.variant_list [];
       
   259   in the o AList.lookup (op =) (Ts ~~ names) end;
       
   260 
       
   261 fun eval_for_const ctxt cTs =
       
   262   let
       
   263     fun symbol_list (c, T) = c :: maps tycos_of (Sign.const_typargs (Proof_Context.theory_of ctxt) (c, T))
       
   264     val names = cTs
       
   265       |> map (prefix "eval_" o space_implode "_" o map ml_name_of o symbol_list)
       
   266       |> Name.variant_list [];
       
   267   in the o AList.lookup (op =) (cTs ~~ names) end;
       
   268 
       
   269 end;
       
   270 
       
   271 val generated_computationN = "Generated_Computation";
       
   272 
       
   273 fun print_computation_code ctxt compiled_value requested_Ts cTs =
   308 fun print_computation_code ctxt compiled_value requested_Ts cTs =
   274   let
   309   let
   275     val proper_cTs = map_filter I cTs;
   310     val proper_cTs = map_filter I cTs;
   276     val typ_sign_for = typ_signatures proper_cTs;
   311     val typ_sign_for = typ_signatures proper_cTs;
   277     fun add_typ T Ts =
   312     fun add_typ T Ts =
   305       "",
   340       "",
   306       "end"
   341       "end"
   307     ], map (prefix (generated_computationN ^ ".") o of_term_for_typ') requested_Ts)
   342     ], map (prefix (generated_computationN ^ ".") o of_term_for_typ') requested_Ts)
   308   end;
   343   end;
   309 
   344 
   310 fun check_typ ctxt T t =
   345 fun mount_computation ctxt cTs T raw_computation lift_postproc =
   311   Syntax.check_term ctxt (Type.constraint T t);
   346   Code_Preproc.static_value { ctxt = ctxt, lift_postproc = lift_postproc, consts = [] }
   312 
   347     (fn _ => fn ctxt' =>
   313 fun check_computation_input ctxt cTs t =
   348       check_typ ctxt' T
   314   let
   349       #> reject_vars ctxt'
   315     fun check t = check_comb (strip_comb t)
   350       #> check_computation_input ctxt' cTs
   316     and check_comb (t as Abs _, _) =
   351       #> raw_computation);
   317           error ("Bad term, contains abstraction: " ^ Syntax.string_of_term ctxt t)
       
   318       | check_comb (t as Const (cT as (c, T)), ts) =
       
   319           let
       
   320             val _ = if not (member (op =) cTs cT)
       
   321               then error ("Bad term, computation cannot proceed on constant " ^ Syntax.string_of_term ctxt t)
       
   322               else ();
       
   323             val _ = if not (monomorphic T)
       
   324               then error ("Bad term, contains polymorphic constant " ^ Syntax.string_of_term ctxt t)
       
   325               else ();
       
   326             val _ = map check ts;
       
   327           in () end;
       
   328     val _ = check t;
       
   329   in t end;
       
   330 
   352 
   331 fun compile_computation cookie ctxt T program evals vs_ty_evals deps =
   353 fun compile_computation cookie ctxt T program evals vs_ty_evals deps =
   332   let
   354   let
   333     fun the_const (Const cT) = cT
   355     fun the_const (Const cT) = cT
   334       | the_const t = error ("No constant after preprocessing: " ^ Syntax.string_of_term ctxt t)
   356       | the_const t = error ("No constant after preprocessing: " ^ Syntax.string_of_term ctxt t)
   338     val cTs = fold_rev (fn cT => fn cTs =>
   360     val cTs = fold_rev (fn cT => fn cTs =>
   339       (if member (op =) cTs (SOME cT) then NONE else SOME cT) :: cTs) raw_cTs [];
   361       (if member (op =) cTs (SOME cT) then NONE else SOME cT) :: cTs) raw_cTs [];
   340     fun comp' vs_ty_evals =
   362     fun comp' vs_ty_evals =
   341       let
   363       let
   342         val (generated_code, compiled_value) =
   364         val (generated_code, compiled_value) =
   343           build_computation_text ctxt NONE program deps vs_ty_evals;
   365           build_compilation_text ctxt NONE program deps vs_ty_evals;
   344         val (of_term_code, [of_term]) = print_computation_code ctxt compiled_value [T] cTs;
   366         val (of_term_code, [of_term]) = print_computation_code ctxt compiled_value [T] cTs;
   345       in
   367       in
   346         (generated_code ^ "\n" ^ of_term_code,
   368         (generated_code ^ "\n" ^ of_term_code,
   347           enclose "(" ")" ("fn () => " ^ of_term))
   369           enclose "(" ")" ("fn () => " ^ of_term))
   348       end;
   370       end;
   349     val compiled_computation =
   371     val compiled_computation =
   350       Exn.release (run_computation_text cookie ctxt comp' vs_ty_evals []);
   372       Exn.release (run_compilation_text cookie ctxt comp' vs_ty_evals []);
   351   in fn ctxt' =>
   373   in (map_filter I cTs, compiled_computation) end;
   352     check_typ ctxt' T
       
   353     #> reject_vars ctxt'
       
   354     #> check_computation_input ctxt (map_filter I cTs)
       
   355     #> compiled_computation
       
   356   end;
       
   357 
   374 
   358 fun experimental_computation cookie { ctxt, lift_postproc, terms = ts, T } =
   375 fun experimental_computation cookie { ctxt, lift_postproc, terms = ts, T } =
   359   let
   376   let
   360     val _ = if not (monomorphic T)
   377     val _ = if not (monomorphic T)
   361       then error ("Polymorphic type: " ^ Syntax.string_of_typ ctxt T)
   378       then error ("Polymorphic type: " ^ Syntax.string_of_typ ctxt T)
   363     val cTs = (fold o fold_aterms)
   380     val cTs = (fold o fold_aterms)
   364       (fn (t as Const (cT as (_, T))) =>
   381       (fn (t as Const (cT as (_, T))) =>
   365         if not (monomorphic T) then error ("Polymorphic constant:" ^ Syntax.string_of_term ctxt t)
   382         if not (monomorphic T) then error ("Polymorphic constant:" ^ Syntax.string_of_term ctxt t)
   366         else insert (op =) cT | _ => I) ts [];
   383         else insert (op =) cT | _ => I) ts [];
   367     val evals = Abs ("eval", map snd cTs ---> TFree (Name.aT, []), list_comb (Bound 0, map Const cTs));
   384     val evals = Abs ("eval", map snd cTs ---> TFree (Name.aT, []), list_comb (Bound 0, map Const cTs));
   368     val computation = Code_Thingol.dynamic_value ctxt
   385     val (cTs, raw_computation) = Code_Thingol.dynamic_value ctxt
   369       (K I) (compile_computation cookie ctxt T) evals;
   386       (K I) (compile_computation cookie ctxt T) evals;
   370   in
   387   in
   371     Code_Preproc.static_value { ctxt = ctxt, lift_postproc = lift_postproc, consts = [] }
   388     mount_computation ctxt cTs T raw_computation lift_postproc
   372       (K computation)
       
   373   end;
   389   end;
   374 
   390 
   375 
   391 
   376 (** code antiquotation **)
   392 (** code antiquotation **)
   377 
   393 
   378 fun evaluation_code ctxt module_name program tycos consts =
   394 fun runtime_code ctxt module_name program tycos consts =
   379   let
   395   let
   380     val thy = Proof_Context.theory_of ctxt;
   396     val thy = Proof_Context.theory_of ctxt;
   381     val (ml_modules, target_names) =
   397     val (ml_modules, target_names) =
   382       Code_Target.produce_code_for ctxt
   398       Code_Target.produce_code_for ctxt
   383         target NONE module_name [] program false (map Constant consts @ map Type_Constructor tycos);
   399         target NONE module_name [] program false (map Constant consts @ map Type_Constructor tycos);
   420 
   436 
   421 fun lazy_code ctxt consts = Lazy.lazy (fn () =>
   437 fun lazy_code ctxt consts = Lazy.lazy (fn () =>
   422   let
   438   let
   423     val program = Code_Thingol.consts_program ctxt consts;
   439     val program = Code_Thingol.consts_program ctxt consts;
   424     val (code, (_, consts_map)) =
   440     val (code, (_, consts_map)) =
   425       evaluation_code ctxt Code_Target.generatedN program [] consts
   441       runtime_code ctxt Code_Target.generatedN program [] consts
   426   in { code = code, consts_map = consts_map } end);
   442   in { code = code, consts_map = consts_map } end);
   427 
   443 
   428 fun register_const const ctxt =
   444 fun register_const const ctxt =
   429   let
   445   let
   430     val consts = insert (op =) const ((#named_consts o Code_Antiq_Data.get) ctxt);
   446     val consts = insert (op =) const ((#named_consts o Code_Antiq_Data.get) ctxt);
   530     val (tycos, constrs) = map_split (uncurry (check_datatype thy)) datatypes
   546     val (tycos, constrs) = map_split (uncurry (check_datatype thy)) datatypes
   531       |> apsnd flat;
   547       |> apsnd flat;
   532     val functions = map (prep_const thy) raw_functions;
   548     val functions = map (prep_const thy) raw_functions;
   533     val consts = constrs @ functions;
   549     val consts = constrs @ functions;
   534     val program = Code_Thingol.consts_program ctxt consts;
   550     val program = Code_Thingol.consts_program ctxt consts;
   535     val result = evaluation_code ctxt module_name program tycos consts
   551     val result = runtime_code ctxt module_name program tycos consts
   536       |> (apsnd o apsnd) (chop (length constrs));
   552       |> (apsnd o apsnd) (chop (length constrs));
   537   in
   553   in
   538     thy
   554     thy
   539     |> process_reflection result module_name some_file
   555     |> process_reflection result module_name some_file
   540   end;
   556   end;