Here is a self-contained example that shows how one might do communication; I believe something like this would work in the context of the DrRacket evaluator as well, though I haven't tried it yet.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; #lang racket ;; Experiment: interaction between compiled code and a tool. ;; ;; Often, 3d syntax is often used here to get expanded code to communicate ;; with some other third party (like a tool). ;; ;; But let's say we don't want 3d syntax. Is there another way? ;; ;; Idea: when evaluating code, attach a module to the evaluating ;; namespace that the code and the tool share. ;; (require syntax/kerncase) (define ns (make-base-namespace)) (eval '(module tool-runtime racket/base (provide (all-defined-out)) (define current-on-application (make-parameter (lambda (stx) (printf "default\n") (void))))) ns) (eval '(require 'tool-runtime) ns) ;; Let us extract out an identifier syntax for the current-on-application ;; function: ;; ;; current-on-app-stx: identifier (define current-on-app-stx (eval '#'current-on-application ns)) ;; It will also be useful to get the actual parameter value, and not just the syntax. (define current-on-application (eval 'current-on-application ns)) ;; If we inspect at current-on-app-stx, we'll see that it has an identifier binding ;; attached to the tool-runtime module we're written above. ;; Let us try to use this in the context of annotating a bit of code and injecting calls ;; to current-on-application. First, let's create the expanded code: (define expanded-code (parameterize ([current-namespace ns]) (expand '(begin (define (f x) (* x x)) (define (hypo a b) (sqrt (+ (f a) (f b)))) (displayln (hypo 3 4)))))) ;; Now let's annotate this code. ;; We will put a reference to the tool-runtime's current-on-application ;; whenever we see an application. ;; Note: this sample annotator is woefully incomplete. We should really follow the ;; grammar of fully-expanded syntax! This is just to sketch out the idea. (define annotated-code (let loop ([stx expanded-code]) (kernel-syntax-case stx #f [(begin top-level-form ...) #`(begin #,@(map loop (syntax->list #'(top-level-form ...))))] [(define-values (id ...) expr) #`(define-values (id ...) #,(loop #'expr))] [_ (identifier? stx) stx] [(#%plain-lambda formals expr ...) #`(#%plain-lambda formals #,@(map loop (syntax->list #'(expr ...))))] [(#%plain-app expr ...) #`(begin ((#,current-on-app-stx) #'#,stx) (#%plain-app expr ...))]))) annotated-code ;; If we had been using 3d syntax, the annotated code would not be compilable. ;; But here, we can still compile the code. The compiler will know that the ;; references to current-on-application refer to our tool-runtime module, since ;; we're compiling it in the namespace that knows about it. (define compiled-code (parameterize ([current-namespace ns]) (compile annotated-code))) ;; Now, if we try to evaluate the code in a namespace that doesn't know about ;; that tool-runtime, of course bad things will happen: it will say that it has ;; no idea what tool-runtime is about: ; ; Uncomment the following to see the error: #;(eval compiled-code (make-base-namespace)) ;; But we can evaluate it in ns: (printf "evaluating the compiled code\n") (eval compiled-code ns) (newline) ;; Most importantly, we should be able to also override the parameter: (printf "overridding current-on-application:\n") (parameterize ([current-on-application (lambda (stx) (printf "calling ~s\n" stx))]) (eval compiled-code ns)) ____________________ Racket Users list: http://lists.racket-lang.org/users