Comment by ~jaawerth on ~technomancy/fennel
Oh, good catch - I knew I should have looked at that unary fix too!
Comment by ~jaawerth on ~technomancy/fennel
Just sent a patch to the mailing list - even though it's a small change, I opted for a proper review instead of directly pushing since we're about to release 1.3.1 =)
Comment by ~jaawerth on ~technomancy/fennel
I looked at this today, and I think the cleanest fix will be to change
(eval (embed-source ...) ...)With a macro that loads the macros source, precompiles it within compiler scope with
:env _COMPILER
, emits the lua code as a string, and loads it in runtime in place ofeval
, using the newly created compiler env.Which sounds super confusing, but it should prevent the need for the bracket string and remove the indent. Bonus point, it'll save a little initialization time as fennel wouldn't have to compile parts of itself at startup.
Comment by ~jaawerth on ~technomancy/fennel
One solution coming to mind is to add a
:fn
plugin hook for the REPL that usesdebug.getupvalue
to get the names of every upvalue that's also a local, and every timelocal referredLocal = ___replLocals___['referredLocal']
is injeced on a REPL loop, also inject the necessarydebug.setupvalue
call to update it for that function.It would take a fair bit of doing, I think, so it still may be better to rethink how we currently save locals.
Comment by ~jaawerth on ~technomancy/fennel
~technomancy I too thought it was because the function was invoked after saving the replLocals, but it turns out to be a bit more complicated than that.
I went through the same steps you did getting it to print the spliced code, and one big difference is that if it were merely that, then the result of
(print (incf v))
wouldn't continue to increase every time you run it. But if you simply this (you don't need the macro or anything, you can just write a function):(var v 1) (fn incv [] (set v (+ v 1)) v) (incv) (incv) (incv) vYou'll get the output
2 3 4 1
It took me a minute to figure out where it was being updated and retained, but I finally worked it out: the original local still lives in
incv
as an upvalue!The function (generated or not) is creating a closure. Each time the REPL re-introduces saved locals when executing code, declaring a new local
v
. This value is the one set from and saved to___replLocals___
, distinct from the upvaluev
thatincv
is updating and returning.This may be tricky to correct - to account for any functions holding REPL locals as upvalues, you'd have to keep track of any such functions and use
debug.setupvalue
on them on each new REPL loop, which feels like a bit much. It'll likely take some thought to work out the cleanest fix.#fixing the out-of-order locals saving
There may be edge cases I'm not considering, but I think that one can be worked around by emitting something like
(function (...) <code to save locals> return ... end)(return_statement_with_return_removed)
Comment by ~jaawerth on ~technomancy/fennel
Resolve by 6eccd68
REPORTED
RESOLVED CLOSEDTicket created by ~jaawerth on ~technomancy/fennel
When a lambda has a metadata literal in its definition and there are assertions injected, the metadata loses its position in the body so that it's never recognized as metadata, and is instead left in the body of the function.
(macrodebug (λ foo [a ...] {:fnl/arglist [a ?b c]} (let [(b c) (if (< (select :# ...) 2) (values :B b) ...)] [a b c]))) ;; => (fn foo [a ...] ;; (_G.assert (not= nil a) "Missing argument a on unknown:1") ;; {:fnl/arglist [a ?b c]} ;; (let [(b c) (if (< (select "#" ...) 2) ;; (values :B b) ;; ...)] ;; [a b c]))When, as above, an arglist definition contains undefined syms, this leads to a compiler error
unknown:2:19 Compile error: unknown identifier: ?b
Fix is imminent; I just wanted the full bug to be documented somewhere before IP pushed it.
next-release added by ~jaawerth on ~technomancy/fennel