#lang scheme/base
(require mzlib/match
"choice.ss"
"unify.ss"
"database.ss"
"enum.ss"
"fail.ss"
(for-syntax
scheme/base
"unify.ss"))
(define-syntax (rule-lambda stx)
(define (map-id stx var sym)
(let map ((stx stx))
(syntax-case stx ()
((a . d) #`(#,(map #'a) . #,(map #'d)))
(() #'())
(x (if (variable? (syntax->datum #'x))
(var #'x)
(sym #'x))))))
(define (id x) x)
(syntax-case stx ()
((_ (head . body))
#`(match-lambda
(#,(map-id #'head id (lambda (x) #'_)) `#,(map-id #'(head . body) (lambda (x) #`,#,x) id))
(else (fail))))))
(define-syntax-rule (make-rules rule ...)
(list->enum (list (rule-lambda rule) ...)))
(define (unify-rule store pattern rule-subst)
(match (rule-subst pattern) ((head . body)
(for/fold ((store (unify store pattern head))) ((bpat body))
(unify-pattern/db store bpat)))))
(define rules-db (make-parameter #f))
(define (unify-pattern/db store pattern)
(unify-rule store pattern (choice/enum (rules-db))))
(define (solve pattern)
(solutions
(query
(bindings
(unify-pattern/db
(add-free-variables (empty) pattern)
pattern)))))
(rules-db
(make-rules
((summer))
((green ?x)
(tree ?x)
(summer))
((tree pine))
((green algae))))