56 datatype arith_op = Plus | Minus |
56 datatype arith_op = Plus | Minus |
57 |
57 |
58 datatype prol_term = Var of string | Cons of string | AppF of string * prol_term list |
58 datatype prol_term = Var of string | Cons of string | AppF of string * prol_term list |
59 | Number of int | ArithOp of arith_op * prol_term list; |
59 | Number of int | ArithOp of arith_op * prol_term list; |
60 |
60 |
|
61 fun dest_Var (Var v) = v |
|
62 |
|
63 fun add_vars (Var v) = insert (op =) v |
|
64 | add_vars (ArithOp (_, ts)) = fold add_vars ts |
|
65 | add_vars (AppF (_, ts)) = fold add_vars ts |
|
66 | add_vars _ = I |
|
67 |
|
68 fun map_vars f (Var v) = Var (f v) |
|
69 | map_vars f (ArithOp (opr, ts)) = ArithOp (opr, map (map_vars f) ts) |
|
70 | map_vars f (AppF (fs, ts)) = AppF (fs, map (map_vars f) ts) |
|
71 | map_vars f t = t |
|
72 |
61 fun maybe_AppF (c, []) = Cons c |
73 fun maybe_AppF (c, []) = Cons c |
62 | maybe_AppF (c, xs) = AppF (c, xs) |
74 | maybe_AppF (c, xs) = AppF (c, xs) |
63 |
75 |
64 fun is_Var (Var _) = true |
76 fun is_Var (Var _) = true |
65 | is_Var _ = false |
77 | is_Var _ = false |
77 datatype prem = Conj of prem list |
89 datatype prem = Conj of prem list |
78 | Rel of string * prol_term list | NotRel of string * prol_term list |
90 | Rel of string * prol_term list | NotRel of string * prol_term list |
79 | Eq of prol_term * prol_term | NotEq of prol_term * prol_term |
91 | Eq of prol_term * prol_term | NotEq of prol_term * prol_term |
80 | ArithEq of prol_term * prol_term | NotArithEq of prol_term * prol_term |
92 | ArithEq of prol_term * prol_term | NotArithEq of prol_term * prol_term |
81 | Ground of string * typ; |
93 | Ground of string * typ; |
82 |
94 |
83 fun dest_Rel (Rel (c, ts)) = (c, ts) |
95 fun dest_Rel (Rel (c, ts)) = (c, ts) |
84 |
96 |
|
97 fun map_term_prem f (Conj prems) = Conj (map (map_term_prem f) prems) |
|
98 | map_term_prem f (Rel (r, ts)) = Rel (r, map f ts) |
|
99 | map_term_prem f (NotRel (r, ts)) = NotRel (r, map f ts) |
|
100 | map_term_prem f (Eq (l, r)) = Eq (f l, f r) |
|
101 | map_term_prem f (NotEq (l, r)) = NotEq (f l, f r) |
|
102 | map_term_prem f (ArithEq (l, r)) = ArithEq (f l, f r) |
|
103 | map_term_prem f (NotArithEq (l, r)) = NotArithEq (f l, f r) |
|
104 | map_term_prem f (Ground (v, T)) = Ground (dest_Var (f (Var v)), T) |
|
105 |
|
106 fun fold_prem_terms f (Conj prems) = fold (fold_prem_terms f) prems |
|
107 | fold_prem_terms f (Rel (_, ts)) = fold f ts |
|
108 | fold_prem_terms f (NotRel (_, ts)) = fold f ts |
|
109 | fold_prem_terms f (Eq (l, r)) = f l #> f r |
|
110 | fold_prem_terms f (NotEq (l, r)) = f l #> f r |
|
111 | fold_prem_terms f (ArithEq (l, r)) = f l #> f r |
|
112 | fold_prem_terms f (NotArithEq (l, r)) = f l #> f r |
|
113 | fold_prem_terms f (Ground (v, T)) = f (Var v) |
|
114 |
85 type clause = ((string * prol_term list) * prem); |
115 type clause = ((string * prol_term list) * prem); |
86 |
116 |
87 type logic_program = clause list; |
117 type logic_program = clause list; |
88 |
118 |
89 (* translation from introduction rules to internal representation *) |
119 (* translation from introduction rules to internal representation *) |
306 val p' = map (apsnd replace_ground) p |
336 val p' = map (apsnd replace_ground) p |
307 in |
337 in |
308 ((flat grs) @ p', constant_table') |
338 ((flat grs) @ p', constant_table') |
309 end |
339 end |
310 |
340 |
|
341 (* rename variables to prolog-friendly names *) |
|
342 |
|
343 fun rename_vars_term renaming = map_vars (fn v => the (AList.lookup (op =) renaming v)) |
|
344 |
|
345 fun rename_vars_prem renaming = map_term_prem (rename_vars_term renaming) |
|
346 |
|
347 fun dest_Char (Symbol.Char c) = c |
|
348 |
|
349 fun is_prolog_conform v = |
|
350 forall (fn s => Symbol.is_ascii_letter s orelse Symbol.is_ascii_digit s) (Symbol.explode v) |
|
351 |
|
352 fun mk_conform avoid v = |
|
353 let |
|
354 val v' = space_implode "" (map (dest_Char o Symbol.decode) |
|
355 (filter (fn s => Symbol.is_ascii_letter s orelse Symbol.is_ascii_digit s) |
|
356 (Symbol.explode v))) |
|
357 val v' = if v' = "" then "var" else v' |
|
358 in Name.variant avoid (first_upper v') end |
|
359 |
|
360 fun mk_renaming v renaming = |
|
361 (v, mk_conform (map snd renaming) v) :: renaming |
|
362 |
|
363 fun rename_vars_clause ((rel, args), prem) = |
|
364 let |
|
365 val vars = fold_prem_terms add_vars prem (fold add_vars args []) |
|
366 val renaming = fold mk_renaming vars [] |
|
367 in ((rel, map (rename_vars_term renaming) args), rename_vars_prem renaming prem) end |
|
368 |
|
369 val rename_vars_program = map rename_vars_clause |
|
370 |
311 (* code printer *) |
371 (* code printer *) |
312 |
372 |
313 fun write_arith_op Plus = "+" |
373 fun write_arith_op Plus = "+" |
314 | write_arith_op Minus = "-" |
374 | write_arith_op Minus = "-" |
315 |
375 |
316 fun write_term (Var v) = first_upper v |
376 fun write_term (Var v) = v |
317 | write_term (Cons c) = c |
377 | write_term (Cons c) = c |
318 | write_term (AppF (f, args)) = f ^ "(" ^ space_implode ", " (map write_term args) ^ ")" |
378 | write_term (AppF (f, args)) = f ^ "(" ^ space_implode ", " (map write_term args) ^ ")" |
319 | write_term (ArithOp (oper, [a1, a2])) = write_term a1 ^ " " ^ write_arith_op oper ^ " " ^ write_term a2 |
379 | write_term (ArithOp (oper, [a1, a2])) = write_term a1 ^ " " ^ write_arith_op oper ^ " " ^ write_term a2 |
320 | write_term (Number n) = string_of_int n |
380 | write_term (Number n) = string_of_int n |
321 |
381 |
412 (* calling external interpreter and getting results *) |
472 (* calling external interpreter and getting results *) |
413 |
473 |
414 fun run p query_rel vnames nsols = |
474 fun run p query_rel vnames nsols = |
415 let |
475 let |
416 val cmd = Path.named_root |
476 val cmd = Path.named_root |
417 val query = case nsols of NONE => query_first | SOME n => query_firstn n |
477 val query = case nsols of NONE => query_first | SOME n => query_firstn n |
418 val prog = prelude ^ query query_rel vnames ^ write_program p |
478 val p' = rename_vars_program p |
|
479 val _ = tracing "Renaming variable names..." |
|
480 val renaming = fold mk_renaming vnames [] |
|
481 val vnames' = map (fn v => the (AList.lookup (op =) renaming v)) vnames |
|
482 val prog = prelude ^ query query_rel vnames' ^ write_program p' |
419 val _ = tracing ("Generated prolog program:\n" ^ prog) |
483 val _ = tracing ("Generated prolog program:\n" ^ prog) |
420 val prolog_file = File.tmp_path (Path.basic "prolog_file") |
484 val prolog_file = File.tmp_path (Path.basic "prolog_file") |
421 val _ = File.write prolog_file prog |
485 val _ = File.write prolog_file prog |
422 val (solution, _) = bash_output ("/usr/local/bin/swipl -f " ^ File.shell_path prolog_file) |
486 val (solution, _) = bash_output ("/usr/local/bin/swipl -f " ^ File.shell_path prolog_file) |
423 val _ = tracing ("Prolog returned solution(s):\n" ^ solution) |
487 val _ = tracing ("Prolog returned solution(s):\n" ^ solution) |
563 val ctxt'' = ProofContext.init_global thy3 |
627 val ctxt'' = ProofContext.init_global thy3 |
564 val _ = tracing "Generating prolog program..." |
628 val _ = tracing "Generating prolog program..." |
565 val (p, constant_table) = generate {ensure_groundness = true} ctxt'' full_constname |
629 val (p, constant_table) = generate {ensure_groundness = true} ctxt'' full_constname |
566 |> add_ground_predicates ctxt'' |
630 |> add_ground_predicates ctxt'' |
567 val _ = tracing "Running prolog program..." |
631 val _ = tracing "Running prolog program..." |
568 val [ts] = run p (translate_const constant_table full_constname) (map (first_upper o fst) vs') |
632 val [ts] = run p (translate_const constant_table full_constname) (map fst vs') |
569 (SOME 1) |
633 (SOME 1) |
570 val _ = tracing "Restoring terms..." |
634 val _ = tracing "Restoring terms..." |
571 val res = SOME (map (restore_term ctxt'' constant_table) (ts ~~ Ts)) |
635 val res = SOME (map (restore_term ctxt'' constant_table) (ts ~~ Ts)) |
572 val empty_report = ([], false) |
636 val empty_report = ([], false) |
573 in |
637 in |