guile-z3/z3.scm.in

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