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)]]