Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Table literals modified by macros don't get all their fields emitted #425

Closed
datwaft opened this issue May 3, 2022 · 2 comments
Closed
Labels

Comments

@datwaft
Copy link

datwaft commented May 3, 2022

Environment

$ fennel --version
Fennel 1.1.0 on PUC Lua 5.4 

How reproduce the issue

1. Create a new file containing the following content:

(macro highlight! [name attributes colors]
  (let [name (tostring name)
        colors (collect [_ v (ipairs attributes) :into colors] (tostring v) true)]
    `(vim.api.nvim_set_hl 0 ,name ,colors)))

(macrodebug (highlight! MatchParen [:underline] {:bg "#262626"}))
(highlight! MatchParen [:underline] {:bg "#262626"})

2. Execute the following command:

fennel --globals vim -c <filename>

Expected result

The compilation result must be equals to the macrodebug result:

print("(vim.api.nvim_set_hl 0 \"MatchParen\" {:bg \"#262626\" :underline true})")
return vim.api.nvim_set_hl(0, "MatchParen", {bg = "#262626" :underline true})

Current result

The compilation result differs from the macrodebug result:

print("(vim.api.nvim_set_hl 0 \"MatchParen\" {:bg \"#262626\" :underline true})")
return vim.api.nvim_set_hl(0, "MatchParen", {bg = "#262626"})
@technomancy
Copy link
Collaborator

This is a really interesting one! It actually has nothing to do with
macrodebug, other than the fact that the bug happens during
compilation to lua, so macrodebug isn't affected.

What happens is that the parser puts a keys field in a metatable on
every key/value table literal it reads. This allows the table to be
reconstructed exactly as it was originally in the input; even though
key/value tables are un-ordered in their representation, we can emit
them with their keys in the original order.

The problem is that a macro can modify a table in a way that doesn't
actually change the separate keys table. When the compiler emits a
Lua table, currently it only pays attention to keys and if it
disagrees with the actual value of the table itself, the keys table
wins.

The correct behavior is to use keys only for ordering: we must ignore
entries which don't exist in the table, and we must ensure that
legitimate keys which aren't found in keys are still emitted in the Lua.

Anyway the best solution here of course is to not use a macro; this
code is much better suited for a function. But it is a legitimate bug in
the compiler, so I'll put together a fix for it. In the mean time if you
can't replace it with a function without breaking compatibility, you can
work around the bug by avoiding the use of :into and copying fields
manually for the time being.

Thanks for finding this.

@technomancy technomancy changed the title Compilation result differs from macrodebug result Table literals modified by macros don't get all their fields emitted May 3, 2022
@technomancy
Copy link
Collaborator

Should be fixed in 5596e09.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants