Type and contents, used by qeval
(section
), specify that a
special form is identified by the symbol in its car.
They are the same as the type-tag and contents procedures in
section
, except for the error message.
(define (type exp)
(if (pair? exp)
(car exp)
(error "Unknown expression TYPE" exp)))
(define (contents exp)
(if (pair? exp)
(cdr exp)
(error "Unknown expression CONTENTS" exp)))
The following procedures, used by query-driver-loop
(in section
), specify
that rules and assertions are added to the data base by expressions of
the form (assert! rule-or-assertion):
(define (assertion-to-be-added? exp) (eq? (type exp) 'assert!)) (define (add-assertion-body exp) (car (contents exp)))
Here are the syntax definitions for the
and,
or,
not, and lisp-value special forms
(section
):
(define (empty-conjunction? exps) (null? exps)) (define (first-conjunct exps) (car exps)) (define (rest-conjuncts exps) (cdr exps)) (define (empty-disjunction? exps) (null? exps)) (define (first-disjunct exps) (car exps)) (define (rest-disjuncts exps) (cdr exps)) (define (negated-query exps) (car exps)) (define (predicate exps) (car exps)) (define (args exps) (cdr exps))
The following three procedures define the syntax of rules:
(define (rule? statement)
(tagged-list? statement 'rule))
(define (conclusion rule) (cadr rule))
(define (rule-body rule)
(if (null? (cddr rule))
'(always-true)
(caddr rule)))
Query-driver-loop (section
)
calls query-syntax-process to
transform pattern variables in the expression, which have the form
?symbol, into the internal format (? symbol). That is to
say, a pattern such as (job ?x ?y) is actually represented
internally by the system as (job (? x) (? y)). This increases
the efficiency of query processing, since it means that the system can
check to see if an expression is a pattern variable by checking
whether the car of the expression is the symbol ?, rather
than having to extract characters from the symbol. The syntax
transformation is accomplished by the following
procedure:
(define (query-syntax-process exp)
(map-over-symbols expand-question-mark exp))
(define (map-over-symbols proc exp)
(cond ((pair? exp)
(cons (map-over-symbols proc (car exp))
(map-over-symbols proc (cdr exp))))
((symbol? exp) (proc exp))
(else exp)))
(define (expand-question-mark symbol)
(let ((chars (symbol->string symbol)))
(if (string=? (substring chars 0 1) "?")
(list '?
(string->symbol
(substring chars 1 (string-length chars))))
symbol)))
Once the variables are transformed in this way, the variables in a
pattern are lists starting with ?,
and the constant symbols (which need to be recognized for
data-base indexing, section
) are just the symbols.
(define (var? exp) (tagged-list? exp '?)) (define (constant-symbol? exp) (symbol? exp))
Unique variables are constructed during rule application
(in section
) by means of
the following procedures. The unique identifier for a rule
application is a number, which is incremented each time a rule is
applied.
(define rule-counter 0) (define (new-rule-application-id) (set! rule-counter (+ 1 rule-counter)) rule-counter) (define (make-new-variable var rule-application-id) (cons '? (cons rule-application-id (cdr var))))
When query-driver-loop instantiates the query to print the answer, it converts any unbound pattern variables back to the right form for printing, using
(define (contract-question-mark variable)
(string->symbol
(string-append "?"
(if (number? (cadr variable))
(string-append (symbol->string (caddr variable))
"-"
(number->string (cadr variable)))
(symbol->string (cadr variable))))))