[plt-scheme] local-expansion interaction with class.ss

From: Jim Meier (jdm352 at mail.usask.ca)
Date: Thu Jun 14 15:12:31 EDT 2007

I'm new to using mzscheme macros, and so I apologize if the answer to  
these questions is as simple as pointer to the correct paragraph of  
documentation.

I'm trying to build an extension language on top of the standard  
mzscheme that redefines #%app to preprocess the call through a simple  
wrapper function:

(module my-lang mzscheme
   (define-syntax my-app
     (syntax-rules ()
       ((_ f a ...)
        (app/wrapper f a ...))))

   (define (app/wrapper fun . args)
     ;; various processing
     (apply fun args))

   (provide (all-from-except mzscheme #%app))
   (provide (rename my-app #%app))
)

This works well for many programs; however, if those programs use the  
standard class.ss library, this causes issues:

(module objects-test my-lang
   (require (lib "class.ss"))

   (define cls%
     (class object%
       (define/public (some-method a)
         (printf "Method invoked: ~a\n" a))
       (super-new)
       (some-method "Implicit Send")))
)

Here, some-method is converted to a macro that only works in the  
application position; so when the my-app macro rewrites (some-method  
"Implicit Send") to (app/wrapper some-method "Implicit Send"), it  
complains with:

    class: misuse of method (not in application) in: some-method


It seems that I can get past this difficulty by using local-expand to  
remove all macros from the syntax before transforming it. An initial  
attempt at putting local-expand inside the my-app macro was a  
failure, causing infinite recursion as it repeatedly tried to expand  
itself.

Instead, it seems that I'll have to do the the expansion earlier. I  
chose to replace #%module-begin, and do the expansion in there; but  
even before adding my-app back in, I encountered a problem. Here's an  
example:

(module a mzscheme
   (provide (all-from-except mzscheme #%module-begin))
   (provide (rename my-module-begin #%module-begin))

   (define-syntax (my-module-begin stx)
     (syntax-case stx ()
       [(_ e ...)
        (begin
	 (printf "Transforming Module:\n")
	 (printf "~s\n" (syntax-object->datum stx))
	 (let* ([expanded (local-expand (syntax (#%module-begin e ...))
					(syntax-local-context)
					null)])
	   (printf "expanded:\n")
	   (printf "~s\n" (syntax-object->datum expanded))
	   expanded))]))
)


(module b a
   (require (lib "class.ss"))

   (define cls% (class object%
                  (super-new)))
)

(require b)

Here, the transformation takes place as expected, but the compilation  
fails with the error:

/Users/jdm352/Library/PLT Scheme/360/collects/mzlib/private/class- 
internal.ss:1296:85: compile: identifier used out of context in:  
super-go

Why is this the case? My understanding (weak as it is) was that  
expansion would preserve all the contexts required (how else could  
the compiler work, for example?). Clearly, I've got a fundamental  
misunderstanding about the macro system, and reading the docs and  
papers is leaving me scratching my head in further confusion.

Is this local-expansion plan the correct way to solve the problem? If  
so, why does it lose the proper context for super-go and other  
identifiers?

Much thanks for any help you can point me to.

Jim


Posted on the users mailing list.