From SRS0=wz7z=NV=google.com=posting-system@bounce2.pobox.com Wed Nov 3 00:15:27 2004 Date: Tue, 2 Nov 2004 17:15:22 -0800 From: oleg-at-pobox.com Newsgroups: comp.lang.scheme Subject: Re: See results of macro expansion References: Message-ID: <7eb8ac3e.0411021715.2dff620c@posting.google.com> Status: OR Hans Oesterholt-Dijkema wrote in message news:... > Is there a way to see the results of macro > expansion in scheme expressions? Petite Chez Scheme has `expand' procedure, SCM has the procedure `macroexpand', Scheme48 has `expand' _command_, Bigloo has a compile-time flag `-syntax' that produces a file after macro-expansion. One can always use Al Petrofsky's alexpander to expand a particular form. Given below is a portable, R5RS syntax-rule tracer. It is not perfect, but is often useful. (define-syntax mtrace (syntax-rules () ((mtrace x) (begin (display "Trace: ") (write 'x) (newline) x)))) That is it. Given your macro: (define-syntax test (syntax-rules () ((test name a1 ...) (define (name a1 ...) (apply * (list a1 ...)))))) we re-write it as follows: (define-syntax test (syntax-rules () ((test name a1 ...) (mtrace (define (name a1 ...) (apply * (list a1 ...))))))) that is, just enclose the template of the clause of interest in mtrace: > (test h a b c) Trace: (define (h a b c) (apply * (list a b c))) > (h 1 2 3) 6 Here's a more interesting example, of a tracing of a recursive macro, letrec -- taken verbatim from R5RS. We renamed it into rletrec, to avoid name clashes: (define-syntax rletrec1 (syntax-rules () ((_ ((var1 init1) ...) body ...) (rletrec "generate temp names" (var1 ...) () ((var1 init1) ...) body ...)) ((_ "generate temp names" () (temp1 ...) ((var1 init1) ...) body ...) (let ((var1 #f) ...) (let ((temp1 init1) ...) (set! var1 temp1) ... body ...))) ((_ "generate temp names" (x y ...) (temp ...) ((var1 init1) ...) body ...) (rletrec "generate temp names" (y ...) (newtemp temp ...) ((var1 init1) ...) body ...)))) Actually, we renamed the top-level macro: rletrec into rletrec1, and added the following trivial macro: (define-syntax rletrec (syntax-rules () ((rletrec . args) (mtrace (rletrec1 . args))))) Then the following (rletrec ((a 1) (b (lambda () a)) (c (lambda (f) (if f (c #f) (b))))) (c #t)) produced the output: Trace: (rletrec1 ((a 1) (b (lambda () a)) (c (lambda (f) (if f (c #f) (b))))) (c #t)) Trace: (rletrec1 "generate temp names" (a b c) () ((a 1) (b (lambda () a)) (c (lambda (f) (if f (c #f) (b))))) (c #t)) Trace: (rletrec1 "generate temp names" (b c) (newtemp) ((a 1) (b (lambda () a)) (c (lambda (f) (if f (c #f) (b))))) (c #t)) Trace: (rletrec1 "generate temp names" (c) (newtemp newtemp) ((a 1) (b (lambda () a)) (c (lambda (f) (if f (c #f) (b))))) (c #t)) Trace: (rletrec1 "generate temp names" () (newtemp newtemp newtemp) ((a 1) (b (lambda () a)) (c (lambda (f) (if f (c #f) (b))))) (c #t)) 1 One can see a notable drawback: identifiers are printed without their color. Alas, that problem can't be solved portably.