home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-386-Vol-2of3.iso
/
c
/
cr-macro.zip
/
RULES.SCM
< prev
next >
Wrap
Text File
|
1990-02-16
|
5KB
|
147 lines
; Rewrite-rule compiler (a.k.a. "extend-syntax")
; Fix bug with nested ... patterns
; Put fenders and subkeyword lists following template?
; Example:
;
; (define-syntax or
; (syntax-rules ()
; ((or) #f)
; ((or e) e)
; ((or e1 e +) (let ((temp e1))
; (if temp temp (or e +))))))
(define (r exp) ;for testing
(rewrite-syntax-rules exp (lambda (x) x) eq?))
(define (rewrite-syntax-rules exp rename compare)
(process-rules (cddr exp) (cadr exp) rename compare))
(define (process-rules rules subkeywords rename compare)
(let ((tail '%tail%))
`(lambda (%input% %rename% %compare%) ;These should be renamed...
(let ((,tail (cdr %input%)))
(cond ,@(map (lambda (rule)
(process-rule rule tail subkeywords))
rules)
(else (syntax-error "use of macro doesn't match definition"
%input%)))))))
(define (process-rule rule tail subkeywords)
(if (not (= (length rule) 2))
(syntax-error "ill-formed rule" rule))
(let ((pattern (car rule))
(template (cadr rule)))
(let ((env (process-pattern (cdr pattern) tail null-rank subkeywords)))
`(,(process-match tail (cdr pattern) subkeywords)
(let* ,(map (lambda (z)
`(,(car z) ,(cadr z)))
env)
,(process-template template env null-rank))))))
(define null-rank '())
; Generate code to test whether input expression matches pattern
(define (process-match input pattern subkeywords)
(cond ((name? pattern)
(if (member pattern subkeywords)
`(%compare% ,input ',pattern)
`#t))
((zero-or-more? pattern)
(process-list-match input (car pattern) subkeywords))
((at-least-one? pattern)
`(and (not (null? ,input))
,(process-list-match input (car pattern) subkeywords)))
((pair? pattern)
`(let ((%temp% ,input))
(and (pair? %temp%)
,(process-match `(car %temp%) (car pattern) subkeywords)
,(process-match `(cdr %temp%) (cdr pattern) subkeywords))))
(else
`(equal? ,input ',pattern))))
(define (process-list-match input pattern subkeywords)
`(let loop ((l ,input))
(or (null? l)
(and (pair? l)
,(process-match '(car l) pattern subkeywords)
(loop (cdr l))))))
; Generate code to take apart the input expression
(define (process-pattern pattern path rank subkeywords)
(cond ((name? pattern)
(if (name-member pattern subkeywords)
'()
(list (list pattern path rank))))
((or (zero-or-more? pattern)
(at-least-one? pattern))
(let ((temp '%temp%)) ;Bug -- should gensym here!!
(cons `(,temp ,path)
(map (lambda (z)
`(,(car z)
(map (lambda (%input%)
,(cadr z))
,temp)
,(caddr z)))
(process-pattern (car pattern)
'%input%
(cons (cadr pattern) rank)
subkeywords)))))
((pair? pattern)
(append (process-pattern (car pattern) `(car ,path) rank subkeywords)
(process-pattern (cdr pattern) `(cdr ,path) rank subkeywords)))
(else '())))
; Generate code to compose the output expression according to template
(define (process-template template env rank)
(cond ((name? template)
(let ((probe (name-assoc template env)))
(if probe
(if (equal? (caddr probe) rank)
template
(syntax-error "rank error" template rank))
`(%rename% ',template))))
((or (zero-or-more? template)
(at-least-one? template))
(let ((vars (free-template-vars (car template) env '())))
(if (null? vars)
(syntax-error "ill-formed template" template)
`(map (lambda ,vars
,(process-template (car template)
env
(cons (cadr template) rank)))
,@vars))))
((pair? template)
`(cons ,(process-template (car template) env rank)
,(process-template (cdr template) env rank)))
(else `',template)))
(define (free-template-vars template env free)
(cond ((name? template)
(if (and (name-assoc template env)
(not (name-member template free)))
(cons template free)
free))
((or (zero-or-more? template)
(at-least-one? template))
(free-template-vars (cadr template) env free))
((pair? template)
(free-template-vars (car template) env
(free-template-vars (cdr template) env free)))
(else free)))
(define (check-cadr syms)
(lambda (pattern)
(and (pair? pattern)
(pair? (cdr pattern))
(memq (cadr pattern) syms)
(or (null? (cddr pattern))
(syntax-error "segment matching not implemented" pattern)))))
(define zero-or-more? (check-cadr `(* ,(string->symbol "..."))))
(define at-least-one? (check-cadr '(+)))