home *** CD-ROM | disk | FTP | other *** search
- Basic Database Functions.
-
-
- (defun clear-db ()
- (setq *db* (make-hash-table)))
-
- (clear-db)
-
- (defmacro entries (x)
- `(gethash ,x *db*))
-
- (defmacro fact (pred &rest args)
- `(fact+ ',pred ',args))
-
- (defun fact+ (pred args)
- (push args (entries pred))
- args)
-
- (defun world ()
- (maphash #'(lambda (key value)
- (pprint (list key value)))
- *db*))
-
-
- --------------------------------------
- Functions for Answering Queries.
-
-
- (defun lookup (pred args)
- (let ((result nil))
- (dolist (e (entries pred))
- (let ((vals (pmatch e args '((null binds)))))
- (if vals (push vals result))))
- (reverse result)))
-
- (defun var? (x)
- (string= (subseq (princ-to-string x) 0 1) '?))
- (defun pmatch (obj pat binds)
- (cond ((null pat) binds)
- ((not (var? (car pat)))
- (and (equal (car pat) (car obj))
- (pmatch (cdr obj) (cdr pat) binds)))
- ((assoc (car pat) binds)
- (and (eq (car obj)
- (cadr (assoc (car pat) binds)))
- (pmatch (cdr obj) (cdr pat) binds)))
- (t (pmatch (cdr obj)
- (cdr pat)
- (cons (list (car pat) (car obj))
- binds)))))
-
-
-
- (defmacro with-answer (query &body body)
- (let ((vars (vars-in query)))
- `(mapcar #'(lambda (binds)
- (apply #'(lambda ,vars ,@body)
- binds)) ,(compile-query query vars))))
-
- (defun vars-in (expr)
- (labels ((rec-vars (expr)
- (cond ((null expr) nil)
- ((consp expr)
- (mapcan #'rec-vars expr))
- (t (if (var? expr) (list expr))))))
- (remove-duplicates (rec-vars expr))))
-
- ---------------------------------------------------
-
-
- Query Compiler.
-
-
- (defun compile-query (expr vars)
- `(mapcan #'(lambda (binds)
- ,(query-code expr vars))
- '(,vars)))
-
- (defun query-code (expr vars)
- (case (car expr)
- (and (compile-and (reverse (cdr expr)) vars))
- (or (compile-or (cdr expr) vars))
- (not (compile-not (cadr expr) vars))
- (lisp (compile-lisp (cadr expr) vars))
- (t (compile-simple (car expr) (cdr expr) vars))))
-
- (defun compile-and (clauses vars)
- (if (singleton clauses)
- (query-code (car clauses) vars)
- `(mapcan #'(lambda (binds)
- ,(query-code (car clauses) vars))
- ,(compile-and (cdr clauses) vars))))
-
- (defun compile-or (clauses vars)
- `(delete-duplicates
- (append ,@(mapcar #'(lambda (c)
- (query-code c vars))
- clauses))
- :test #'equal))
-
- (defun compile-not (clause vars)
- `(if ,(query-code clause vars)
- nil
- (list binds)))
-
-
- (defun compile-lisp (expr vars)
- `(apply #'(lambda ,vars
- (if ,expr
- (list binds)))
- binds))
-
- (defun compile-simple (pred args vars)
- `(apply #'(lambda ,vars
- (mapcar #'(lambda (result)
- (list ,@(mapcar #'(lambda (v)
- `(or (cadr (assoc ',v result))
- ,v))
- vars)))
- (lookup ',pred (list ,@args))))
- binds))
-
- ,v))
-