Newsgroups: comp.lang.scheme
Path: cantaloupe.srv.cs.cmu.edu!das-news2.harvard.edu!news2.near.net!howland.reston.ans.net!torn!nott!cunews!syou
From: syou@sol.carleton.ca (Shihong You)
Subject: help
Message-ID: <syou.795713117@sol>
Keywords: macro
Sender: news@cunews.carleton.ca (News Administrator)
Organization: Carleton University
Date: Mon, 20 Mar 1995 15:25:17 GMT
Lines: 145

Hello, everyone. Currently I have a problem in program in Scheme.
We want to use continuation to implement rule base systems.
A rule consists of a collection of clauses, it has form of
          (Rule
            Clause exp .. exp EndClause
            Clause exp .. exp EndClause
            .....
            Clause exp .. exp EndClause
          EndRule)
The expressions in each clause are evaluated until it encounters
either function (failure) or (success). Failure will transfer the
control to next clause. Success will tranfer the control to EndRule. 
If neither failure nor success encounter in a clause, It will suppose
that a success function is hitted. This implies that if any one clause
is success, rule will return true; if all clauses are failure, rule will
return false.  
Following is my Scheme code for macro rule. There is some bug, but I
can't figure it out. Does anyone can help me work it out? 
Please send your reply to my email account:
          syou@sol.carleton.ca
Many thanks.
------
Sam

;---------- Macro Rule ------------;
; to evaluate these tests, please do the following:
;  (macro rule testRule) ---> to define the macro
;  (eval testN) ------> to test the macro

(define test1 
  '(Rule Clause (failure) EndClause EndRule))
(define test2 
  '(Rule 
     Clause (writeln "in clause now") EndClause 
    EndRule))
(define test3 
  '(Rule 
     Clause (writeln "before failure") 
            (failure) EndClause
     Clause (writeln "after failure")
            EndClause
    EndRule))
(define test4
  '(Rule 
     Clause (writeln "before failure")
            (failure) EndClause
     Clause (writeln "between failure and success")
            (success) EndClause
     Clause (writeln "I should not appear")
            EndClause
    EndRule))
(define test5
  '(Rule 
     Clause (set! x 4) (if (= x 4) (failure)) 
            EndClause
     Clause (writeln x) (if (> x 0) (success))
            EndClause
     Clause (writeln "nothing worked")
            EndClause
    EndRule))

;---------- Macro code ------------;
(define (first exp) (car exp))
(define (second exp) (cadr exp))
(define is= equal?)
(define == eq?)
(define nil ())

(define (list? exp)
  (cond 
    ((null? exp) #t)
    ((not (pair? exp)) #f)
    (else (list? (cdr exp)))))
(define (last exp)
  (cond 
    ((not (list? exp)) 
     (error "argument is not a list" exp))
    ((null? exp) nil)
    ((null? (cdr exp)) (car exp))
    (else (last (cdr exp)))))
(define (rest aList) 
  (cond 
    ((list? aList) 
     (error "this is not a list" aList))
    ((null? aList) nil)
    (else (cdr aList))))
(define (addLast aList anObject) 
  (if (not (list? aList))
      (error "argument should be a list" aList)
      (if (null? aList)
          (cons anObject aList)
          (cons (car aList) 
                (addLast (cdr aList) anObject)))))

(define (testRule originalExp)
   
  (define (checkFormat exp)
    (if (not (is= (first exp) 'rule))
        (error "this is not a rule" exp)
        (if (not (is= (last exp) 'endrule))
            (error "not ending with endrule" exp)
            #t))) ;pass the checking
   
  (define (skipThisClause exp)
    (cond ((is= (car exp) 'EndClause) (cdr exp))
          ((is= (car exp) 'Clause) exp)
          (else (skipThisClause (cdr exp)))))
 
  (define (getClause exp)
    (cond ((is= (car exp) 'EndRule) nil)
          ((is= (car exp) 'EndClause) nil)
          (else (cons (car exp) (getClause (cdr exp))))))
  (define (getNextClause exp)
    (getClause (cdr (skipThisClause exp))))  

  (define (moreClause? exp)
    (cond ((is= (car exp) 'EndRule) nil)
          ((is= (car exp) 'Clause) #t)
          (else (error "incorrect format" exp))))

  (define (getAllClauses exp)
    (if (moreClause? exp) 
        (cons (getNextClause exp) 
              (getAllClauses (skipThisClause (cdr exp))))
        nil))
 
  (define (expandClause aClause)
   `(call/cc (lambda (failureContinuation)
       (let ((failure (lambda () 
           (failureContinuation nil))))
        ,(addLast aClause '(success)) )))  )
 
  (define (expandExp exp) 
   `(call/cc (lambda (successContinuation)
      (let ((success (lambda () 
             (successContinuation #t))))
        ,(map expandClause (getAllClauses exp))
        #f))) )

  (checkFormat originalExp)  
  (expandExp (cdr originalExp)))
  (eval (expandExp (cdr originalExp))) )   
        


