~technomancy/antifennel

964c5f67417b20e46314142780d9cf9aea7667b7 — Phil Hagelberg 8 months ago ecd2169
Ensure that mixed tables don't end in multivals.
5 files changed, 26 insertions(+), 11 deletions(-)

M README.md
M anticompiler.fnl
M changelog.md
M test.lua
M test_expected.fnl
M README.md => README.md +13 -4
@@ 76,10 76,19 @@ The second example must be split into two separate assignments in
order to compile, since `tset` does not support multiple value
assignment in Fennel.

Regular statement-comments are compiled to Fennel comments; multi-line
comments are currently not supported, nor are comments inside tables
and argument lists. Sometimes comments which should go on the end of
an existing line get placed on their own line.
Regular line-comments are compiled to Fennel comments when the
`--comments` argument is given; multi-line comments are currently not
supported, nor are comments inside tables and argument
lists. Sometimes comments which should go on the end of an existing
line get placed on their own line.

Expanding multi-values into key/value tables does not work; for instance:

    local t = { a = "value", "bcd", ... }

This is because while the Fennel output can contain mixed tables, it
can't guarantee the order of the keys in the table, and for the above to
work, the multi-valued expression must be the last one in the Lua output.

## Integration


M anticompiler.fnl => anticompiler.fnl +10 -1
@@ 310,11 310,20 @@
              step-compiled step-compiled)]
          (unpack (map body (partial compile subscope))))))

(fn potential-multival? [{: kind}]
  (or (= :Vararg kind) (= :CallExpression kind)))

(fn table* [compile scope {: keyvals}]
  (let [out (if (next keyvals)
                (sequence)
                {})]
    (each [_ [v k] (pairs keyvals)]
    (each [i [v k] (ipairs keyvals)]
      ;; if the current key is nil then it's numeric; if there's no metatable
      ;; on out, then the table has *some* non-numeric key.
      (assert (not (and (= nil k) (not (getmetatable out))
                        (= nil (. keyvals (+ i 1)))
                        (potential-multival? v)))
              (.. "Mixed tables can't end in potential multivals: " (view keyvals)))
      (if k
          (do (tset out (compile scope k) (compile scope v))
              (setmetatable out nil))

M changelog.md => changelog.md +1 -0
@@ 2,6 2,7 @@

## 0.3.0 / ???

* Refuse to compile multivals at the end of mixed tables.
* Fix a bug with raw iterator values in a for loop.
* Add support for comments.
* Add support for bitwise operators.

M test.lua => test.lua +1 -3
@@ 56,9 56,7 @@ local function f123(_1)
end

local function bcd(...)
   local t = { a = "value", "bcd", ... }
   -- TODO: this doesn't work.
   -- assert(t[3] == "three", t[3])
   local t = { a = "value", "bcd" }
   if true then return letter(), f123("a") end
   return nil
end

M test_expected.fnl => test_expected.fnl +1 -3
@@ 54,9 54,7 @@
  (let [/_0 :zero] (noprint (.. /_0 /_1)) (values {} 2 3)))

(fn bcd [...]
  (let [t {1 :bcd 2 ... :a :value}]
    ;; TODO: this doesn't work.
    ;; assert(t[3] == "three", t[3])
  (let [t {1 :bcd :a :value}]
    (when true
      (let [___antifnl_rtn_1___ (letter)
            ___antifnl_rtns_2___ [(f123 :a)]]