Fennel, when used as a library, provides a number of functions in order to call various parts of the compiler. Most of these functions accept, inside an options table, an optional list of plugins that can affect the way the compiler works. Although plugins have the :parse-error hook that affects the way parsing works, the function fennel.parser
does not accept a list of plugins. This means the only way to pass an argument to affect the parser is via a function like fennel.compileString
which parses and compiles in the same call (I haven't actually verified if this option works), or by calling the compiler via command line and passing a plugin filename as an argument.
Ideally, fennel.parser would be able to simply use the :plugins key from its options table.
The reason this is slightly more complicated than it looks is that the plugins are accessed via the
utils.hook
function. This function does not take the plugins as arguments; instead it looks for them inutils.root
which acts as a kind of cheap version of dynamic scope where for every compilation we set and unset the root values (chunk, options, and scope) when we enter and exit the compilation process. (This is why pluginsassert-compile
function has that final reset function arg; otherwise the root data doesn't get cleaned up.)So when the parser calls
utils.hook
during the normal compilation process, it works fine. But when you callfennel.parser
directly, there is no such "enter/exit" cycle for the root to be set. However, the point of the root is to avoid having to pass these values around everywhere, and within the parser, "everywhere" is not so big of a problem.So the first step would be to make
utils.hook
accept an optional argument to check for a plugins table instead of the root, because the root is simply not a viable concept infennel.parser
. Problem isutils.hook
takes...
so we can't add an optional argument. Maybe we can create a separateutils.hook-opts
or something which takes options as an arg and changeutils.hook
to call it? Or update all the calls toutils.hook
to pass in nil as its second argument before...
.
Thanks for the fix!