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 | #:export (z3-eval |
32 | run-with-z3)) |
33 | |
34 | ;;; Dynamic linking to foreign functions |
35 | (define libz3 (dynamic-link "@Z3_LIBDIR@/libz3")) |
36 | |
37 | (define z3-mk-config |
38 | (pointer->procedure '* (dynamic-func "Z3_mk_config" libz3) '())) |
39 | (define z3-del-config |
40 | (pointer->procedure void (dynamic-func "Z3_del_config" libz3) (list '*))) |
41 | |
42 | (define z3-mk-context |
43 | (pointer->procedure '* (dynamic-func "Z3_mk_context" libz3) (list '*))) |
44 | (define z3-del-context |
45 | (pointer->procedure void (dynamic-func "Z3_del_context" libz3) (list '*))) |
46 | |
47 | (define z3-eval-smtlib2-string |
48 | (pointer->procedure '* (dynamic-func "Z3_eval_smtlib2_string" libz3) (list '* '*))) |
49 | |
50 | (define z3-set-error-handler |
51 | (pointer->procedure void (dynamic-func "Z3_set_error_handler" libz3) (list '* '*))) |
52 | (define get-error |
53 | (dynamic-func "Z3_get_error_msg" libz3)) |
54 | |
55 | ;;; Utility function |
56 | |
57 | (define (sexp->string sexp) |
58 | "Converts an s-expression to a string, to be passed to eval-smtlib2" |
59 | (with-output-to-string |
60 | (lambda _ |
61 | (write sexp)))) |
62 | |
63 | ;;; Interface |
64 | |
65 | (define (z3-eval context query) |
66 | "Runs a query as an SMT-LIB2 s-expression in the Z3 context. See the Z3 |
67 | manual for more information on the expected format." |
68 | (let* ((query (sexp->string query)) |
69 | (ans (z3-eval-smtlib2-string |
70 | context |
71 | (string->pointer |
72 | (substring query 1 (- (string-length query) 1)))))) |
73 | (call-with-input-string (pointer->string ans) read))) |
74 | |
75 | (define (run-with-z3 thunk) |
76 | "Runs a one-argument procedure in a new Z3 context. The only argument to that |
77 | procedure is the newly-created Z3 context." |
78 | (let* ((conf (z3-mk-config)) |
79 | (ctx (z3-mk-context conf)) |
80 | (_ (z3-set-error-handler ctx get-error))) |
81 | (dynamic-wind |
82 | (lambda () #t) |
83 | (lambda () (thunk ctx)) |
84 | (lambda () |
85 | (z3-del-context ctx) |
86 | (z3-del-config conf))))) |
87 |