121 datatype prolog_system = SWI_PROLOG | YAP |
121 datatype prolog_system = SWI_PROLOG | YAP |
122 |
122 |
123 fun string_of_system SWI_PROLOG = "swiprolog" |
123 fun string_of_system SWI_PROLOG = "swiprolog" |
124 | string_of_system YAP = "yap" |
124 | string_of_system YAP = "yap" |
125 |
125 |
126 val prolog_system = Attrib.setup_config_string @{binding prolog_system} (K "swiprolog") |
126 val prolog_system = Attrib.setup_config_string \<^binding>\<open>prolog_system\<close> (K "swiprolog") |
127 |
127 |
128 fun get_prolog_system ctxt = |
128 fun get_prolog_system ctxt = |
129 (case Config.get ctxt prolog_system of |
129 (case Config.get ctxt prolog_system of |
130 "swiprolog" => SWI_PROLOG |
130 "swiprolog" => SWI_PROLOG |
131 | "yap" => YAP |
131 | "yap" => YAP |
132 | name => error ("Bad prolog system: " ^ quote name ^ " (\"swiprolog\" or \"yap\" expected)")) |
132 | name => error ("Bad prolog system: " ^ quote name ^ " (\"swiprolog\" or \"yap\" expected)")) |
133 |
133 |
134 |
134 |
135 val prolog_timeout = Attrib.setup_config_real @{binding prolog_timeout} (K 10.0) |
135 val prolog_timeout = Attrib.setup_config_real \<^binding>\<open>prolog_timeout\<close> (K 10.0) |
136 |
136 |
137 fun get_prolog_timeout ctxt = seconds (Config.get ctxt prolog_timeout) |
137 fun get_prolog_timeout ctxt = seconds (Config.get ctxt prolog_timeout) |
138 |
138 |
139 |
139 |
140 (* internal program representation *) |
140 (* internal program representation *) |
248 | NONE => error ("No constant corresponding to " ^ c)) |
248 | NONE => error ("No constant corresponding to " ^ c)) |
249 |
249 |
250 |
250 |
251 (** translation of terms, literals, premises, and clauses **) |
251 (** translation of terms, literals, premises, and clauses **) |
252 |
252 |
253 fun translate_arith_const @{const_name "Groups.plus_class.plus"} = SOME Plus |
253 fun translate_arith_const \<^const_name>\<open>Groups.plus_class.plus\<close> = SOME Plus |
254 | translate_arith_const @{const_name "Groups.minus_class.minus"} = SOME Minus |
254 | translate_arith_const \<^const_name>\<open>Groups.minus_class.minus\<close> = SOME Minus |
255 | translate_arith_const _ = NONE |
255 | translate_arith_const _ = NONE |
256 |
256 |
257 fun mk_nat_term constant_table n = |
257 fun mk_nat_term constant_table n = |
258 let |
258 let |
259 val zero = translate_const constant_table @{const_name "Groups.zero_class.zero"} |
259 val zero = translate_const constant_table \<^const_name>\<open>Groups.zero_class.zero\<close> |
260 val Suc = translate_const constant_table @{const_name "Suc"} |
260 val Suc = translate_const constant_table \<^const_name>\<open>Suc\<close> |
261 in funpow n (fn t => AppF (Suc, [t])) (Cons zero) end |
261 in funpow n (fn t => AppF (Suc, [t])) (Cons zero) end |
262 |
262 |
263 fun translate_term ctxt constant_table t = |
263 fun translate_term ctxt constant_table t = |
264 (case try HOLogic.dest_number t of |
264 (case try HOLogic.dest_number t of |
265 SOME (@{typ "int"}, n) => Number n |
265 SOME (\<^typ>\<open>int\<close>, n) => Number n |
266 | SOME (@{typ "nat"}, n) => mk_nat_term constant_table n |
266 | SOME (\<^typ>\<open>nat\<close>, n) => mk_nat_term constant_table n |
267 | NONE => |
267 | NONE => |
268 (case strip_comb t of |
268 (case strip_comb t of |
269 (Free (v, T), []) => Var v |
269 (Free (v, T), []) => Var v |
270 | (Const (c, _), []) => Cons (translate_const constant_table c) |
270 | (Const (c, _), []) => Cons (translate_const constant_table c) |
271 | (Const (c, _), args) => |
271 | (Const (c, _), args) => |
275 AppF (translate_const constant_table c, map (translate_term ctxt constant_table) args)) |
275 AppF (translate_const constant_table c, map (translate_term ctxt constant_table) args)) |
276 | _ => error ("illegal term for translation: " ^ Syntax.string_of_term ctxt t))) |
276 | _ => error ("illegal term for translation: " ^ Syntax.string_of_term ctxt t))) |
277 |
277 |
278 fun translate_literal ctxt constant_table t = |
278 fun translate_literal ctxt constant_table t = |
279 (case strip_comb t of |
279 (case strip_comb t of |
280 (Const (@{const_name HOL.eq}, _), [l, r]) => |
280 (Const (\<^const_name>\<open>HOL.eq\<close>, _), [l, r]) => |
281 let |
281 let |
282 val l' = translate_term ctxt constant_table l |
282 val l' = translate_term ctxt constant_table l |
283 val r' = translate_term ctxt constant_table r |
283 val r' = translate_term ctxt constant_table r |
284 in |
284 in |
285 (if is_Var l' andalso is_arith_term r' andalso not (is_Var r') then ArithEq else Eq) |
285 (if is_Var l' andalso is_arith_term r' andalso not (is_Var r') then ArithEq else Eq) |
304 NegRel_of (translate_literal ctxt constant_table t) |
304 NegRel_of (translate_literal ctxt constant_table t) |
305 | NONE => translate_literal ctxt constant_table t) |
305 | NONE => translate_literal ctxt constant_table t) |
306 |
306 |
307 fun imp_prems_conv cv ct = |
307 fun imp_prems_conv cv ct = |
308 (case Thm.term_of ct of |
308 (case Thm.term_of ct of |
309 Const (@{const_name Pure.imp}, _) $ _ $ _ => |
309 Const (\<^const_name>\<open>Pure.imp\<close>, _) $ _ $ _ => |
310 Conv.combination_conv (Conv.arg_conv cv) (imp_prems_conv cv) ct |
310 Conv.combination_conv (Conv.arg_conv cv) (imp_prems_conv cv) ct |
311 | _ => Conv.all_conv ct) |
311 | _ => Conv.all_conv ct) |
312 |
312 |
313 fun preprocess_intro thy rule = |
313 fun preprocess_intro thy rule = |
314 Conv.fconv_rule |
314 Conv.fconv_rule |
491 Graph.strong_conn (Graph.restrict (member (op =) (Graph.all_succs gr keys)) gr) |
491 Graph.strong_conn (Graph.restrict (member (op =) (Graph.all_succs gr keys)) gr) |
492 val gr = Core_Data.intros_graph_of ctxt |
492 val gr = Core_Data.intros_graph_of ctxt |
493 val gr' = add_edges depending_preds_of const gr |
493 val gr' = add_edges depending_preds_of const gr |
494 val scc = strong_conn_of gr' [const] |
494 val scc = strong_conn_of gr' [const] |
495 val initial_constant_table = |
495 val initial_constant_table = |
496 declare_consts [@{const_name "Groups.zero_class.zero"}, @{const_name "Suc"}] [] |
496 declare_consts [\<^const_name>\<open>Groups.zero_class.zero\<close>, \<^const_name>\<open>Suc\<close>] [] |
497 in |
497 in |
498 (case use_modes of |
498 (case use_modes of |
499 SOME mode => |
499 SOME mode => |
500 let |
500 let |
501 val moded_gr = mk_moded_clauses_graph ctxt scc gr |
501 val moded_gr = mk_moded_clauses_graph ctxt scc gr |
893 |
893 |
894 |
894 |
895 (* restoring types in terms *) |
895 (* restoring types in terms *) |
896 |
896 |
897 fun restore_term ctxt constant_table (Var s, T) = Free (s, T) |
897 fun restore_term ctxt constant_table (Var s, T) = Free (s, T) |
898 | restore_term ctxt constant_table (Number n, @{typ "int"}) = HOLogic.mk_number @{typ "int"} n |
898 | restore_term ctxt constant_table (Number n, \<^typ>\<open>int\<close>) = HOLogic.mk_number \<^typ>\<open>int\<close> n |
899 | restore_term ctxt constant_table (Number n, _) = raise (Fail "unexpected type for number") |
899 | restore_term ctxt constant_table (Number n, _) = raise (Fail "unexpected type for number") |
900 | restore_term ctxt constant_table (Cons s, T) = Const (restore_const constant_table s, T) |
900 | restore_term ctxt constant_table (Cons s, T) = Const (restore_const constant_table s, T) |
901 | restore_term ctxt constant_table (AppF (f, args), T) = |
901 | restore_term ctxt constant_table (AppF (f, args), T) = |
902 let |
902 let |
903 val thy = Proof_Context.theory_of ctxt |
903 val thy = Proof_Context.theory_of ctxt |
952 fun values ctxt soln t_compr = |
952 fun values ctxt soln t_compr = |
953 let |
953 let |
954 val options = code_options_of (Proof_Context.theory_of ctxt) |
954 val options = code_options_of (Proof_Context.theory_of ctxt) |
955 val split = |
955 val split = |
956 (case t_compr of |
956 (case t_compr of |
957 (Const (@{const_name Collect}, _) $ t) => t |
957 (Const (\<^const_name>\<open>Collect\<close>, _) $ t) => t |
958 | _ => error ("Not a set comprehension: " ^ Syntax.string_of_term ctxt t_compr)) |
958 | _ => error ("Not a set comprehension: " ^ Syntax.string_of_term ctxt t_compr)) |
959 val (body, Ts, fp) = HOLogic.strip_ptupleabs split |
959 val (body, Ts, fp) = HOLogic.strip_ptupleabs split |
960 val output_names = Name.variant_list (Term.add_free_names body []) |
960 val output_names = Name.variant_list (Term.add_free_names body []) |
961 (map (fn i => "x" ^ string_of_int i) (1 upto length Ts)) |
961 (map (fn i => "x" ^ string_of_int i) (1 upto length Ts)) |
962 val output_frees = rev (map2 (curry Free) output_names Ts) |
962 val output_frees = rev (map2 (curry Free) output_names Ts) |
978 val constant_table' = declare_consts (fold Term.add_const_names all_args []) constant_table |
978 val constant_table' = declare_consts (fold Term.add_const_names all_args []) constant_table |
979 val args' = map (translate_term ctxt constant_table') all_args |
979 val args' = map (translate_term ctxt constant_table') all_args |
980 val _ = tracing "Running prolog program..." |
980 val _ = tracing "Running prolog program..." |
981 val tss = run ctxt p (translate_const constant_table' name, args') output_names soln |
981 val tss = run ctxt p (translate_const constant_table' name, args') output_names soln |
982 val _ = tracing "Restoring terms..." |
982 val _ = tracing "Restoring terms..." |
983 val empty = Const(@{const_name bot}, fastype_of t_compr) |
983 val empty = Const(\<^const_name>\<open>bot\<close>, fastype_of t_compr) |
984 fun mk_insert x S = |
984 fun mk_insert x S = |
985 Const (@{const_name "Set.insert"}, fastype_of x --> fastype_of S --> fastype_of S) $ x $ S |
985 Const (\<^const_name>\<open>Set.insert\<close>, fastype_of x --> fastype_of S --> fastype_of S) $ x $ S |
986 fun mk_set_compr in_insert [] xs = |
986 fun mk_set_compr in_insert [] xs = |
987 rev ((Free ("dots", fastype_of t_compr)) :: (* FIXME proper name!? *) |
987 rev ((Free ("dots", fastype_of t_compr)) :: (* FIXME proper name!? *) |
988 (if null in_insert then xs else (fold mk_insert in_insert empty) :: xs)) |
988 (if null in_insert then xs else (fold mk_insert in_insert empty) :: xs)) |
989 | mk_set_compr in_insert (t :: ts) xs = |
989 | mk_set_compr in_insert (t :: ts) xs = |
990 let |
990 let |
997 val uu as (uuN, uuT) = |
997 val uu as (uuN, uuT) = |
998 singleton (Variable.variant_frees ctxt' [t]) ("uu", fastype_of t) |
998 singleton (Variable.variant_frees ctxt' [t]) ("uu", fastype_of t) |
999 val set_compr = |
999 val set_compr = |
1000 HOLogic.mk_Collect (uuN, uuT, |
1000 HOLogic.mk_Collect (uuN, uuT, |
1001 fold (fn (s, T) => fn t => HOLogic.mk_exists (s, T, t)) |
1001 fold (fn (s, T) => fn t => HOLogic.mk_exists (s, T, t)) |
1002 frees (HOLogic.mk_conj (HOLogic.mk_eq (Free uu, t), @{term "True"}))) |
1002 frees (HOLogic.mk_conj (HOLogic.mk_eq (Free uu, t), \<^term>\<open>True\<close>))) |
1003 in |
1003 in |
1004 mk_set_compr [] ts |
1004 mk_set_compr [] ts |
1005 (set_compr :: |
1005 (set_compr :: |
1006 (if null in_insert then xs else (fold mk_insert in_insert empty) :: xs)) |
1006 (if null in_insert then xs else (fold mk_insert in_insert empty) :: xs)) |
1007 end |
1007 end |
1008 end |
1008 end |
1009 in |
1009 in |
1010 foldl1 (HOLogic.mk_binop @{const_name sup}) (mk_set_compr [] |
1010 foldl1 (HOLogic.mk_binop \<^const_name>\<open>sup\<close>) (mk_set_compr [] |
1011 (map (fn ts => HOLogic.mk_tuple |
1011 (map (fn ts => HOLogic.mk_tuple |
1012 (map (restore_nat_numerals o restore_term ctxt' constant_table) (ts ~~ Ts))) tss) []) |
1012 (map (restore_nat_numerals o restore_term ctxt' constant_table) (ts ~~ Ts))) tss) []) |
1013 end |
1013 end |
1014 |
1014 |
1015 fun values_cmd print_modes soln raw_t state = |
1015 fun values_cmd print_modes soln raw_t state = |
1028 |
1028 |
1029 |
1029 |
1030 (* values command for Prolog queries *) |
1030 (* values command for Prolog queries *) |
1031 |
1031 |
1032 val opt_print_modes = |
1032 val opt_print_modes = |
1033 Scan.optional (@{keyword "("} |-- Parse.!!! (Scan.repeat1 Parse.name --| @{keyword ")"})) [] |
1033 Scan.optional (\<^keyword>\<open>(\<close> |-- Parse.!!! (Scan.repeat1 Parse.name --| \<^keyword>\<open>)\<close>)) [] |
1034 |
1034 |
1035 val _ = |
1035 val _ = |
1036 Outer_Syntax.command @{command_keyword values_prolog} |
1036 Outer_Syntax.command \<^command_keyword>\<open>values_prolog\<close> |
1037 "enumerate and print comprehensions" |
1037 "enumerate and print comprehensions" |
1038 (opt_print_modes -- Scan.optional (Parse.nat >> SOME) NONE -- Parse.term |
1038 (opt_print_modes -- Scan.optional (Parse.nat >> SOME) NONE -- Parse.term |
1039 >> (fn ((print_modes, soln), t) => Toplevel.keep (values_cmd print_modes soln t))) |
1039 >> (fn ((print_modes, soln), t) => Toplevel.keep (values_cmd print_modes soln t))) |
1040 |
1040 |
1041 |
1041 |
1042 (* quickcheck generator *) |
1042 (* quickcheck generator *) |
1043 |
1043 |
1044 (* FIXME: a small clone of Predicate_Compile_Quickcheck - maybe refactor out commons *) |
1044 (* FIXME: a small clone of Predicate_Compile_Quickcheck - maybe refactor out commons *) |
1045 |
1045 |
1046 val active = Attrib.setup_config_bool @{binding quickcheck_prolog_active} (K true) |
1046 val active = Attrib.setup_config_bool \<^binding>\<open>quickcheck_prolog_active\<close> (K true) |
1047 |
1047 |
1048 fun test_term ctxt (t, eval_terms) = |
1048 fun test_term ctxt (t, eval_terms) = |
1049 let |
1049 let |
1050 val t' = fold_rev absfree (Term.add_frees t []) t |
1050 val t' = fold_rev absfree (Term.add_frees t []) t |
1051 val options = code_options_of (Proof_Context.theory_of ctxt) |
1051 val options = code_options_of (Proof_Context.theory_of ctxt) |
1052 val thy = Proof_Context.theory_of ctxt |
1052 val thy = Proof_Context.theory_of ctxt |
1053 val ((((full_constname, constT), vs'), intro), thy1) = |
1053 val ((((full_constname, constT), vs'), intro), thy1) = |
1054 Predicate_Compile_Aux.define_quickcheck_predicate t' thy |
1054 Predicate_Compile_Aux.define_quickcheck_predicate t' thy |
1055 val thy2 = |
1055 val thy2 = |
1056 Context.theory_map (Named_Theorems.add_thm @{named_theorems code_pred_def} intro) thy1 |
1056 Context.theory_map (Named_Theorems.add_thm \<^named_theorems>\<open>code_pred_def\<close> intro) thy1 |
1057 val thy3 = Predicate_Compile.preprocess preprocess_options (Const (full_constname, constT)) thy2 |
1057 val thy3 = Predicate_Compile.preprocess preprocess_options (Const (full_constname, constT)) thy2 |
1058 val ctxt' = Proof_Context.init_global thy3 |
1058 val ctxt' = Proof_Context.init_global thy3 |
1059 val _ = tracing "Generating prolog program..." |
1059 val _ = tracing "Generating prolog program..." |
1060 val (p, constant_table) = generate (NONE, true) ctxt' full_constname |
1060 val (p, constant_table) = generate (NONE, true) ctxt' full_constname |
1061 |> post_process ctxt' (set_ensure_groundness options) full_constname |
1061 |> post_process ctxt' (set_ensure_groundness options) full_constname |