I'm building a custom language using Racket and I would like to expand all macros in a given piece of syntax, while leaving any other forms untouched.
Example:
#lang racket
(define-syntax-rule (identity x) x)
(define-syntax-rule (make-pair x y) (pair x y))
(define-syntax my-expand
(lambda (stx)
(define expr-stx (cadr (syntax-e stx)))
(printf "expanded1: ~a\n" (local-expand expr-stx 'expression #f))
(printf "expanded2: ~a\n" (local-expand expr-stx 'expression '()))
#'(void)
))
(my-expand (make-pair (identity foo) (identity bar)))
What I would like to get:
expanded1: #<syntax:expand.rkt:34:11 (pair (identity foo) (identity bar))>
expanded2: #<syntax:expand.rkt:34:11 (pair foo bar)>
What I get:
expanded1: #<syntax:expand.rkt:34:11 (pair (identity foo) (identity bar))>
expand.rkt:6:37: pair: unbound identifier
in: pair
location...:
expand.rkt:6:37
context...:
/usr/share/racket/collects/syntax/wrap-modbeg.rkt:46:4
I have read the Macros for Domain-Specific Languages paper, I have seen the ee-lib package and I have tried to look at other languages implemented in Racket, but I haven't been able to figure this out.
I have a hunch that the Racket expander needs to understand the scope of all identifiers it encounters, for example to enable macro hygiene. However, the scoping rules in my custom language do not really match Racket scoping rules. Is there an easy way out?