-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsmt.rkt
95 lines (82 loc) · 2.75 KB
/
smt.rkt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#lang racket
(require "common.rkt")
(provide define-constraints smt? smt-cond smt-let smt-let* smt-not smt-and smt-or smt-replace smt-replace-terms
and-assertions disassemble-forall)
(define smt? any/c)
(define-syntax smt-cond
(syntax-rules (else)
[(smt-cond [else body])
`body]
[(smt-cond [else body ...])
`(and body ...)]
[(smt-cond [test body] rest ...)
`(ite test body ,(smt-cond rest ...))]
[(smt-cond [test body ...] rest ...)
`(ite test (and body ...) ,(smt-cond rest ...))]))
(define-syntax-rule (define-constraints name body ...)
(define name `(body ...)))
(define-syntax-rule (smt-let bindings constraints ...)
`(let bindings (and constraints ...)))
(define-syntax smt-let*
(syntax-rules ()
[(smt-let* () constraint)
`constraint]
[(smt-let* () constraints ...)
`(and constraints ...)]
[(smt-let* ([a b] rest ...) constraints ...)
`(let ([a b]) ,(smt-let* (rest ...) constraints ...))]))
(define (smt-not x)
(match x
['true 'false]
['false 'true]
[_ (list 'not x)]))
(define (smt-and . pieces)
(define pieces* (filter (λ (x) (not (equal? x 'true))) pieces))
(if (ormap (curry equal? 'false) pieces*)
'false
(match pieces*
['() 'true]
[(list x) x]
[xs (cons 'and xs)])))
(define (smt-or . pieces)
(define pieces* (filter (λ (x) (not (equal? x 'false))) pieces))
(if (ormap (curry equal? 'true) pieces*)
'true
(match pieces*
['() 'false]
[(list x) x]
[xs (cons 'or xs)])))
(define (smt-replace-terms expr bindings)
(match expr
[(? (curry dict-has-key? bindings)) (dict-ref bindings expr)]
[`(let ((,vars ,vals) ...) ,body)
`(let (,@(map list vars (map (curryr smt-replace-terms bindings) vals)))
,(smt-replace-terms body (dict-remove* bindings vars)))]
[(? list?) (map (curryr smt-replace-terms bindings) expr)]
[_ expr]))
(define-syntax-rule (smt-replace expr [pattern body ...] ...)
(let loop ([e expr])
(match e
[(list 'let bindings body2)
(define bindings* (for/list ([b bindings]) (list (car b) (loop (cadr b)))))
(list 'let bindings* (loop body2))]
[pattern body ...] ...
[x
(if (list? x)
(cons (car x) (map loop (cdr x)))
x)])))
(define/match (disassemble-forall a)
[(`(forall (,vars ...) ,body))
(values vars body)]
[(body)
(values '() body)])
(define (and-assertions . as)
(define-values (vars body)
(let loop ([as as])
(match as
['() (values '() 'true)]
[(cons a as)
(define-values (avars abody) (disassemble-forall a))
(define-values (bvars bbody) (loop as))
(values (set-union avars bvars) (smt-and abody bbody))])))
`(forall ,vars ,body))