~ ~require-macros
contains a couple compiler.assert
calls, which emit normally when require-macros
is invoked directly. However, when invoked indirectly via import-macros
, the errors get emitted in a nested form.
~Additionally, if there are any associated fennel.friend suggestions (I don't think there are any that can currently come from ~import-macros
, but there's a new assert I'm about to merge that will), the suggestion is emitted twice.
This problem is much simpler than it first appears: any errors coming from an assert-compile
call that originated from a macro that has suggestions matching the provided error message will result in any friend.fnl suggestions to be printed twice. This includes the ones in require-macros
when it's being invoked by import-macros
.
;; can use any message that has a match in `friend.fnl`
(macro oops [s] (assert-compile false "unable to bind (.*)" s) "unreachable")
(oops)
Error output:
(oops asdf)
Compile error: Compile error in unknown:2:0
Compile error in unknown:2:6
unable to bind (.*)
(oops asdf)
* Try replacing the (.*) with an identifier.
stack traceback:
[C]: in function 'error'
/usr/local/bin/fennel:3728: in function 'fennel.friend.assert-compile'
/usr/local/bin/fennel:2464: in function 'fennel.compiler.assert'
[string "local function _1_(s)..."]:2: in function <[string "local function _1_(s)..."]:1>
(...tail calls...)
[C]: in function 'xpcall'
/usr/local/bin/fennel:2972: in function 'fennel.compiler.macroexpand'
/usr/local/bin/fennel:3159: in function 'fennel.compiler.compile1'
/usr/local/bin/fennel:3456: in function 'fennel.compiler.compile'
[C]: in function 'pcall'
/usr/local/bin/fennel:864: in function </usr/local/bin/fennel:842>
(...tail calls...)
/usr/local/bin/fennel:907: in function 'fennel.repl'
(...tail calls...)
[C]: in ?
* Try replacing the (.*)
(oops asdf)
* Try replacing the (.*) with an identifier.
stack traceback:
[C]: in function 'error'
/usr/local/bin/fennel:3728: in function 'fennel.friend.assert-compile'
/usr/local/bin/fennel:2464: in function 'fennel.compiler.assert'
[string "local function _1_(s)..."]:2: in function <[string "local function _1_(s)..."]:1>
(...tail calls...)
[C]: in function 'xpcall'
/usr/local/bin/fennel:2972: in function 'fennel.compiler.macroexpand'
/usr/local/bin/fennel:3159: in function 'fennel.compiler.compile1'
/usr/local/bin/fennel:3456: in function 'fennel.compiler.compile'
[C]: in function 'pcall'
/usr/local/bin/fennel:864: in function </usr/local/bin/fennel:842>
(...tail calls...)
/usr/local/bin/fennel:907: in function 'fennel.repl'
(...tail calls...)
[C]: in ? with an identifier.
macroexpand
is using pcall
to invoke macros to expand the AST, and then running (assert-compile ok ...)
to verify successful expansion.
The upside to doing this is that we get the friendly suggestions even for any assert
calls within the macro itself, and it highlights the entire macro call.
The downside is we lose the ability to highlight more granular areas of a macro call (such as a sym being where it shouldn't , etc), and there's little benefit to assert-compile
being in the compiler scope.
Ideally we can find a way for friend.assert-compile
(and assert-compile
ingeneral) to detect nesting and dedupe the output.
For an example of the double-suggestions from
fennel.friend
, here's a repro for an assert I just added torequire-macros
(and the reason I spotted this), present in currentmain
and the upcoming 1.2.0 release:
bad-macro.fnl
:(fn i-am-not-a-table [] "This won't work with import-macros" :oops)Running
(import-macros bad :bad-macro)Outputs:
Compile error in unknown:1:0 Compile error in unknown:1:15 expected macros to be table (import-macros bad :bad-macro) * Try ensuring your macro definitions return a table. * Try ensuring your macro definitions return a table.
EDITED: This was a red herring! See edited bug description.