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.

Reply via email to