[plt-scheme] macros for unit/sig

From: David Herman (dherman at ccs.neu.edu)
Date: Sun May 25 18:50:04 EDT 2003

I'm learning a few things at once here, so please forgive any 
muddle-headedness... I'm having some trouble defining macros that 
generate unit/sig. Below is an example: a signature called "algorithm" 
that imports a math unit to compute something. I want to introduce a 
"define-algorithm" form that hides the plumbing.

I managed to figure out (admittedly without quite understanding it) how 
to match the implementation's function with the function in the 
signature -- by introducing it to syntax-case as a keyword -- but now 
the problem is that an implementation can't use any of the imported 
identifiers. The following code produces a "reference to undefined 
identifier: plus".

At what point is the body being evaluated? I would've expected it not 
to evaluate it until after it expanded the macro, so the reference 
would safely be within the body of the unit/sig declaration. Or is this 
a case where hygiene is causing identifiers not to match?

Thanks so much,

;; --
(require (lib "unitsig.ss"))

(define-signature math^ (plus minus times divide))
(define math@
   (unit/sig math^
     (define plus +)
     (define minus -)
     (define times *)
     (define divide /)))

(define-signature algorithm^ (compute))

(define-syntax (define-algorithm expr)
   (syntax-case expr (define compute)
     [(_ name d1 d2 ...)
            (let f ([ds (syntax->list (syntax (d1 d2 ...)))])
                    (syntax-case (car ds) (define compute)
                      [(define (compute) e1 e2 ...)
                       (syntax (define compute (lambda () e1 e2 ...)))]
                      [(define (compute a1 a2 ...) e1 e2 ...)
                       (syntax (define compute (lambda (a1 a2 ...) e1 e2 
                      [(define compute e)
                       (syntax (define compute e))]
                      [(define (fn) e1 e2 ...)
                       (syntax (define fn (lambda () e1 e2 ...)))]
                      [(define (fn a1 a2 ...) e1 e2 ...)
                       (syntax (define fn (lambda (a1 a2 ...) e1 e2 
                      [(define x e)
                       (syntax (define x e))])])
                (if (null? (cdr ds))
                    (syntax first)
                    (with-syntax ([rest (f (cdr ds))])
                      (syntax (begin first rest))))))])
        (syntax (define name
                  (unit/sig algorithm^
                    (import math^)

(define-algorithm alg@
   (define (compute) (plus (times 2 3) 4)))

(define linked@
     (link (MATH : math^ (math@))
           (ALG  : algorithm^ (alg@ MATH)))
     (export (open ALG))))

(define-values/invoke-unit/sig algorithm^ linked@)

(compute) ; error: reference to undefined identifier: plus
;; --

Posted on the users mailing list.