~technomancy/fennel

fennel: don't modify non-string and non-nil values in compiler.traceback v1 PROPOSED

: 1
 don't modify non-string and non-nil values in compiler.traceback

 2 files changed, 26 insertions(+), 21 deletions(-)
#1300040 .build.yml success
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~technomancy/fennel/patches/54416/mbox | git am -3
Learn more about email & git

[PATCH fennel] don't modify non-string and non-nil values in compiler.traceback Export this patch

From: Andrey Listopadov <andreyorst@gmail.com>

Lua's debug.traceback entry from the manual:

If message is present but is neither a string nor nil, this function
returns message without further processing. Otherwise, it returns a
string with a traceback of the call stack. The optional message string
is appended at the beginning of the traceback. An optional level
number tells at which level to start the traceback (default is 1, the
function calling traceback).
---
 changelog.md            |  2 ++
 src/fennel/compiler.fnl | 45 ++++++++++++++++++++++-------------------
 2 files changed, 26 insertions(+), 21 deletions(-)

diff --git a/changelog.md b/changelog.md
index c3a734f..e4a331b 100644
--- a/changelog.md
+++ b/changelog.md
@@ -13,6 +13,8 @@ deprecated forms.
* `,doc`/`fennel.doc`: Don't mutate `:fnl/arglist` directly when showing callable form
* `(set (. tgt k1 ...) v)` now works on known globals and `$, $1 ... $9` in hashfns
* Macro quote expansion no longer breaks when `sym`, `list` or `sequence` is shadowed
* Bring `compiler.traceback` behavior closer to Lua's `traceback` by
  not modifying non-string and non-`nil` values.

## 1.5.0 / 2024-06-23

diff --git a/src/fennel/compiler.fnl b/src/fennel/compiler.fnl
index 7f297a7..2aed257 100644
--- a/src/fennel/compiler.fnl
+++ b/src/fennel/compiler.fnl
@@ -919,27 +919,30 @@ (fn traceback
  "A custom traceback function for Fennel that looks similar to debug.traceback.
Use with xpcall to produce fennel specific stacktraces. Skips frames from the
compiler by default; these can be re-enabled with export FENNEL_DEBUG=trace."
  (let [msg (tostring (or ?msg ""))]
    (if (and (or (msg:find "^%g+:%d+:%d+ Compile error:.*")
                 (msg:find "^%g+:%d+:%d+ Parse error:.*"))
             (not (utils.debug-on? :trace)))
        msg ; skip the trace because it's compiler internals.
        (let [lines []]
          (if (or (msg:find "^%g+:%d+:%d+ Compile error:")
                  (msg:find "^%g+:%d+:%d+ Parse error:"))
              (table.insert lines msg)
              (let [newmsg (msg:gsub "^[^:]*:%d+:%s+" "runtime error: ")]
                (table.insert lines newmsg)))
          (table.insert lines "stack traceback:")
          (var (done? level) (values false (or ?start 2)))
          ;; This would be cleaner factored out into its own recursive
          ;; function, but that would interfere with the traceback itself!
          (while (not done?)
            (match (lua-getinfo level :Sln)
              nil (set done? true)
              info (table.insert lines (traceback-frame info)))
            (set level (+ level 1)))
          (table.concat lines "\n")))))
  (case (type ?msg)
    (where (or :nil :string))
    (let [msg (or ?msg "")]
      (if (and (or (msg:find "^%g+:%d+:%d+ Compile error:.*")
                   (msg:find "^%g+:%d+:%d+ Parse error:.*"))
               (not (utils.debug-on? :trace)))
          msg        ; skip the trace because it's compiler internals.
          (let [lines []]
            (if (or (msg:find "^%g+:%d+:%d+ Compile error:")
                    (msg:find "^%g+:%d+:%d+ Parse error:"))
                (table.insert lines msg)
                (let [newmsg (msg:gsub "^[^:]*:%d+:%s+" "runtime error: ")]
                  (table.insert lines newmsg)))
            (table.insert lines "stack traceback:")
            (var (done? level) (values false (or ?start 2)))
            ;; This would be cleaner factored out into its own recursive
            ;; function, but that would interfere with the traceback itself!
            (while (not done?)
              (match (lua-getinfo level :Sln)
                nil (set done? true)
                info (table.insert lines (traceback-frame info)))
              (set level (+ level 1)))
            (table.concat lines "\n"))))
    _ ?msg))

(fn getinfo [thread-or-level ...]
  ;; if we're given a level, we have to add 1 because fennel.getinfo
-- 
2.45.0
fennel/patches/.build.yml: SUCCESS in 30s

[don't modify non-string and non-nil values in compiler.traceback][0] from [][1]

[0]: https://lists.sr.ht/~technomancy/fennel/patches/54416
[1]: mailto:andreyorst@gmail.com

✓ #1300040 SUCCESS fennel/patches/.build.yml https://builds.sr.ht/~technomancy/job/1300040
andreyorst@gmail.com writes: