(module inference-control mzscheme
(provide (all-defined))
(require "inference-environments.ss")
(require "bindings.ss")
(require "patterns.ss")
(require "facts.ss")
(require "rulesets.ss")
(require "matches.ss")
(require "assertions.ss")
(require (lib "list.ss" "srfi" "1"))
(define assert
(case-lambda
((fact reason)
(let ((assertion (make-assertion fact reason)))
(when (current-inference-trace)
(printf ">>> ~a~n" assertion))
(hash-table-put! (current-inference-assertion-index)
(fact-first fact)
(cons assertion
(hash-table-get
(current-inference-assertion-index)
(fact-first fact) (lambda () '()))))
(for-each
(lambda (match-node)
(match-node-assert match-node assertion))
(hash-table-get (current-inference-data-index)
(fact-first fact) (lambda () '())))
assertion))
((fact)
(assert fact (current-inference-rule))
)))
(define (retract assertion)
(when (current-inference-trace)
(printf "<<< ~a~n" assertion))
(hash-table-put! (current-inference-assertion-index)
(fact-first (assertion-fact assertion))
(delete! assertion
(hash-table-get
(current-inference-assertion-index)
(fact-first (assertion-fact assertion)))))
(for-each
(lambda (match-node)
(match-node-retract match-node assertion))
(hash-table-get (current-inference-data-index)
(fact-first (assertion-fact assertion)))))
(define replace
(case-lambda
((assertion fact reason)
(retract assertion)
(set-assertion-fact! assertion fact)
(set-assertion-reason! assertion reason)
(when (current-inference-trace)
(printf ">>> ~a~n" assertion))
(hash-table-put! (current-inference-assertion-index)
(fact-first fact)
(cons assertion
(hash-table-get
(current-inference-assertion-index)
(fact-first fact) (lambda () '()))))
(for-each
(lambda (match-node)
(match-node-assert match-node assertion))
(hash-table-get (current-inference-data-index)
(fact-first fact) (lambda () '())))
assertion)
((assertion fact)
(replace assertion fact (current-inference-rule))
)))
(define (check fact)
(let/ec return
(let ((assertion (make-assertion fact (current-inference-rule))))
(when (current-inference-trace)
(printf "??? ~a~n" assertion))
(for-each
(lambda (match-node)
(let ((match (match-node-check match-node assertion return)))
(when (not (null? match))
(return match))))
(hash-table-get (current-inference-goal-index)
(fact-first fact) (lambda () '())))
'())))
(define (query pattern)
(let ((matches '()))
(for-each
(lambda (assertion)
(let* ((fact (assertion-fact assertion))
(bindings (pattern-unify fact pattern '())))
(if bindings
(set! matches
(cons (cons assertion bindings)
matches)))))
(hash-table-get (current-inference-assertion-index)
(pattern-first pattern) (lambda () '())))
matches))
(define (assume fact)
(let ((saved (copy-inference-environment (current-inference-environment))))
(assert fact)
(let ((result (start-inference)))
(if result
(current-inference-exit (inference-environment-exit saved))
(current-inference-environment saved))
result)))
(define-struct node
(successors
matches)
(make-inspector))
(define-struct (match-node node)
(assertion-variable
pattern
match-constraint-variables
match-constraints
match-constraint-predicate
n)
(make-inspector))
(define-struct (join-node node)
(left
right
join-constraint-variables
join-constraints
join-constraint-predicate
existential?
match-counts)
(make-inspector))
(define-struct (rule-node node)
(rule
join
action)
(make-inspector))
(define (get-match-node successors
matches
assertion-variable
pattern
match-constraint-variables
match-constraints
match-constraint-predicate
n)
(let/ec return
(for-each
(lambda (match-node)
(when (and (eq? assertion-variable
(match-node-assertion-variable match-node))
(equal? pattern
(match-node-pattern match-node))
(equal? match-constraint-variables
(match-node-match-constraint-variables match-node))
(equal? match-constraints
(match-node-match-constraints match-node)))
(return match-node)))
(hash-table-get (current-inference-data-index)
(pattern-first pattern)
(lambda () '())))
(let ((match-node
(make-match-node
successors matches assertion-variable pattern match-constraint-variables match-constraints match-constraint-predicate n))) (hash-table-put! (current-inference-data-index)
(pattern-first pattern)
(cons match-node
(hash-table-get (current-inference-data-index)
(pattern-first pattern)
(lambda () '()))))
match-node)))
(define (get-join-node successors
matches
left
right
join-constraint-variables
join-constraints
join-constraint-predicate
existential?
match-counts)
(let/ec return
(for-each
(lambda (join-node)
(when (and (eq? left
(join-node-left join-node))
(eq? right
(join-node-right join-node))
(equal? join-constraint-variables
(join-node-join-constraint-variables join-node))
(equal? join-constraints
(join-node-join-constraints join-node))
(eq? existential?
(join-node-existential? join-node)))
(return join-node)))
(node-successors left))
(make-join-node
successors
matches
left
right
join-constraint-variables
join-constraints
join-constraint-predicate
existential?
match-counts)))
(define (link-nodes predecessor successor)
(when (not (memq successor (node-successors predecessor)))
(set-node-successors!
predecessor
(cons successor (node-successors predecessor)))))
(define (add-match-to-node-matches match node)
(when (node-matches node)
(set-node-matches!
node (cons match (node-matches node)))))
(define (remove-match-from-node-matches match node)
(let/cc exit
(let loop ((previous #f)
(matches (node-matches node)))
(when (not (null? matches))
(when (eq? match (car matches))
(if previous
(set-cdr! previous (cdr matches))
(set-node-matches! node (cdr matches)))
(exit))
(loop matches (cdr matches))))))
(define (get-node-matches node bindings)
(let ((matches (node-matches node)))
(if matches
matches
(if (match-node? node)
(check (pattern-substitute
(match-node-pattern node) bindings))
#f))))
(define (activate ruleset)
(let ((initial-join-node
(make-join-node
'() '((())) #f #f '() '() #f #f '()))) (for-each
(lambda (rule)
(activate-rule rule initial-join-node))
(ruleset-rules ruleset)))
(fix-goal-matches))
(define (activate-rule rule initial-node)
(let ((match-node #f)
(join-node #f)
(rule-node #f)
(previous-node initial-node)
(previous-variable-list '()))
(when (not (null? (rule-goals rule)))
(let ((goal-pattern (car (rule-goals rule))))
(set! previous-node
(make-match-node
'() #f #f goal-pattern '() '() #f 0 ))
(hash-table-put!
(current-inference-goal-index)
(pattern-first goal-pattern)
(cons previous-node
(hash-table-get
(current-inference-goal-index)
(pattern-first goal-pattern)
(lambda () '()))))
(set! previous-variable-list
(pattern-variables goal-pattern))))
(for-each
(lambda (clause)
(let ((existential? #f)
(assertion-variable #f)
(pattern #f)
(variable-list '()))
(cond ((and (pair? clause)
(variable? (car clause)))
(set! assertion-variable (car clause))
(set! pattern (caddr clause)))
((and (pair? clause)
(memq (car clause) '(no notany any notall all)))
(set! existential? (car clause))
(set! pattern (cadr clause)))
(else
(set! pattern clause)))
(set! variable-list
(merge-variable-lists
previous-variable-list
(if assertion-variable
(cons assertion-variable (pattern-variables pattern))
(pattern-variables pattern))))
(let ((match-constraints
(pattern-match-constraints
pattern (pattern-variables pattern))))
(set! match-node
(get-match-node
'() '() assertion-variable (pattern-base-pattern pattern) (if assertion-variable (cons assertion-variable (pattern-variables pattern))
(pattern-variables pattern))
match-constraints (if (null? match-constraints) #f
(eval
`(lambda ,(if assertion-variable
(cons assertion-variable
(pattern-variables pattern))
(pattern-variables pattern))
(and ,@match-constraints))))
0))) (let ((join-constraints
(pattern-join-constraints
pattern (pattern-variables pattern))))
(set! join-node
(get-join-node
'() (if (null? (rule-goals rule))
(if (or (memq existential? '(no notany))
(eq? existential? 'all))
(node-matches previous-node)
'())
#f) previous-node match-node variable-list join-constraints (if (null? join-constraints) #f
(eval `(lambda ,variable-list
(and ,@join-constraints))))
existential? '()))) (link-nodes match-node join-node)
(link-nodes previous-node join-node)
(set! previous-node join-node)
(if (not existential?)
(set! previous-variable-list variable-list))))
(rule-preconditions rule))
(set! rule-node
(make-rule-node
'() (if (null? (rule-goals rule))
(node-matches previous-node)
#f) rule previous-node (if (not (rule-actions rule))
#f
(eval #`(lambda #,previous-variable-list
(and #,@(rule-actions rule)))))
))
(link-nodes previous-node rule-node)
(current-inference-rule-nodes
(append! (current-inference-rule-nodes)
(list rule-node)))
)
(void))
(define (fix-goal-matches)
(hash-table-for-each (current-inference-data-index)
(lambda (key value)
(when (hash-table-get (current-inference-goal-index) key
(lambda () #f))
(for-each
(lambda (match-node)
(set-node-matches! match-node #f))
value)
(hash-table-remove! (current-inference-data-index) key)))))
(define (merge-variable-lists list1 list2)
(cond ((null? list2)
list1)
((memq (car list2) list1)
(merge-variable-lists list1 (cdr list2)))
(else
(merge-variable-lists
(append list1 (list (car list2))) (cdr list2)))))
(define (match-node-assert match-node assertion)
(set-match-node-n! match-node (+ (match-node-n match-node) 1))
(let ((bindings (pattern-unify
(assertion-fact assertion)
(match-node-pattern match-node) '())))
(when bindings
(when (match-node-assertion-variable match-node)
(set! bindings
(cons
(cons (match-node-assertion-variable match-node)
assertion)
bindings)))
(when (and (match-node-match-constraint-predicate match-node)
(not (apply (match-node-match-constraint-predicate match-node)
(bindings-data bindings))))
(set! bindings #f)))
(if bindings
(let ((match (cons (list assertion) bindings)))
(add-match-to-node-matches match match-node)
(for-each
(lambda (successor)
(propagate-match-from-match-node match successor))
(node-successors match-node)))
(for-each
(lambda (successor)
(propagate-nonmatch-from-match-node successor))
(node-successors match-node)))))
(define (match-node-retract match-node assertion)
(set-match-node-n! match-node (- (match-node-n match-node) 1))
(let/cc exit
(let loop ((previous #f)
(matches (node-matches match-node)))
(when (not (null? matches))
(let ((match (car matches)))
(when (eq? assertion (caar match))
(if previous
(set-cdr! previous (cdr matches))
(set-node-matches! match-node (cdr matches)))
(for-each
(lambda (successor)
(unpropagate-match-from-match-node match successor))
(node-successors match-node))
(exit)))
(loop matches (cdr matches))))
(for-each
(lambda (successor)
(unpropagate-nonmatch-from-match-node successor))
(node-successors match-node))))
(define (match-node-check match-node assertion continuation)
(let/ec exit
(let ((bindings (pattern-unify
(assertion-fact assertion)
(match-node-pattern match-node) '())))
(when bindings
(if (match-node-assertion-variable match-node)
(set! bindings
(cons
(cons (match-node-assertion-variable match-node)
assertion)
bindings)))
(when (and (match-node-match-constraint-predicate match-node)
(not (apply (match-node-match-constraint-predicate match-node)
(bindings-data bindings))))
(exit #f))
(let ((match (cons (list assertion) bindings)))
(add-match-to-node-matches match match-node)
(for-each
(lambda (successor)
(propagate-match-from-join-node match successor continuation))
(node-successors match-node)))))
'()))
(define (propagate-match-from-match-node match join-node)
(when (node-matches join-node)
(for-each
(lambda (left-match)
(let ((joined-match (join left-match match join-node)))
(if (join-node-existential? join-node)
(let* ((count-association
(assq left-match (join-node-match-counts join-node)))
(count (if count-association
(cdr count-association)
0)))
(when joined-match
(set! count (+ count 1))
(if count-association
(set-cdr! count-association count)
(set-join-node-match-counts!
join-node (cons (cons left-match count)
(join-node-match-counts join-node)))))
(case (join-node-existential? join-node)
((no notany)
(when (and joined-match
(= count 1)) (unpropagate-match-to-successors left-match join-node)))
((any)
(when (and joined-match
(= count 1)) (propagate-match-to-successors left-match join-node #f)))
((notall)
(let ((n (match-node-n (join-node-right join-node))))
(when (and (not joined-match)
(= count (- n 1)))
(propagate-match-to-successors left-match join-node #f))))
((all)
(let ((n (match-node-n (join-node-right join-node))))
(when (and (not joined-match)
(= count (- n 1)))
(unpropagate-match-to-successors left-match join-node #f))))))
(when joined-match
(propagate-match-to-successors joined-match join-node #f)))))
(get-node-matches (join-node-left join-node) (car match)))))
(define (propagate-nonmatch-from-match-node join-node)
(when (node-matches join-node)
(for-each
(lambda (left-match)
(when (join-node-existential? join-node)
(let* ((count-association
(assq left-match (join-node-match-counts join-node)))
(count (if count-association
(cdr count-association)
0)))
(case (join-node-existential? join-node)
((notall)
(let ((n (match-node-n (join-node-right join-node))))
(when (= count (- n 1))
(propagate-match-to-successors left-match join-node #f))))
((all)
(let ((n (match-node-n (join-node-right join-node))))
(when (= count (- n 1))
(unpropagate-match-to-successors left-match join-node))))))))
(get-node-matches (join-node-left join-node) '()))))
(define (propagate-match-from-join-node match join-node continuation)
(if (join-node-existential? join-node)
(let ((count 0))
(for-each
(lambda (right-match)
(let ((joined-match (join match right-match join-node)))
(when joined-match
(set! count (+ count 1)))))
(node-matches (join-node-right join-node)))
(set-join-node-match-counts!
join-node (cons (cons match count)
(join-node-match-counts join-node)))
(case (join-node-existential? join-node)
((no notany)
(when (= count 0)
(propagate-match-to-successors match join-node continuation)))
((any)
(when (> count 1)
(propagate-match-to-successors match join-node continuation)))
((notall)
(let ((n (match-node-n (join-node-right join-node))))
(when (< count n)
(propagate-match-to-successors match join-node continuation))))
((all)
(let ((n (match-node-n (join-node-right join-node))))
(when (= count n)
(propagate-match-to-successors match join-node continuation))))))
(for-each
(lambda (right-match)
(let ((joined-match (join match right-match join-node)))
(when joined-match
(propagate-match-to-successors joined-match join-node continuation))))
(get-node-matches (join-node-right join-node) (cdr match)))))
(define (propagate-match-to-successors match join-node continuation)
(add-match-to-node-matches match join-node)
(for-each
(lambda (successor)
(if (join-node? successor)
(propagate-match-from-join-node match successor continuation)
(propagate-match-to-rule match successor continuation)))
(node-successors join-node)))
(define (propagate-match-to-rule match rule-node continuation)
(if (node-matches rule-node)
(let ((rule-instance
(make-rule-instance rule-node match 0)))
(agenda-add! rule-instance))
(begin
(when (current-inference-trace)
(printf "<== ~a: ~a~n"
(rule-node-rule rule-node)
(cdr match)))
(when (rule-node-action rule-node)
(current-inference-rule (rule-node-rule))
(apply (rule-node-action rule-node)
(bindings-data match))
(current-inference-rule #f)
(current-inference-rules-fired
(+ (current-inference-rules-fired) 1))
)
(continuation (list (cons (list (caar match)) (cdr match)))))))
(define (unpropagate-match-from-match-node match join-node)
(if (join-node-existential? join-node)
(for-each
(lambda (left-match)
(let* ((count-association
(assq left-match (join-node-match-counts join-node)))
(count (cdr count-association))
(joined-match (join left-match match join-node)))
(when joined-match
(set! count (- count 1))
(set-cdr! count-association count))
(case (join-node-existential? join-node)
((no notany)
(when (and joined-match
(= count 0)) (propagate-match-to-successors left-match join-node #f)))
((any)
(when (and join-node
(= count 0)) (unpropagate-match-to-successors left-match join-node)))
((notall)
(let ((n (match-node-n (join-node-right join-node))))
(when (and (not joined-match)
(= count n))
(unpropagate-match-to-successors left-match join-node))))
((all)
(let ((n (match-node-n (join-node-right join-node))))
(when (and (not joined-match)
(= count n))
(propagate-match-to-successors left-match join-node #f)))))))
(node-matches (join-node-left join-node)))
(let ((assertion (caar match)))
(for-each
(lambda (match)
(when (eq? assertion
(last (car match)))
(unpropagate-match-to-successors match join-node)))
(node-matches join-node)))))
(define (unpropagate-nonmatch-from-match-node join-node)
(when (join-node-existential? join-node)
(for-each
(lambda (left-match)
(let* ((count-association
(assq left-match (join-node-match-counts join-node)))
(count (if count-association
(cdr count-association)
0)))
(case (join-node-existential? join-node)
((notall)
(let ((n (match-node-n (join-node-right join-node))))
(when (= count n)
(unpropagate-match-to-successors left-match join-node))))
((all)
(let ((n (match-node-n (join-node-right join-node))))
(when (= count n)
(propagate-match-to-successors left-match join-node #f)))))))
(node-matches (join-node-left join-node)))))
(define (unpropagate-match-from-join-node match join-node)
(let/ec exit
(let loop ((previous #f)
(alist (join-node-match-counts join-node)))
(when (not (null? alist))
(let ((association (car alist)))
(when (eq? match (car association))
(if previous
(set-cdr! previous (cdr alist))
(set-join-node-match-counts! join-node (cdr alist)))
(exit)))
(loop alist (cdr alist)))))
(for-each
(lambda (node-match)
(when (match-subset? match node-match)
(unpropagate-match-to-successors node-match join-node)))
(node-matches join-node)))
(define (unpropagate-match-to-successors match join-node)
(remove-match-from-node-matches match join-node)
(for-each
(lambda (successor)
(if (join-node? successor)
(unpropagate-match-from-join-node match successor)
(unpropagate-match-to-rule match successor)))
(node-successors join-node)))
(define (unpropagate-match-to-rule match rule-node)
(agenda-remove! rule-node match))
(define (join left-match right-match join-node)
(let ((left-assertions (car left-match))
(left-bindings (cdr left-match))
(right-assertions (car right-match))
(right-bindings (cdr right-match)))
(let/cc return
(for-each
(lambda (right-binding)
(if (assq (car right-binding) left-bindings)
(if (not (equal? (cdr right-binding)
(cdr (assq (car right-binding) left-bindings))))
(return #f))))
right-bindings)
(let ((bindings left-bindings))
(for-each
(lambda (right-binding)
(if (not (assq (car right-binding) left-bindings))
(set! bindings (append bindings (list right-binding)))))
right-bindings)
(if (and (join-node-join-constraint-predicate join-node)
(not (apply (join-node-join-constraint-predicate join-node)
(bindings-data bindings))))
(return #f))
(cons (append left-assertions right-assertions) bindings)))))
(define-struct rule-instance (rule-node match random))
(define (rule-instance-apply rule-instance)
(let* ((rule-node (rule-instance-rule-node rule-instance))
(rule (rule-node-rule rule-node))
(match (rule-instance-match rule-instance))
(arguments (bindings-data (cdr match))))
(when (current-inference-trace)
(printf "==> ~a: ~a~n"
rule (cdr match)))
(current-inference-rule rule)
(apply (rule-node-action rule-node) arguments)
(current-inference-rule #f)
(current-inference-rules-fired
(+ (current-inference-rules-fired) 1))
))
(define (agenda-add! rule-instance)
(let* ((rule-node (rule-instance-rule-node rule-instance))
(rule (rule-node-rule rule-node))
(priority (rule-priority rule)))
(when (eq? (current-inference-strategy) 'random)
(set-rule-instance-random! rule-instance (random)))
(let ((agenda-tail (current-inference-agenda))
(previous #f))
(let loop ()
(when (not (null? agenda-tail))
(let* ((item (car agenda-tail))
(item-rule-node (rule-instance-rule-node item))
(item-rule (rule-node-rule item-rule-node))
(item-priority (rule-priority item-rule)))
(cond ((> item-priority priority)
(set! previous agenda-tail)
(set! agenda-tail (cdr agenda-tail))
(loop))
((and (= item-priority priority)
(or (eq? (current-inference-strategy) 'breadth)
(and (eq? (current-inference-strategy) 'order)
(< (rule-order item-rule)
(rule-order rule)))
(and (eq? (current-inference-strategy) 'simplicity)
(< (rule-specificity item-rule)
(rule-specificity rule)))
(and (eq? (current-inference-strategy) 'complexity)
(> (rule-specificity item-rule)
(rule-specificity rule)))
(and (eq? (current-inference-strategy) 'random)
(< (rule-instance-random item)
(rule-instance-random rule-instance)))))
(set! previous agenda-tail)
(set! agenda-tail (cdr agenda-tail))
(loop))
(else
(void))))))
(if previous
(set-cdr! previous (cons rule-instance agenda-tail))
(current-inference-agenda (cons rule-instance agenda-tail))))))
(define (agenda-remove! rule-node match)
(let loop ((previous #f)
(agenda-tail (current-inference-agenda)))
(when (not (null? agenda-tail))
(let ((item (car agenda-tail)))
(if (and (eq? rule-node (rule-instance-rule-node item))
(eq? match (rule-instance-match item)))
(if previous
(set-cdr! previous (cdr agenda-tail))
(current-inference-agenda (cdr agenda-tail)))
(loop agenda-tail (cdr agenda-tail)))))))
(define (import pattern)
(when (not (current-inference-parent))
(error 'import
"Current inference environment is not a child environment"))
(let ((matches '()))
(with-inference-environment (current-inference-parent)
(set! matches (query pattern)))
(for-each
(lambda (match)
(assert (assertion-fact (car match))))
matches)))
(define (export pattern)
(when (not (current-inference-parent))
(error 'import
"Current inference environment is not a child environment"))
(let ((matches (query pattern)))
(with-inference-environment (current-inference-parent)
(for-each
(lambda (match)
(assert (assertion-fact (car match))))
matches))))
(define (copy-inference-environment source)
(let ((target (make-inference-environment))
(hash-table (make-hash-table)))
(for-each
(lambda (rule-node)
(copy-rule-node rule-node hash-table))
(inference-environment-rule-nodes source))
(let ((target-data-index (inference-environment-data-index target)))
(hash-table-for-each
(inference-environment-data-index source)
(lambda (key value)
(hash-table-put!
target-data-index
key (copy-match-node-list value)))))
(let ((target-goal-index (inference-environment-goal-index target)))
(hash-table-for-each
(inference-environment-goal-index source)
(lambda (key value)
(hash-table-put!
target-goal-index
key (copy-match-node-list value)))))
(set-inference-environment-exit!
target (inference-environment-exit source))
(set-inference-environment-next-assertion-id!
target (inference-environment-next-assertion-id source))
(let ((target-assertion-index
(inference-environment-assertion-index target)))
(hash-table-for-each
(inference-environment-assertion-index source)
(lambda (key value)
(hash-table-put!
target-assertion-index key (list-copy value)))))
(set-inference-environment-agenda!
target (list-copy (inference-environment-agenda source)))
(set-inference-environment-rule!
target (inference-environment-rule source))
(set-inference-environment-strategy!
target (inference-environment-strategy source))
(set-inference-environment-parent!
target (inference-environment-parent source))
target))
(define (copy-node node hash-table)
(cond ((match-node? node)
(copy-match-node node hash-table))
((join-node? node)
(copy-join-node node hash-table))
((rule-node? node)
(copy-rule-node node hash-table))
(else
(error 'copy-node
"~a is not a type of rule network node" node))))
(define (copy-match-node match-node hash-table)
(let ((copied-node (hash-table-get hash-table match-node #f)))
(unless copied-node
(set! copied-node
(make-match-node
'()
(if (node-matches match-node)
(list-copy (node-matches match-node))
#f)
(match-node-assertion-variable match-node)
(match-node-pattern match-node)
(match-node-match-constraint-variables match-node)
(match-node-match-constraints match-node)
(match-node-match-constraint-predicate match-node)
(match-node-n match-node)))
(hash-table-put! hash-table match-node copied-node))
copied-node))
(define (copy-join-node join-node hash-table)
(let ((copied-node (hash-table-get hash-table join-node #f)))
(unless copied-node
(set! copied-node
(make-join-node
'()
(if (node-matches join-node)
(list-copy (node-matches join-node))
#f)
(copy-node (join-node-left join-node) hash-table)
(copy-node (join-node-right join-node) hash-table)
(join-node-join-constraint-variables join-node)
(join-node-join-constraints join-node)
(join-node-join-constraint-predicate join-node)
(join-node-existential? join-node)
(alist-copy (join-node-match-counts join-node))))
(link-nodes (join-node-left copied-node) copied-node)
(link-nodes (join-node-right copied-node) copied-node)
(hash-table-put! hash-table join-node copied-node))
copied-node))
(define (copy-rule-node rule-node hash-table)
(let ((copied-node (hash-table-get hash-table rule-node #f)))
(unless copied-node
(set! copied-node
(make-rule-node
'()
(if (node-matches rule-node)
(list-copy (node-matches rule-node))
#f)
(rule-node-rule rule-node)
(copy-node (rule-node-join rule-node))
(rule-node-action rule-node)))
(link-nodes (rule-node-join rule-node) copied-node)
(hash-table-put! hash-table rule-node copied-node))
copied-node))
(define (copy-match-node-list match-node-list hash-table)
match-node-list)
(define (start-inference)
(assert '(start))
(let/cc exit
(current-inference-exit exit)
(let loop ()
(let ((agenda (current-inference-agenda)))
(if (not (null? agenda))
(let ((rule-instance (car agenda)))
(current-inference-agenda (cdr agenda))
(rule-instance-apply rule-instance)
(loop))
#f)))))
(define stop-inference
(case-lambda
((return-value)
((current-inference-exit) return-value))
(()
((current-inference-exit)))))
(define (succeed)
(stop-inference #t))
(define (fail)
(stop-inference #:fail))
(define (print-rule-network)
(for-each
(lambda (rule-node)
(printf "----------~n")
(printf "Rule: ~a~n~n" (rule-name (rule-node-rule rule-node)))
(print-join-node (rule-node-join rule-node)))
(current-inference-rule-nodes)))
(define (print-join-node join-node)
(when (join-node-left join-node)
(if (join-node? (join-node-left join-node))
(print-join-node (join-node-left join-node))
(print-match-node (join-node-left join-node))))
(when (join-node-right join-node)
(print-match-node (join-node-right join-node)))
(printf "join node: existential? = ~a~n" (join-node-existential? join-node))
(printf "join-node: match-counts = ~a~n" (join-node-match-counts join-node))
(printf "join node: matches = ~a~n~n" (node-matches join-node)))
(define (print-match-node match-node)
(printf "match-node: pattern = ~a~n" (match-node-pattern match-node))
(printf "match-node: matches = ~a~n~n" (node-matches match-node)))
)