~technomancy/fennel#131: 
assert-compile originating from macros prints duplicate friend.fnl lines


~~~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.~~~

## UPDATE

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`.


## User macro repro

```fennel
;; 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.
```

## culprit: macroexpand

`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.
Status
REPORTED
Submitter
~jaawerth
Assigned to
No-one
Submitted
2 years ago
Updated
2 years ago
Labels
bug

~jaawerth 2 years ago

For an example of the double-suggestions from fennel.friend, here's a repro for an assert I just added to require-macros (and the reason I spotted this), present in current main 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.

~jaawerth 2 years ago*

EDITED: This was a red herring! See edited bug description.

Register here or Log in to comment, or comment via email.