z3.scm.in
1 | ;; Guile-Z3 |
2 | ;; Copyright (C) 2020 Julien Lepiller <julien@lepiller.eu> |
3 | |
4 | ;; This library is free software; you can redistribute it and/or modify |
5 | ;; it under the terms of the GNU Lesser General Public License as |
6 | ;; published by the Free Software Foundation; either version 3 of the |
7 | ;; License, or (at your option) any later version. |
8 | ;; |
9 | ;; This library is distributed in the hope that it will be useful, but |
10 | ;; WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | ;; Lesser General Public License for more details. |
13 | ;; |
14 | ;; You should have received a copy of the GNU Lesser General Public |
15 | ;; License along with this program; if not, contact: |
16 | ;; |
17 | ;; Free Software Foundation Voice: +1-617-542-5942 |
18 | ;; 59 Temple Place - Suite 330 Fax: +1-617-542-2652 |
19 | ;; Boston, MA 02111-1307, USA gnu@gnu.org |
20 | |
21 | ;;; Commentary: |
22 | ;; |
23 | ;; A Guile binding for the Z3 Theorem Prover. |
24 | ;; |
25 | ;;; Code: |
26 | |
27 | (define-module (z3) |
28 | #:use-module (system foreign) |
29 | #:use-module (rnrs bytevectors) |
30 | #:use-module (srfi srfi-9) |
31 | #:use-module (system base language) |
32 | #:use-module (system repl command) |
33 | #:use-module (system repl common) |
34 | #:use-module (system repl repl) |
35 | #:export (z3-eval |
36 | run-with-z3)) |
37 | |
38 | ;;; Dynamic linking to foreign functions |
39 | (define libz3 (dynamic-link "@Z3_LIBDIR@/libz3")) |
40 | |
41 | (define z3-mk-config |
42 | (pointer->procedure '* (dynamic-func "Z3_mk_config" libz3) '())) |
43 | (define z3-del-config |
44 | (pointer->procedure void (dynamic-func "Z3_del_config" libz3) (list '*))) |
45 | |
46 | (define z3-mk-context |
47 | (pointer->procedure '* (dynamic-func "Z3_mk_context" libz3) (list '*))) |
48 | (define z3-del-context |
49 | (pointer->procedure void (dynamic-func "Z3_del_context" libz3) (list '*))) |
50 | |
51 | (define z3-eval-smtlib2-string |
52 | (pointer->procedure '* (dynamic-func "Z3_eval_smtlib2_string" libz3) (list '* '*))) |
53 | |
54 | (define z3-set-error-handler |
55 | (pointer->procedure void (dynamic-func "Z3_set_error_handler" libz3) (list '* '*))) |
56 | (define get-error |
57 | (dynamic-func "Z3_get_error_msg" libz3)) |
58 | |
59 | ;;; Utility function |
60 | |
61 | (define (sexp->string sexp) |
62 | "Converts an s-expression to a string, to be passed to eval-smtlib2" |
63 | (with-output-to-string |
64 | (lambda _ |
65 | (write sexp)))) |
66 | |
67 | ;;; Interface |
68 | |
69 | (define (z3-eval context query) |
70 | "Runs a query as an SMT-LIB2 s-expression in the Z3 context. See the Z3 |
71 | manual for more information on the expected format." |
72 | (let* ((query (sexp->string query)) |
73 | (ans (z3-eval-smtlib2-string |
74 | context |
75 | (string->pointer |
76 | (substring query 1 (- (string-length query) 1)))))) |
77 | (call-with-input-string (pointer->string ans) read))) |
78 | |
79 | (define (run-with-z3 thunk) |
80 | "Runs a one-argument procedure in a new Z3 context. The only argument to that |
81 | procedure is the newly-created Z3 context." |
82 | (let* ((conf (z3-mk-config)) |
83 | (ctx (z3-mk-context conf)) |
84 | (_ (z3-set-error-handler ctx get-error))) |
85 | (dynamic-wind |
86 | (lambda () #t) |
87 | (lambda () (thunk ctx)) |
88 | (lambda () |
89 | (z3-del-context ctx) |
90 | (z3-del-config conf))))) |
91 | |
92 | (define-meta-command ((z3 exp) repl) |
93 | "Run exp in custom repl." |
94 | (run-with-z3 |
95 | (lambda (context) |
96 | (let* ((scheme (lookup-language 'scheme)) |
97 | (new (make-repl |
98 | (make-language #:name "z3" |
99 | #:title "z3" |
100 | #:reader (language-reader scheme) |
101 | #:evaluator (lambda (exp env) |
102 | (z3-eval context (list exp))) |
103 | #:printer (language-printer scheme) |
104 | #:make-default-environment |
105 | (language-make-default-environment scheme))))) |
106 | (repl-option-set! new 'interp #t) |
107 | (run-repl new))))) |
108 |