Closed 6cdh closed 3 years ago
In order to do this you have to disable the compiler sandbox. Otherwise the sandbox would be useless and simply by requiring fennel you could escape it.
With the sandbox disabled, you can use this:
(macro form->string [form]
(let [fennel (require :fennel)]
(fennel.compileString (fennel.view form))))
(print (form->string (let [a (require :abc)]
(print (+ a 3)))))
$ fennel --no-compiler-sandbox scratch.fnl
local a = require("abc")
return print((a + 3))
(Note that since you are returning a string there is no need for quoting, unquoting, or autogensym.)
Normally the original code would fail with a better error message indicating that the compiler sandbox is to blame, but the fennel module itself is special because it's needed for compiling code that uses metadata, so we have to fake it out with a special replacement module. Perhaps we could add a __index metamethod on that fake module to make it clearer what is really happening.
Thanks a lot for correcting my code, it works.
Normally the original code would fail with a better error message indicating that the compiler sandbox is to blame
I can't understand. Use (os.date)
in macro:
(macro m []
(os.date))
(m)
still lead to an obscure error rather than pointing to sandbox (with the latest fennel until now)
[string "local function _1_(x)..."]:3: attempt to index a nil value (global 'os')
And sure, we need a better error message.
Perhaps we could add a __index metamethod on that fake module to make it clearer what is really happening.
I second this solution, it's often very ambigous seing an error of accessing nil
, and not being sure why, and then realizing that you're at compile time.
Turns out this is a bug in macros
where we apply strict globals checking based on runtime globals, not the compiler sandbox.
Fixed in 4f23734.
For example, this macro
can compile a form at runtime:
I expect it can be compiled at compile time, so it can yield this lua code:
I've tried
It can't work since field 'compileString' is not callable (a nil value).
Is there a way to do it?