~andreyorst

Moscow

https://andreyorst.gitlab.io/

I love Lisp and text editors!


#103 Improve relative require 12 days ago

Comment by ~andreyorst on ~technomancy/fennel

From https://github.com/bakpakin/Fennel/pull/423:

(macro rel-path [module from-macro?]
  `(.. (or (: (or ... "") :match "(.+%.)[^.]+")
           (if (= ... ,(if from-macro? "init-macros" "init"))
               ""
               (.. ... ".")))
       ,module))

This macro should cover most common cases for relative require from regular modules and macro modules.

#114 Taking remainder with zero fails silently in the REPL a month ago

Ticket created by ~andreyorst on ~technomancy/fennel

Here's a visual example: https://asciinema.org/a/va75Trg0KyJDj9KRI37OcURfd

And here's the same as the REPL output:

Welcome to Fennel 1.0.1-dev on PUC Lua 5.4!
Use ,help to see available commands.
Try installing readline via luarocks for a better repl experience.
>> (% 2 0)
>> (do (% 2 0) 1)
runtime error: attempt to perform 'n%0'
stack traceback:
  [string "do local _ = (2 % 0) end..."]:1: in main chunk
  /home/alist/.local/bin/fennel:780: in function ?
  [C]: in function 'xpcall'
  /home/alist/.local/bin/fennel:788: in function ?
  /home/alist/.local/bin/fennel:5836: in function ?
  [C]: in ?

Bisecting showed that the first bad commit is 04cc99ffe933cd4db920531639e77e365840ddc6

#113 compile-time arglist docstring overload 2 months ago

Ticket created by ~andreyorst on ~technomancy/fennel

It's possible to set the docstring metadata of a function at compile time, by putting a string literal as the first expression after the arglist, however it's impossible to do the same with the arglist metadata.

For documentation automation purposes, and (editor) discoverability it'd be great if the arglist could be altered without loading fennel compiler at runtime and calling fennel.metadata:set. Here are some cases for it:

  • Functions that have heavy use of destructuring.
    A result of the .doc command doesn't have to contain all this information, cluttering the docstring, instead a clear names can be provided to arguments, like often done with &as. E.g. a function definition like this: (fn foo [{: some : heavy :destrutcturing [going here] &as arg-name}] "foo is a foo" nil) is displayed as:
    >> ,doc foo
      (foo {&as arg-name :destrutcturing [going here] :some some :heavy heavy})
      foo is a foo
    
    Instead if we could override the arglist, we could keep the destructuring in the definition, but for the arglist just say that it's just arg-name. Alternativel, such destructuring can be analyzed and &as name would be picked by the compiler automatically, but this is not always the desired behavior, I believe.
  • all-variadic functions.
    Functions that are defined with only the [...] arglist and then match on it somehow, convey nothing of what they're accepting. Altering such arglist can make documentation more clear.
  • Library case.
    My fennel-cljlib library implements the fn* macro, which has different notion of arglist, and to actually display it in the ,doc command I have to make this macro to check if metadata is enabled and require fennel at runtime to call fennel.metadata:set so the correct arglist representation could be set to the function. This also makes it problematic, since to set a metadata we have to have a function's name, and thus wrap everything in a let binding, preventing some conventional patters, like returning a function from a file.

This can be done if the fn special could accept a table in-place of the docstring, which would have the same syntax for metadata keys as accepted by fennel.metadata:set:

(fn add [...]
  {:fnl/arglist ["a" "b" "& rest"]
   :fnl/docstring "adds arbitrary amount of numbers"}
  (match (select :# ...) 0 0 1 ...))

As with docstring, if nothing follows the table, it gets returned, so it shouldn't be a problem.

#112 doc command crashes the REPL 2 months ago

Ticket created by ~andreyorst on ~technomancy/fennel

trying to access unknown global crashes the REPL:

Welcome to Fennel 1.0.1-dev on PUC Lua 5.4!
Use ,help to see available commands.
Try installing readline via luarocks for a better repl experience.
>> ,doc fennel
fennel not found
>> ,doc fennel.metadata
lua: [string "return fennel.metadata"]:1: attempt to index a nil value (global 'fennel')
stack traceback:
        [string "return fennel.metadata"]:1: in main chunk
        (...tail calls...)
        /home/alist/.local/bin/fennel:614: in function </home/alist/.local/bin/fennel:612>
        (...tail calls...)
        /home/alist/.local/bin/fennel:639: in function </home/alist/.local/bin/fennel:633>
        (...tail calls...)
        /home/alist/.local/bin/fennel:5710: in function </home/alist/.local/bin/fennel:5697>
        (...tail calls...)
        [C]: in ?

Trying to get documentation for a method call also crashes the REPL:

Welcome to Fennel 1.0.1-dev on PUC Lua 5.4!
Use ,help to see available commands.
Try installing readline via luarocks for a better repl experience.
>> (local fennel (require :fennel))
nil
>> ,doc fennel.metadata.get
(fennel.metadata.get #<unknown-arguments>)
  #<undocumented>
>> ,doc fennel.metadata:get
lua: Compile error in unknown:1
  multisym method calls may only be in call position

* Try using a period instead of a colon to reference a table's fields.
* Try putting parens around this.
stack traceback:
        [C]: in function 'error'
        /home/alist/.local/bin/fennel:3406: in function 'fennel.friend.assert-compile'
        /home/alist/.local/bin/fennel:2250: in function 'fennel.compiler.assert'
        /home/alist/.local/bin/fennel:2797: in function </home/alist/.local/bin/fennel:2795>
        (...tail calls...)
        /home/alist/.local/bin/fennel:3111: in function 'fennel.compiler.compile-stream'
        (...tail calls...)
        /home/alist/.local/bin/fennel:558: in upvalue 'resolve'
        /home/alist/.local/bin/fennel:614: in function </home/alist/.local/bin/fennel:612>
        (...tail calls...)
        /home/alist/.local/bin/fennel:639: in function </home/alist/.local/bin/fennel:633>
        (...tail calls...)
        /home/alist/.local/bin/fennel:5710: in function </home/alist/.local/bin/fennel:5697>
        (...tail calls...)
        [C]: in ?

#111 Missing IIFE in or and and specials 3 months ago

Ticket created by ~andreyorst on ~technomancy/fennel

Submitting the bug from IRC channel so it won't be left out.

(or true (tset _G :foo :bar))
(and false (set _G.foo :bar))

The code above compiles to the following lua:

_G["foo"] = "bar"
do local _ = (true or nil) end
_G.foo = "bar"
return (false and nil)

Wrapping set and tset in a do block fixes the compilation:

(or true (do (tset _G :foo :bar)))
(and false (do (set _G.foo :bar)))

Side effects are correctly deferred:

local function _1_(...)
  _G["foo"] = "bar"
  return nil
end
do local _ = (true or _1_(...)) end
local function _2_(...)
  _G.foo = "bar"
  return nil
end
return (false and _2_(...))

This raises a question if or and and should be implemented with macros that expand to if as done in Clojure and Common Lisp:

(macro or* [x ...]
  (if (= (select :# ...) 0)
      x
      `(let [or# ,x]
         (if or# or# (or* ,...)))))

(macro and* [...]
  (let [nargs (select :# ...)]
    (if (= nargs 0)
        true
        (= nargs 1) ...
        (let [(first) ...]
          `(let [and# ,first]
             (if and#
                 (and* ,(select 2 ...))
                 and#))))))

(or* true (tset _G :foo :bar))
(and* false (set _G.foo :bar))

No IIFE needed in this case:

do
  local or_2_auto = true
  if or_2_auto then
  else
    _G["foo"] = "bar"
  end
end
local and_2_auto = false
if and_2_auto then
  _G.foo = "bar"
  return nil
else
  return and_2_auto
end

The if itself may be transformed to IIFE to perform correct return in case of multiple values, but this should be well tested.

#101 Mangling affects strict global checking in REPL 6 months ago

Comment by ~andreyorst on ~technomancy/fennel

However, the first one should not work at all; it looks like somehow strict globals checking stopped working in the repl.

I agree. This was fixed in a11d3658

REPORTED RESOLVED FIXED

#101 Mangling affects strict global checking in REPL 6 months ago

Ticket created by ~andreyorst on ~technomancy/fennel

I'm not sure how exactly this should work but the current behavior is probably inaccurate:

Welcome to Fennel 1.0.0-dev on Lua 5.4!
Use ,help to see available commands.
Try installing readline via luarocks for a better repl experience.
>> (tset _G :foo (fn [] (print :foo)))
nil
>> (foo)
foo
>> (tset _G :foo-bar (fn [] (print :foo-bar)))
nil
>> (foo-bar)
runtime error: global '__fnl_global__foo_2dbar' is not callable (a nil value)
stack traceback: ...

#99 compiler special to detect vararg in current scope 6 months ago

Comment by ~andreyorst on ~technomancy/fennel

That's even better

#99 compiler special to detect vararg in current scope 6 months ago

Comment by ~andreyorst on ~technomancy/fennel

thanks! Really glad that we have it before 1.0.0. as I'm planning on making 1.0.0 mandatory for most of the libs when in will be out.

#97 short circuiting bug with (do) 6 months ago

Comment by ~andreyorst on ~technomancy/fennel

the opts.nval value is equal to 1 in cases like (and (do 42) false), and the branching is done depending if nval is set https://git.sr.ht/~technomancy/fennel/tree/main/item/src/fennel/specials.fnl#L121-131