Hi, I'm trying to write a macro that fully-expands define forms with the goal of doing some static checking (and thus want the code in racket core so that I know what I'm looking at). Ideally, this macro would work in any context where a define form works. Unfortunately, I'm having a great deal of difficulty using local-expand to get what I want. I've tried a few approaches---the code and simple examples are below.
Local expanding as a 'top-level' definition was closest to working because it both fully-expands the definition and inserts binding into the enclosing definition context. Unfortunately, it seems to fail to bind the identifier correctly in the body of its own define. I tried expanding in the 'syntax-local-context', but this causes define-values to complain that it isn't in a definition context (even though syntax-local-context is a module context, which I thought was a definition context). Creating a new definition context makes the expansion work, but the binding goes into the newly created context, which isn't what I want. It also doesn't fully expand the definition. (If I remove define-values from the stop list, it tries to fully-expand but dies complaining that define-values is not in a definition context). I think I'm probably misreading the documentation. Can anyone suggest a correct solution? Thanks, Scott #lang racket (require (for-syntax syntax/parse syntax/parse/lib/function-header)) (define-for-syntax (definition-local-context-expand stx) (local-expand stx (syntax-local-context) '())) (define-syntax (define-expand-top-level stx) (syntax-parse stx #:literals (define-expand-top-level) [(define-expand-top-level header:function-header body ...+) (local-expand #'(define header body ...) 'top-level '())])) (define-syntax (define-expand-local-context stx) (syntax-parse stx #:literals (define-expand-local-context) [(define-expand-local-context header:function-header body ...+) (local-expand #'(define header body ...) (syntax-local-context) '())])) (define-syntax (define-expand-new-context stx) (syntax-parse stx #:literals (define-expand-new-context) [(define-expand-new-context header:function-header body ...+) (let* ([def-ctx (syntax-local-make-definition-context)] [ctx (if (list? (syntax-local-context)) (cons (gensym) (syntax-local-context)) (list (gensym)))] [expd (local-expand #'(define header body ...) ctx (list #'define-values) def-ctx)]) (define ids (syntax-parse expd [(def (id) _) (list #'id)])) (syntax-local-bind-syntaxes ids #f def-ctx) (internal-definition-context-seal def-ctx) expd)])) ; Works as expected (define-expand-top-level (foo n) (+ n 1)) (foo 5) ; Fails to bind fib in the body of the define #;(define-expand-top-level (fib n) (if (<= n 1) 1 (+ (fib (- n 1)) (fib (- n 2))))) ; fib: unbound identifier in module in: fib ; Attempt to use the local-context (which should be a definition context?) #;(define-expand-local-context (fib n) (if (<= n 1) 1 (+ (fib (- n 1)) (fib (- n 2))))) ; define-values: not in a definition context in: ; (define-values (fib) (lambda (n) (if (<= n 1) 1 (+ (fib (- n 1)) (fib (- n 2)))))) ; Creating new definition context makes the expand work but doesn't expose ; the identifiers to the definition context I really want (define-expand-new-context (fib n) (if (<= n 1) 1 (+ (fib (- n 1)) (fib (- n 2))))) #;(fib 3) ; fib: unbound identifier in module in: fib -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.