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
  #: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