moving to project folder
This commit is contained in:
89
picocalc/lisp/query.lsp
Normal file
89
picocalc/lisp/query.lsp
Normal file
@@ -0,0 +1,89 @@
|
||||
; uLisp Query Language - 9th April 2019
|
||||
; See http://www.ulisp.com/show?2I60
|
||||
;
|
||||
|
||||
; Database
|
||||
|
||||
(defvar *rules* nil)
|
||||
|
||||
(defun add (rule)
|
||||
(unless (assoc (car rule) *rules*) (push (list (car rule)) *rules*))
|
||||
(push (cdr rule) (cdr (assoc (car rule) *rules*)))
|
||||
t)
|
||||
|
||||
; Match
|
||||
|
||||
(defun match (x y &optional binds)
|
||||
(cond
|
||||
((eq x y) (if binds binds '((t))))
|
||||
((assoc x binds) (match (binding x binds) y binds))
|
||||
((assoc y binds) (match x (binding y binds) binds))
|
||||
((var? x) (cons (cons x y) binds))
|
||||
((var? y) (cons (cons y x) binds))
|
||||
(t
|
||||
(when (and (consp x) (consp y))
|
||||
(let ((m (match (car x) (car y) binds)))
|
||||
(when m (match (cdr x) (cdr y) m)))))))
|
||||
|
||||
(defun var? (x)
|
||||
(and (symbolp x) (eq (char (string x) 0) #\?)))
|
||||
|
||||
(defun binding (x binds)
|
||||
(let ((b (assoc x binds)))
|
||||
(when b
|
||||
(or (binding (cdr b) binds)
|
||||
(cdr b)))))
|
||||
|
||||
; Inference
|
||||
|
||||
(defun query (expr &optional binds)
|
||||
(case (car expr)
|
||||
(and (query-and (reverse (cdr expr)) binds))
|
||||
(or (query-or (cdr expr) binds))
|
||||
(not (query-not (second expr) binds))
|
||||
(test (query-test (second expr) binds))
|
||||
(t (lookup (car expr) (cdr expr) binds))))
|
||||
|
||||
(defun lookup (pred args &optional binds)
|
||||
(mapcan
|
||||
(lambda (x)
|
||||
(let ((m (match args x binds)))
|
||||
(when m (list m))))
|
||||
(cdr (assoc pred *rules*))))
|
||||
|
||||
(defun query-and (clauses binds)
|
||||
(if (null clauses)
|
||||
(list binds)
|
||||
(mapcan (lambda (b) (query (car clauses) b))
|
||||
(query-and (cdr clauses) binds))))
|
||||
|
||||
(defun query-or (clauses binds)
|
||||
(apply 'append (mapcar (lambda (c) (query c binds)) clauses)))
|
||||
|
||||
(defun query-not (clause binds)
|
||||
(unless (query clause binds)
|
||||
(list binds)))
|
||||
|
||||
(defun subs (lst binds)
|
||||
(cond
|
||||
((null lst) nil)
|
||||
((atom lst) (if (assoc lst binds) (cdr (assoc lst binds)) lst))
|
||||
(t (cons (subs (car lst) binds) (subs (cdr lst) binds)))))
|
||||
|
||||
(defun query-test (tst binds)
|
||||
(when (eval (subs tst binds))
|
||||
(list binds)))
|
||||
|
||||
(defun answer (expr output)
|
||||
(dolist (binds (query expr nil))
|
||||
(mapc (lambda (p) (princ p) (princ #\space)) (subs output binds))
|
||||
(terpri)))
|
||||
|
||||
(defun read-data ()
|
||||
(dolist (rules *data*)
|
||||
(let ((pred (first rules))
|
||||
(data (cdr rules)))
|
||||
(mapc (lambda (rule) (add (cons (first rule) (cons pred (cdr rule))))) data)))
|
||||
t)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user