Pregunta

I've been stuck with an issue for a number of hours now. I'm trying to define a DSL using Racket's language extension features. I want to do something like the following pseudo-code. Ultimately I'd like to generate functions and macros given the input in the DSL, and most of that seems to work now, the problem is providing definitions which should work at the same level as the declarations. Is this even possible? It's late, and I'm sure I'm missing something really trivial. The most basic example of the problem is this:

tinylang.rkt:

#lang racket

; here we redefine module begin.
(provide (all-defined-out)
         (except-out (all-from-out racket) #%module-begin)
         (rename-out [module-begin #%module-begin])
         )

(define-syntax (module-begin stx)
  (syntax-case stx ()
    [(_ stmts ...)
     #`(#%module-begin
       (define (hello) (print "Yes!") (newline))
       ; (provide (for-syntax hello))
       (print "Function defined.")
       stmts ...   )]))

Now I try to use this new language elsewhere:

try.rkt:

#lang s-exp "tinylang.rkt"
(hello)

But I get the error "hello: unbound identifier in module in: hello", when loading the second module.

¿Fue útil?

Solución

The problem is that hello is defined in the lexical scope of tinylang.rkt but you want it to be in scope in try.rkt. You can use datum->syntax to set the lexical context of a piece of syntax.

This will fix the problem:

#lang racket

; here we redefine module begin.
(provide (all-defined-out)
         (except-out (all-from-out racket) #%module-begin)
         (rename-out [module-begin #%module-begin])
         )

(define-syntax (module-begin stx)
  (syntax-case stx ()
    [(_ stmts ...)
     #`(#%module-begin
       #,(datum->syntax 
          stx
          (syntax->datum 
           #'(define (hello) (print "Yes!") (newline))))
       (print "Function defined.")
       stmts ...   )]))

UPDATE:

In response to comments, the previous solution could be simplified to:

(define-syntax (module-begin stx)
  (syntax-case stx ()
    [(_ stmts ...)
     (with-syntax ([hello-fn (datum->syntax stx 'hello)])
       #`(#%module-begin
          (define (hello-fn) (print "Yes!") (newline))
          (print "Function defined.")
          stmts ...   ))]))
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top