private/rulesets.ss
;;; PLT Scheme Inference Collection
;;; rulesets.ss
;;; Copyright (c) 2006 M. Douglas Williams
;;;
;;; This library is free software; you can redistribute it and/or
;;; modify it under the terms of the GNU Lesser General Public
;;; License as published by the Free Software Foundation; either
;;; version 2.1 of the License, or (at your option) any later version.
;;;
;;; This library is distributed in the hope that it will be useful,
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;;; Lesser General Public License for more details.
;;;
;;; You should have received a copy of the GNU Lesser General Public
;;; License along with this library; if not, write to the Free
;;; Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
;;; 02111-1307 USA.
;;;

(module rulesets mzscheme
  
  (provide (all-defined))
  
  (require "patterns.ss")
  (require "argument-lists.ss")
  
  ;; Ruleset and Rule Definition
  
  ;; ruleset structure
  ;;   name  - a symbol naming the ruleset
  ;;   rules - a list of the rules in the ruleset
  (define-struct ruleset
    (name rules namespace)
    (make-inspector))
  
  ;; rule structure
  ;;   name          - a symbol naming the rule
  ;;   ruleset       - the ruleset to which the rule belongs
  ;;   goals         - a list of goals
  ;;   preconditions - a list of preconditions
  ;;   actions       - a list of rule actions
  (define-struct rule
    (name ruleset goals preconditions actions)
    (make-inspector))
  
  ;; add-rule: symbol x ruleset x list x procedure -> void
  ;; Adds a rule to a ruleset.  Will be called by the define-rule
  ;; macro in the inference collection.
  (define (add-rule name ruleset goals preconditions actions)
    (let ((rule (make-rule name ruleset goals preconditions actions)))
      (set-ruleset-rules! ruleset
                          (append! (ruleset-rules ruleset)
                                   (list rule)))))
  
  (define-syntax define-ruleset
    (syntax-rules ()
      ((define-ruleset name)
       (define name
         (make-ruleset ',name 
                       '()
                       (current-namespace))))))
  
  (define-syntax define-rule
    (syntax-rules (<== ==>)
      (;; special case - goal with no data or actions
       (define-rule (name ruleset)
         item)
       (add-rule 'name
                 ruleset
                 '(item)
                 '()
                 #f))
      (;; standard initial call - start gathering goals or data
       (define-rule (name ruleset)
         item-1 item-2 ...)
       (define-rule
         "gather goals or data"
         (name ruleset)
         (item-1)
         item-2 ...))
      (;; only found goals (unusual case)
       (define-rule
         "gather goals or data"
         (name ruleset)
         (goal ...))
       (add-rule 'name
                 ruleset
                 '(goal ...)
                 '()
                 #f))
      (;; found end of goals and a single precondition
       (define-rule
         "gather goals or data"
         (name ruleset)
         (goal ...)
         <== item)
       (add-rule 'name
                 ruleset
                 '(goal ...)
                 '(item)
                 #f))
      (;; found end of goals - start gathering data or actions
       (define-rule
         "gather goals or data"
         (name ruleset)
         (goal ...)
         <== item-1 item-2 ...)
       (define-rule
         "gather data or actions"
         (name ruleset)
         (goal ...)
         (item-1)
         item-2 ...))
      (;; found data (and no goals)
       (define-rule
         "gather goals or data"
         (name ruleset)
         (data ...)
         ==> item ...)
       (add-rule 'name
                 ruleset
                 '()
                 '(data ...)
                 #'(item ...)))
      (;; still looking for goals or data
       (define-rule
         "gather goals or data"
         (name ruleset)
         (goal-or-data ...)
         item-1 item-2 ...)
       (define-rule
         "gather goals or data"
         (name ruleset)
         (goal-or-data ... item-1)
         item-2 ...))
      (;; found data (no actions)
       (define-rule
         "gather data or actions"
         (name ruleset)
         (goal ...)
         (data ...))
       (add-rule 'name
                 ruleset
                 '(goal ...)
                 '(data ...)
                 #f))
      (;; found the end of the data
       (define-rule
         "gather-data-or-actions"
         (name ruleset)
         (goal ...)
         (data ...)
         ==> action ...)
       (add-rule 'name
                 ruleset
                 '(goal ...)
                 '(data ...)
                 #'(action ...)))
      (;; still looking for data or actions
       (define-rule
         "gather data or actions"
         (name ruleset)
         (goal ...)
         (data-or-action ...)
         item-1 item-2 ...)
       (define-rule
         "gather data or actions"
         (name ruleset)
         (goal ...)
         (data-or-action ... item-1)
         item-2 ...))))
  
  )