0

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?

Martin Cejp
  • 607
  • 6
  • 13
  • Does `pair` come from your language? (because it's not in Racket) If so, you may just need to add a `(require my-language)` to get the expected result – stchang Sep 26 '22 at 20:44
  • @stchang Yep, `pair` it is a custom form. The language, after macro expansion, is not executed on the Racket runtime. Here is the same goal achieved in Hy: https://mcejp.github.io/2022/08/18/hy-macroexpand.html – Martin Cejp Sep 27 '22 at 11:49

0 Answers0