[plt-scheme] Macro update

From: Noel Welsh (noelwelsh at yahoo.com)
Date: Tue Feb 3 17:41:22 EST 2004

In case anyone is feverishly hacking away at the macro
I emailed, I've made substantial progress.  It appears
I've got a working macro, just the funky structures I
defined don't work with match so I'm going to have to
rework it a bit.  I also think I'm long past the time
when I'm getting any return for extra effort so I'm
going to get some sleep.

Noel

The macro is:

  (define-syntax production
    (lambda (stx)
      (syntax-case stx ()
        ((_)
         (syntax (list)))
        ((_ head rest ...)
         (syntax (cons head (production rest ...))))
        ((_ (head subtree ...) rest ...)
         (syntax
          (cons
           (production head subtree ...)
           (production rest ...)))))))
  
  (define-syntax (l-system stx)
    (syntax-case stx ()
      ((l-system
        ((name param ...) rhs ...) ...)
       (datum->syntax-object 
        stx
        (syntax
         (letrec
             ([loop
               (lambda (lst)
                 (cond
                   [(null? lst) lst]
                   [(and (pair? lst)
                         (pair? (car lst)))
                    (append (cons
                             (matcher (car (car lst)))
                             (loop (cdr (car lst))))
                            (loop (cdr lst)))]
                   [(pair? lst)
                    (cons
                     (matcher (car lst)) 
                     (loop (cdr lst)))]))]
              [matcher
               (lambda (head)
                 (match head
                   [(struct name (param ...))
                    (production rhs ...)]
                   ...))])
           loop))))))
  

The funky structs that don't work with match are:

  ;; words for parametric l-systems
  ;; essentially closures that can be inspected
  (define-syntax (define-word stx)
    (syntax-case stx ()
      ((define-word (name param ...) expr ...)
       (with-syntax 
           ([(struct:name name name?)
             (let ((name-sym (syntax-object->datum
(syntax name))))
               (map (lambda (sym)
                      (datum->syntax-object (syntax
name) sym (syntax name)))
                    (list
                     (symbol-append 'struct: name-sym)

                     name-sym
                     (symbol-append name-sym '?))))]
            [(name-param-accessor ...)
             (let ((name-sym (syntax-object->datum
(syntax name))))
               (map (lambda (param)
                      (datum->syntax-object (syntax
name)
                                           
(symbol-append name-sym '- param)
                                            (syntax
name)))
                    (syntax-object->datum 
                     (syntax (param ...)))))])        
                                
         (syntax
          (define-values (struct:name name name?
name-param-accessor ...)
            (let ((number-of-params (length (list
(quote param) ...))))
              (letrec-values (((struct:name make-name
name? name-ref name-set!)
                               (make-struct-type
(quote name)
                                                
struct:word
                                                
number-of-params
                                                 0
                                                 #f
                                                 null
                                                
(current-inspector)
                                                
(lambda (word) 
                                                  
(apply
                                                   
(lambda (param ...) expr ...)
                                                   
(let loop ((i 0))
                                                     
(if (= i number-of-params)
                                                      
   (list)
                                                      
   (cons (name-ref word i)
                                                      
         (loop (add1 i))))))))))
                (apply values
                       struct:name
                       (lambda (param ...)
                         (make-name (quote name) param
...))
                       name?
                       (let loop ((i 0))
                         (if (= i number-of-params)
                             (list)
                             (cons (lambda (word)
(name-ref word i))
                                   (loop (add1
i))))))))))))))
  

An example is:

  (define-word (word-1 a b c) (list a b c))
  
  (define l-system-tests
    (make-test-suite
     "L-System tests"
             
     (make-test-case
      "define-word test"
      (let ((the-word (word-1 1 2 3)))
        (assert-equal? (the-word)
                       (list 1 2 3))))
     (make-test-case
      "word accessor test"
      (let ((the-word (word-1 1 2 3)))
        (assert-equal? (word-1-a the-word) 1)
        (assert-equal? (word-1-b the-word) 2)
        (assert-equal? (word-1-c the-word) 3)))
     (make-test-case
      "word predicate procedure test"
      (assert-true (word-1? (word-1 1 2 3))))
     
     (make-test-case
      "simple parameterised l-system test"
      (assert-equal?
       ((l-system ((word-1 1 b c) (+ b c) (+ b c))
                  ((word-1 a b c) (+ a b c)))
        (list (word-1 1 2 3) (word-1 2 3 4)))
       (list 5 5 9)))

=====
Email: noelwelsh <at> yahoo <dot> com
Jabber: noelw <at> jabber <dot> org

__________________________________
Do you Yahoo!?
Yahoo! SiteBuilder - Free web site building tool. Try it!
http://webhosting.yahoo.com/ps/sb/


Posted on the users mailing list.