Search code examples
compiler-constructionschemeracketdslbeautiful-racket

My Racket code didn't run while the equivalent code works well


I am using Racket to write a Domain specific language, I have learned it from beautifulracket.com. When I try to finish my DSL's expander, I want to use macros to transform my DSL into racket code. More specifically, I want to use a macro to implement function call. Here's my code

(define-macro (r-eval PARAM ... (r-id ID))
  #'((eval (read (open-input-string ID))) PARAM ...))
(provide r-eval)

but when I try to run it, there are some errors: picture

This chinese DSL code 一 二之【+】 is equivalent to (r-eval 1 2 (r-id "+")),which is equivalent to ((eval (read (open-input-string "+"))) 1 2), and I use macro stepper to confirm that the macro expand correctly,picture but I got an error,+: unbound identifier; also, no #%top syntax transformer is bound in: +

I have (provide +) yet in my expander.rkt, I don't know what does the error means and why does it happens.Here's my expander.rkt's all code:

#lang br/quicklang
(define-macro (r-begin (r-program EXPR ...))
  #'(#%module-begin
     EXPR ...
     ;(display 123)
     ;(define expr-list
     ;  (list EXPR ...))
     ;(display expr-list)
     ;(void (run expr-list))
     ))
(provide (rename-out [r-begin #%module-begin]))

(define-macro (r-expr PARAM ...)
  #' (PARAM ...))
(provide r-expr)

(define-macro (r-eval PARAM ... (r-id ID))
  #'((eval (read (open-input-string ID))) PARAM ...))
(provide r-eval)

(define (run expr-list) 2)
(provide run)

(define (p x y) (+ x y))
(provide p)
(provide +)
(provide eval)
(provide read)
(provide open-input-string)

Solution

  • You should give eval the second argument, the environment that should containt the definition for +. That's what the error message means - that + has no definition.

    There's a built-in name for the initial environment that you can use there. Look in the documentation for the specifics.