799 lines
24 KiB
Racket
799 lines
24 KiB
Racket
#lang racket
|
|
|
|
|
|
;; TODO: figure out what should actually be 'provide'd.
|
|
|
|
(provide (all-defined-out))
|
|
|
|
;; A Note on changes: define-macro isn't so nice, but
|
|
;; someone (Dorai?) helpfully provided commented-out
|
|
;; versions of each macro in syntax-rules style.
|
|
;; Unfortunately, they didn't compile, but this seemed
|
|
;; related to an inability to capture the '!' name.
|
|
;; The easiest way to fix this was just to take the
|
|
;; classic "make 'em put the identifier in there" approach,
|
|
;; which means that uses of cut and rel must now include
|
|
;; a bang explicitly. It wouldn't be too hard to change
|
|
;; back to a capturing macro; I know syntax-case can do
|
|
;; it, I don't know if syntax-rules can.
|
|
|
|
;; Also, I changed a few top-level mutable bindings into
|
|
;; boxed bindings.
|
|
|
|
;;-- JBC, 2010-04-22
|
|
|
|
|
|
;MzScheme version of
|
|
;schelog.scm
|
|
;Schelog
|
|
;An embedding of Prolog in Scheme
|
|
;Dorai Sitaram
|
|
;1989, revised Feb. 1993, Mar. 1997
|
|
|
|
;logic variables and their manipulation
|
|
|
|
(define schelog:*ref* "ref")
|
|
|
|
(define schelog:*unbound* '_)
|
|
|
|
(define schelog:make-ref
|
|
;;makes a fresh unbound ref;
|
|
;;unbound refs point to themselves
|
|
(lambda opt
|
|
(vector schelog:*ref*
|
|
(if (null? opt) schelog:*unbound*
|
|
(car opt)))))
|
|
|
|
(define _ schelog:make-ref)
|
|
|
|
(define schelog:ref?
|
|
(lambda (r)
|
|
(and (vector? r)
|
|
(eq? (vector-ref r 0) schelog:*ref*))))
|
|
|
|
(define schelog:deref
|
|
(lambda (r)
|
|
(vector-ref r 1)))
|
|
|
|
(define schelog:set-ref!
|
|
(lambda (r v)
|
|
(vector-set! r 1 v)))
|
|
|
|
(define schelog:unbound-ref?
|
|
(lambda (r)
|
|
(eq? (schelog:deref r) schelog:*unbound*)))
|
|
|
|
(define schelog:unbind-ref!
|
|
(lambda (r)
|
|
(schelog:set-ref! r schelog:*unbound*)))
|
|
|
|
;frozen logic vars
|
|
|
|
(define schelog:*frozen* "frozen")
|
|
|
|
(define schelog:freeze-ref
|
|
(lambda (r)
|
|
(schelog:make-ref (vector schelog:*frozen* r))))
|
|
|
|
(define schelog:thaw-frozen-ref
|
|
(lambda (r)
|
|
(vector-ref (schelog:deref r) 1)))
|
|
|
|
(define schelog:frozen-ref?
|
|
(lambda (r)
|
|
(let ((r2 (schelog:deref r)))
|
|
(and (vector? r2)
|
|
(eq? (vector-ref r2 0) schelog:*frozen*)))))
|
|
|
|
;deref a structure completely (except the frozen ones, i.e.)
|
|
|
|
(define schelog:deref*
|
|
(lambda (s)
|
|
(cond ((schelog:ref? s)
|
|
(if (schelog:frozen-ref? s) s
|
|
(schelog:deref* (schelog:deref s))))
|
|
((pair? s) (cons (schelog:deref* (car s))
|
|
(schelog:deref* (cdr s))))
|
|
((vector? s)
|
|
(list->vector (map schelog:deref* (vector->list s))))
|
|
(else s))))
|
|
|
|
;%let introduces new logic variables
|
|
|
|
(define-syntax %let
|
|
(syntax-rules ()
|
|
((%let (x ...) . e)
|
|
(let ((x (schelog:make-ref)) ...)
|
|
. e))))
|
|
|
|
#;(define-macro %let
|
|
(lambda (xx . ee)
|
|
`(let ,(map (lambda (x) `(,x (schelog:make-ref))) xx)
|
|
,@ee)))
|
|
|
|
;the unify predicate
|
|
|
|
(define schelog-use-occurs-check? (make-parameter #f))
|
|
|
|
(define schelog:occurs-in?
|
|
(lambda (var term)
|
|
(and (schelog-use-occurs-check?)
|
|
(let loop ((term term))
|
|
(cond ((eqv? var term) #t)
|
|
((schelog:ref? term)
|
|
(cond ((schelog:unbound-ref? term) #f)
|
|
((schelog:frozen-ref? term) #f)
|
|
(else (loop (schelog:deref term)))))
|
|
((pair? term)
|
|
(or (loop (car term)) (loop (cdr term))))
|
|
((vector? term)
|
|
(loop (vector->list term)))
|
|
(else #f))))))
|
|
|
|
(define schelog:unify
|
|
(lambda (t1 t2)
|
|
(lambda (fk)
|
|
(letrec
|
|
((cleanup-n-fail
|
|
(lambda (s)
|
|
(for-each schelog:unbind-ref! s)
|
|
(fk 'fail)))
|
|
(unify1
|
|
(lambda (t1 t2 s)
|
|
;(printf "unify1 ~s ~s~%" t1 t2)
|
|
(cond ((eqv? t1 t2) s)
|
|
((schelog:ref? t1)
|
|
(cond ((schelog:unbound-ref? t1)
|
|
(cond ((schelog:occurs-in? t1 t2)
|
|
(cleanup-n-fail s))
|
|
(else
|
|
(schelog:set-ref! t1 t2)
|
|
(cons t1 s))))
|
|
((schelog:frozen-ref? t1)
|
|
(cond ((schelog:ref? t2)
|
|
(cond ((schelog:unbound-ref? t2)
|
|
;(printf "t2 is unbound~%")
|
|
(unify1 t2 t1 s))
|
|
((schelog:frozen-ref? t2)
|
|
(cleanup-n-fail s))
|
|
(else
|
|
(unify1 t1 (schelog:deref t2) s))))
|
|
(else (cleanup-n-fail s))))
|
|
(else
|
|
;(printf "derefing t1~%")
|
|
(unify1 (schelog:deref t1) t2 s))))
|
|
((schelog:ref? t2) (unify1 t2 t1 s))
|
|
((and (pair? t1) (pair? t2))
|
|
(unify1 (cdr t1) (cdr t2)
|
|
(unify1 (car t1) (car t2) s)))
|
|
((and (string? t1) (string? t2))
|
|
(if (string=? t1 t2) s
|
|
(cleanup-n-fail s)))
|
|
((and (vector? t1) (vector? t2))
|
|
(unify1 (vector->list t1)
|
|
(vector->list t2) s))
|
|
(else
|
|
(for-each schelog:unbind-ref! s)
|
|
(fk 'fail))))))
|
|
(let ((s (unify1 t1 t2 '())))
|
|
(lambda (d)
|
|
(cleanup-n-fail s)))))))
|
|
|
|
(define %= schelog:unify)
|
|
|
|
;disjunction
|
|
|
|
(define-syntax %or
|
|
(syntax-rules ()
|
|
((%or g ...)
|
|
(lambda (__fk)
|
|
(call-with-current-continuation
|
|
(lambda (__sk)
|
|
(call-with-current-continuation
|
|
(lambda (__fk)
|
|
(__sk ((schelog:deref* g) __fk))))
|
|
...
|
|
(__fk 'fail)))))))
|
|
|
|
#;(define-macro %or
|
|
(lambda gg
|
|
`(lambda (__fk)
|
|
(call-with-current-continuation
|
|
(lambda (__sk)
|
|
,@(map (lambda (g)
|
|
`(call-with-current-continuation
|
|
(lambda (__fk)
|
|
(__sk ((schelog:deref* ,g) __fk)))))
|
|
gg)
|
|
(__fk 'fail))))))
|
|
|
|
;conjunction
|
|
|
|
(define-syntax %and
|
|
(syntax-rules ()
|
|
((%and g ...)
|
|
(lambda (__fk)
|
|
(let* ((__fk ((schelog:deref* g) __fk))
|
|
...)
|
|
__fk)))))
|
|
|
|
#;(define-macro %and
|
|
(lambda gg
|
|
`(lambda (__fk)
|
|
(let* ,(map (lambda (g) `(__fk ((schelog:deref* ,g) __fk))) gg)
|
|
__fk))))
|
|
|
|
(define (! fk) (error '! "May only be used inside goal expression."))
|
|
|
|
;cut
|
|
|
|
(define-syntax (%cut-delimiter stx)
|
|
(syntax-case stx ()
|
|
((%cut-delimiter g)
|
|
(with-syntax ([! #'!])
|
|
(syntax/loc stx
|
|
(lambda (__fk)
|
|
(let ((! (lambda (__fk2) __fk)))
|
|
((schelog:deref* g) __fk))))))))
|
|
|
|
#;(define-macro %cut-delimiter
|
|
(lambda (g)
|
|
`(lambda (__fk)
|
|
(let ((! (lambda (__fk2) __fk)))
|
|
((schelog:deref* ,g) __fk)))))
|
|
|
|
;Prolog-like sugar
|
|
|
|
(define-syntax (%rel stx)
|
|
(syntax-case stx ()
|
|
((%rel (v ...) ((a ...) subgoal ...) ...)
|
|
(with-syntax ([! #'!])
|
|
(syntax/loc stx
|
|
(lambda __fmls
|
|
(lambda (__fk)
|
|
(call-with-current-continuation
|
|
(lambda (__sk)
|
|
(let ((! (lambda (fk1) __fk)))
|
|
(%let (v ...)
|
|
(call-with-current-continuation
|
|
(lambda (__fk)
|
|
(let* ((__fk ((%= __fmls (list a ...)) __fk))
|
|
(__fk ((schelog:deref* subgoal) __fk))
|
|
...)
|
|
(__sk __fk))))
|
|
...
|
|
(__fk 'fail))))))))))))
|
|
|
|
#;(define-macro %rel
|
|
(lambda (vv . cc)
|
|
`(lambda __fmls
|
|
(lambda (__fk)
|
|
(call-with-current-continuation
|
|
(lambda (__sk)
|
|
(let ((! (lambda (fk1) __fk)))
|
|
(%let ,vv
|
|
,@(map (lambda (c)
|
|
`(call-with-current-continuation
|
|
(lambda (__fk)
|
|
(let* ((__fk ((%= __fmls (list ,@(car c)))
|
|
__fk))
|
|
,@(map (lambda (sg)
|
|
`(__fk ((schelog:deref* ,sg)
|
|
__fk)))
|
|
(cdr c)))
|
|
(__sk __fk)))))
|
|
cc)
|
|
(__fk 'fail)))))))))
|
|
|
|
;the fail and true preds
|
|
|
|
(define %fail
|
|
(lambda (fk) (fk 'fail)))
|
|
|
|
(define %true
|
|
(lambda (fk) fk))
|
|
|
|
;for structures ("functors"), use Scheme's list and vector
|
|
;functions and anything that's built using them.
|
|
|
|
;arithmetic
|
|
|
|
(define-syntax %is
|
|
(syntax-rules (quote)
|
|
((%is v e)
|
|
(lambda (__fk)
|
|
((%= v (%is (1) e __fk)) __fk)))
|
|
|
|
((%is (1) (quote x) fk) (quote x))
|
|
((%is (1) (x ...) fk)
|
|
((%is (1) x fk) ...))
|
|
((%is (1) x fk)
|
|
(if (and (schelog:ref? x) (schelog:unbound-ref? x))
|
|
(fk 'fail) (schelog:deref* x)))))
|
|
|
|
#;(define-macro %is
|
|
(lambda (v e)
|
|
(letrec ((%is-help (lambda (e fk)
|
|
(cond ((pair? e)
|
|
(cond ((eq? (car e) 'quote) e)
|
|
(else
|
|
(map (lambda (e1)
|
|
(%is-help e1 fk)) e))))
|
|
(else
|
|
`(if (and (schelog:ref? ,e)
|
|
(schelog:unbound-ref? ,e))
|
|
(,fk 'fail) (schelog:deref* ,e)))))))
|
|
`(lambda (__fk)
|
|
((%= ,v ,(%is-help e '__fk)) __fk)))))
|
|
|
|
;defining arithmetic comparison operators
|
|
|
|
(define schelog:make-binary-arithmetic-relation
|
|
(lambda (f)
|
|
(lambda (x y)
|
|
(%is #t (f x y)))))
|
|
|
|
(define %=:= (schelog:make-binary-arithmetic-relation =))
|
|
(define %> (schelog:make-binary-arithmetic-relation >))
|
|
(define %>= (schelog:make-binary-arithmetic-relation >=))
|
|
(define %< (schelog:make-binary-arithmetic-relation <))
|
|
(define %<= (schelog:make-binary-arithmetic-relation <=))
|
|
(define %=/= (schelog:make-binary-arithmetic-relation
|
|
(lambda (m n) (not (= m n)))))
|
|
|
|
;type predicates
|
|
|
|
(define schelog:constant?
|
|
(lambda (x)
|
|
(cond ((schelog:ref? x)
|
|
(cond ((schelog:unbound-ref? x) #f)
|
|
((schelog:frozen-ref? x) #t)
|
|
(else (schelog:constant? (schelog:deref x)))))
|
|
((pair? x) #f)
|
|
((vector? x) #f)
|
|
(else #t))))
|
|
|
|
(define schelog:compound?
|
|
(lambda (x)
|
|
(cond ((schelog:ref? x) (cond ((schelog:unbound-ref? x) #f)
|
|
((schelog:frozen-ref? x) #f)
|
|
(else (schelog:compound? (schelog:deref x)))))
|
|
((pair? x) #t)
|
|
((vector? x) #t)
|
|
(else #f))))
|
|
|
|
(define %constant
|
|
(lambda (x)
|
|
(lambda (fk)
|
|
(if (schelog:constant? x) fk (fk 'fail)))))
|
|
|
|
(define %compound
|
|
(lambda (x)
|
|
(lambda (fk)
|
|
(if (schelog:compound? x) fk (fk 'fail)))))
|
|
|
|
;metalogical type predicates
|
|
|
|
(define schelog:var?
|
|
(lambda (x)
|
|
(cond ((schelog:ref? x)
|
|
(cond ((schelog:unbound-ref? x) #t)
|
|
((schelog:frozen-ref? x) #f)
|
|
(else (schelog:var? (schelog:deref x)))))
|
|
((pair? x) (or (schelog:var? (car x)) (schelog:var? (cdr x))))
|
|
((vector? x) (schelog:var? (vector->list x)))
|
|
(else #f))))
|
|
|
|
(define %var
|
|
(lambda (x)
|
|
(lambda (fk) (if (schelog:var? x) fk (fk 'fail)))))
|
|
|
|
(define %nonvar
|
|
(lambda (x)
|
|
(lambda (fk) (if (schelog:var? x) (fk 'fail) fk))))
|
|
|
|
; negation of unify
|
|
|
|
(define schelog:make-negation ;basically inlined cut-fail
|
|
(lambda (p)
|
|
(lambda args
|
|
(lambda (fk)
|
|
(if (call-with-current-continuation
|
|
(lambda (k)
|
|
((apply p args) (lambda (d) (k #f)))))
|
|
(fk 'fail)
|
|
fk)))))
|
|
|
|
(define %/=
|
|
(schelog:make-negation %=))
|
|
|
|
;identical
|
|
|
|
(define schelog:ident?
|
|
(lambda (x y)
|
|
(cond ((schelog:ref? x)
|
|
(cond ((schelog:unbound-ref? x)
|
|
(cond ((schelog:ref? y)
|
|
(cond ((schelog:unbound-ref? y) (eq? x y))
|
|
((schelog:frozen-ref? y) #f)
|
|
(else (schelog:ident? x (schelog:deref y)))))
|
|
(else #f)))
|
|
((schelog:frozen-ref? x)
|
|
(cond ((schelog:ref? y)
|
|
(cond ((schelog:unbound-ref? y) #f)
|
|
((schelog:frozen-ref? y) (eq? x y))
|
|
(else (schelog:ident? x (schelog:deref y)))))
|
|
(else #f)))
|
|
(else (schelog:ident? (schelog:deref x) y))))
|
|
((pair? x)
|
|
(cond ((schelog:ref? y)
|
|
(cond ((schelog:unbound-ref? y) #f)
|
|
((schelog:frozen-ref? y) #f)
|
|
(else (schelog:ident? x (schelog:deref y)))))
|
|
((pair? y)
|
|
(and (schelog:ident? (car x) (car y))
|
|
(schelog:ident? (cdr x) (cdr y))))
|
|
(else #f)))
|
|
((vector? x)
|
|
(cond ((schelog:ref? y)
|
|
(cond ((schelog:unbound-ref? y) #f)
|
|
((schelog:frozen-ref? y) #f)
|
|
(else (schelog:ident? x (schelog:deref y)))))
|
|
((vector? y)
|
|
(schelog:ident? (vector->list x)
|
|
(vector->list y)))
|
|
(else #f)))
|
|
(else
|
|
(cond ((schelog:ref? y)
|
|
(cond ((schelog:unbound-ref? y) #f)
|
|
((schelog:frozen-ref? y) #f)
|
|
(else (schelog:ident? x (schelog:deref y)))))
|
|
((pair? y) #f)
|
|
((vector? y) #f)
|
|
(else (eqv? x y)))))))
|
|
|
|
(define %==
|
|
(lambda (x y)
|
|
(lambda (fk) (if (schelog:ident? x y) fk (fk 'fail)))))
|
|
|
|
(define %/==
|
|
(lambda (x y)
|
|
(lambda (fk) (if (schelog:ident? x y) (fk 'fail) fk))))
|
|
|
|
;variables as objects
|
|
|
|
(define schelog:freeze
|
|
(lambda (s)
|
|
(let ((dict '()))
|
|
(let loop ((s s))
|
|
(cond ((schelog:ref? s)
|
|
(cond ((or (schelog:unbound-ref? s) (schelog:frozen-ref? s))
|
|
(let ((x (assq s dict)))
|
|
(if x (cdr x)
|
|
(let ((y (schelog:freeze-ref s)))
|
|
(set! dict (cons (cons s y) dict))
|
|
y))))
|
|
;((schelog:frozen-ref? s) s) ;?
|
|
(else (loop (schelog:deref s)))))
|
|
((pair? s) (cons (loop (car s)) (loop (cdr s))))
|
|
((vector? s)
|
|
(list->vector (map loop (vector->list s))))
|
|
(else s))))))
|
|
|
|
(define schelog:melt
|
|
(lambda (f)
|
|
(cond ((schelog:ref? f)
|
|
(cond ((schelog:unbound-ref? f) f)
|
|
((schelog:frozen-ref? f) (schelog:thaw-frozen-ref f))
|
|
(else (schelog:melt (schelog:deref f)))))
|
|
((pair? f)
|
|
(cons (schelog:melt (car f)) (schelog:melt (cdr f))))
|
|
((vector? f)
|
|
(list->vector (map schelog:melt (vector->list f))))
|
|
(else f))))
|
|
|
|
(define schelog:melt-new
|
|
(lambda (f)
|
|
(let ((dict '()))
|
|
(let loop ((f f))
|
|
(cond ((schelog:ref? f)
|
|
(cond ((schelog:unbound-ref? f) f)
|
|
((schelog:frozen-ref? f)
|
|
(let ((x (assq f dict)))
|
|
(if x (cdr x)
|
|
(let ((y (schelog:make-ref)))
|
|
(set! dict (cons (cons f y) dict))
|
|
y))))
|
|
(else (loop (schelog:deref f)))))
|
|
((pair? f) (cons (loop (car f)) (loop (cdr f))))
|
|
((vector? f)
|
|
(list->vector (map loop (vector->list f))))
|
|
(else f))))))
|
|
|
|
(define schelog:copy
|
|
(lambda (s)
|
|
(schelog:melt-new (schelog:freeze s))))
|
|
|
|
(define %freeze
|
|
(lambda (s f)
|
|
(lambda (fk)
|
|
((%= (schelog:freeze s) f) fk))))
|
|
|
|
(define %melt
|
|
(lambda (f s)
|
|
(lambda (fk)
|
|
((%= (schelog:melt f) s) fk))))
|
|
|
|
(define %melt-new
|
|
(lambda (f s)
|
|
(lambda (fk)
|
|
((%= (schelog:melt-new f) s) fk))))
|
|
|
|
(define %copy
|
|
(lambda (s c)
|
|
(lambda (fk)
|
|
((%= (schelog:copy s) c) fk))))
|
|
|
|
;negation as failure
|
|
|
|
(define %not
|
|
(lambda (g)
|
|
(lambda (fk)
|
|
(if (call-with-current-continuation
|
|
(lambda (k)
|
|
((schelog:deref* g) (lambda (d) (k #f)))))
|
|
(fk 'fail) fk))))
|
|
|
|
;assert, asserta
|
|
|
|
(define %empty-rel
|
|
(lambda args
|
|
%fail))
|
|
|
|
(define-syntax %assert
|
|
(syntax-rules ()
|
|
((%assert rel-name (v ...) ((a ...) subgoal ...) ...)
|
|
(set! rel-name
|
|
(let ((__old-rel rel-name)
|
|
(__new-addition (%rel (v ...) ((a ...) subgoal ...) ...)))
|
|
(lambda __fmls
|
|
(%or (apply __old-rel __fmls)
|
|
(apply __new-addition __fmls))))))))
|
|
|
|
(define-syntax %assert-a
|
|
(syntax-rules ()
|
|
((%assert-a rel-name (v ...) ((a ...) subgoal ...) ...)
|
|
(set! rel-name
|
|
(let ((__old-rel rel-name)
|
|
(__new-addition (%rel (v ...) ((a ...) subgoal ...) ...)))
|
|
(lambda __fmls
|
|
(%or (apply __new-addition __fmls)
|
|
(apply __old-rel __fmls))))))))
|
|
|
|
#;(define-macro %assert
|
|
(lambda (rel-name vv . cc)
|
|
`(set! ,rel-name
|
|
(let ((__old-rel ,rel-name)
|
|
(__new-addition (%rel ,vv ,@cc)))
|
|
(lambda __fmls
|
|
(%or (apply __old-rel __fmls)
|
|
(apply __new-addition __fmls)))))))
|
|
|
|
#;(define-macro %assert-a
|
|
(lambda (rel-name vv . cc)
|
|
`(set! ,rel-name
|
|
(let ((__old-rel ,rel-name)
|
|
(__new-addition (%rel ,vv ,@cc)))
|
|
(lambda __fmls
|
|
(%or (apply __new-addition __fmls)
|
|
(apply __old-rel __fmls)))))))
|
|
|
|
;set predicates
|
|
|
|
(define schelog:set-cons
|
|
(lambda (e s)
|
|
(if (member e s) s (cons e s))))
|
|
|
|
(define-syntax %free-vars
|
|
(syntax-rules ()
|
|
((%free-vars (v ...) g)
|
|
(cons 'schelog:goal-with-free-vars
|
|
(cons (list v ...) g)))))
|
|
|
|
#;(define-macro %free-vars
|
|
(lambda (vv g)
|
|
`(cons 'schelog:goal-with-free-vars
|
|
(cons (list ,@vv) ,g))))
|
|
|
|
(define schelog:goal-with-free-vars?
|
|
(lambda (x)
|
|
(and (pair? x) (eq? (car x) 'schelog:goal-with-free-vars))))
|
|
|
|
(define schelog:make-bag-of
|
|
(lambda (kons)
|
|
(lambda (lv goal bag)
|
|
(let ((fvv '()))
|
|
(when (schelog:goal-with-free-vars? goal)
|
|
(set! fvv (cadr goal))
|
|
(set! goal (cddr goal)))
|
|
(schelog:make-bag-of-aux kons fvv lv goal bag)))))
|
|
|
|
(define schelog:make-bag-of-aux
|
|
(lambda (kons fvv lv goal bag)
|
|
(lambda (fk)
|
|
(call-with-current-continuation
|
|
(lambda (sk)
|
|
(let ((lv2 (cons fvv lv)))
|
|
(let* ((acc '())
|
|
(fk-final
|
|
(lambda (d)
|
|
;;(set! acc (reverse! acc))
|
|
(sk ((schelog:separate-bags fvv bag acc) fk))))
|
|
(fk-retry (goal fk-final)))
|
|
(set! acc (kons (schelog:deref* lv2) acc))
|
|
(fk-retry 'retry))))))))
|
|
|
|
(define schelog:separate-bags
|
|
(lambda (fvv bag acc)
|
|
;;(format #t "Accum: ~s~%" acc)
|
|
(let ((bags (let loop ((acc acc)
|
|
(current-fvv #f) (current-bag '())
|
|
(bags '()))
|
|
(if (null? acc)
|
|
(cons (cons current-fvv current-bag) bags)
|
|
(let ((x (car acc)))
|
|
(let ((x-fvv (car x)) (x-lv (cdr x)))
|
|
(if (or (not current-fvv) (equal? x-fvv current-fvv))
|
|
(loop (cdr acc) x-fvv (cons x-lv current-bag) bags)
|
|
(loop (cdr acc) x-fvv (list x-lv)
|
|
(cons (cons current-fvv current-bag) bags)))))))))
|
|
;;(format #t "Bags: ~a~%" bags)
|
|
(if (null? bags) (%= bag '())
|
|
(let ((fvv-bag (cons fvv bag)))
|
|
(let loop ((bags bags))
|
|
(if (null? bags) %fail
|
|
(%or (%= fvv-bag (car bags))
|
|
(loop (cdr bags))))))))))
|
|
|
|
(define %bag-of (schelog:make-bag-of cons))
|
|
(define %set-of (schelog:make-bag-of schelog:set-cons))
|
|
|
|
;%bag-of-1, %set-of-1 hold if there's at least one solution
|
|
|
|
(define %bag-of-1
|
|
(lambda (x g b)
|
|
(%and (%bag-of x g b)
|
|
(%= b (cons (_) (_))))))
|
|
|
|
(define %set-of-1
|
|
(lambda (x g s)
|
|
(%and (%set-of x g s)
|
|
(%= s (cons (_) (_))))))
|
|
|
|
;user interface
|
|
|
|
;(%which (v ...) query) returns #f if query fails and instantiations
|
|
;of v ... if query succeeds. In the latter case, type (%more) to
|
|
;retry query for more instantiations.
|
|
|
|
(define schelog:*more-k* (box 'forward))
|
|
(define schelog:*more-fk* (box 'forward))
|
|
|
|
(define-syntax %which
|
|
(syntax-rules ()
|
|
((%which (v ...) g)
|
|
(%let (v ...)
|
|
(call-with-current-continuation
|
|
(lambda (__qk)
|
|
(set-box! schelog:*more-k* __qk)
|
|
(set-box! schelog:*more-fk*
|
|
((schelog:deref* g)
|
|
(lambda (d)
|
|
(set-box! schelog:*more-fk* #f)
|
|
((unbox schelog:*more-k*) #f))))
|
|
((unbox schelog:*more-k*)
|
|
(map (lambda (nam val) (list nam (schelog:deref* val)))
|
|
'(v ...)
|
|
(list v ...)))))))))
|
|
|
|
#;(define-macro %which
|
|
(lambda (vv g)
|
|
`(%let ,vv
|
|
(call-with-current-continuation
|
|
(lambda (__qk)
|
|
(set! schelog:*more-k* __qk)
|
|
(set! schelog:*more-fk*
|
|
((schelog:deref* ,g)
|
|
(lambda (d)
|
|
(set! schelog:*more-fk* #f)
|
|
(schelog:*more-k* #f))))
|
|
(schelog:*more-k*
|
|
(map (lambda (nam val) (list nam (schelog:deref* val)))
|
|
',vv
|
|
(list ,@vv))))))))
|
|
|
|
(define %more
|
|
(lambda ()
|
|
(call-with-current-continuation
|
|
(lambda (k)
|
|
(set-box! schelog:*more-k* k)
|
|
(if (unbox schelog:*more-fk*) ((unbox schelog:*more-fk*) 'more)
|
|
#f)))))
|
|
|
|
;end of embedding code. The following are
|
|
;some utilities, written in Schelog
|
|
|
|
(define %member
|
|
(lambda (x y)
|
|
(%let (xs z zs)
|
|
(%or
|
|
(%= y (cons x xs))
|
|
(%and (%= y (cons z zs))
|
|
(%member x zs))))))
|
|
|
|
(define %if-then-else
|
|
(lambda (p q r)
|
|
(%cut-delimiter
|
|
(%or
|
|
(%and p ! q)
|
|
r))))
|
|
|
|
;the above could also have been written in a more
|
|
;Prolog-like fashion, viz.
|
|
|
|
#;'(define %member
|
|
(%rel ! (x xs y ys)
|
|
((x (cons x xs)))
|
|
((x (cons y ys)) (%member x ys))))
|
|
|
|
#;'(define %if-then-else
|
|
(%rel ! (p q r)
|
|
((p q r) p ! q)
|
|
((p q r) r)))
|
|
|
|
(define %append
|
|
(%rel (x xs ys zs)
|
|
(('() ys ys))
|
|
(((cons x xs) ys (cons x zs))
|
|
(%append xs ys zs))))
|
|
|
|
(define %repeat
|
|
;;failure-driven loop
|
|
(%rel ()
|
|
(())
|
|
(() (%repeat))))
|
|
|
|
; deprecated names -- retained here for backward-compatibility
|
|
|
|
;; JBC, 2010-04-22 -- don't think backward compatibility counts any more. commenting
|
|
;; these out.
|
|
|
|
#;(define == %=)
|
|
#;(define %notunify %/=)
|
|
|
|
#;(define-macro %cut
|
|
(lambda e
|
|
`(%cur-delimiter ,@e)))
|
|
|
|
#;(define-macro rel
|
|
(lambda e
|
|
`(%rel ,@e)))
|
|
(define %eq %=:=)
|
|
(define %gt %>)
|
|
(define %ge %>=)
|
|
(define %lt %<)
|
|
(define %le %<=)
|
|
(define %ne %=/=)
|
|
(define %ident %==)
|
|
(define %notident %/==)
|
|
;(define-syntax %exists (syntax-rules () ((%exists vv g) g)))
|
|
|
|
#;(define-macro %exists (lambda (vv g) g))
|
|
|
|
#;(define-macro which
|
|
(lambda e
|
|
`(%which ,@e)))
|
|
(define more %more)
|
|
|
|
;end of file
|