Convert String of Racket Source Code into Racket Code
Solution 1:
If you want to evaluate a string, then naïvely you want read
and eval
. You certainly don't want a macro.
Note this is insanely dangerous and almost certainly an extremely bad idea: running uncontrolled code (or even calling read
unless you have absolute faith in read
's safety) that you have been sent by something only makes sense if you have implicit, total trust in the thing that sent you the code. There have been very many famous problems because people abused such trust. At the very least you should read Reflection and Security in the Racket documentation: especially the stuff on sandboxes. But sandboxed evaluators have also been subject to many famous exploits.
;;; May explode if exposed to light. Hypergolic in air.
;;;
(define string-to-evaluate "
(define-syntax-rule (bind [v val] form ...)
(let ([v val]) form ...))
(bind (foo 1)
(+ foo foo))
(define bar 1)
")
(define (evaluate-string s (n (make-base-namespace)))
(values
(call-with-input-string
s
(λ (p)
(for/list ([form (in-port read p)])
(eval form n))))
n))
> (evaluate-string string-to-evaluate)
'(#<void> 2 #<void>)
#<namespace>
> bar
bar: undefined;
cannot reference an identifier before its definition
> (evaluate-string string-to-evaluate (current-namespace))
'(#<void> 2 #<void>)
#<namespace:'anonymous-module>
> bar
1
But
> (evaluate-string "(require racket/system) (system \"echo now I own your computer\")")
now I own your computer
'(#<void> #t)
#<namespace>
Oops.