The Urn Logo

Version 0.2 released

It’s sometime after 11o’clock (well, it is in my timezone) which means it must be time for an Urn update!

Line mappings

We’ve finally got round to adding line mapping, which means any code executed whilst using the Urn compiler will have its positions mapped back to the original source. For instance, consider the following code:

(defun foo (x y)
(+ x y))
(defun do-bar! (x y)
(succ (foo (succ y))))
(print! (do-bar! nil 23))

When executed (lua run.lua demo/fail.lisp --run), you’ll get something like:

demo/fail.lisp:2 (out.lua:24): attempt to perform arithmetic on a nil value (local 'y')
stack traceback:
demo/fail.lisp:2 (out.lua:24): in upvalue 'foo'
demo/fail.lisp:5 (out.lua:27): in local 'do-bar!'
demo/fail.lisp:7 (out.lua:29): in main chunk

As you can see, all line numbers are converted back to their positions in the root lisp file. In addition to that, names are un-mangles, meaning you get do-bar! rather than doBar_21_1. It is worth noting that this metadata is not persisted, so running the compiled code directly will not result in mapped lines.

Benchmarking

We’ve also added a fancy benchmarking and timing library, meaning you can wrap function definitions with (time! ...) in order to time every invocation. For instance:

(time! (defun foo (bar baz)
(with (sum 0)
(for i bar baz (set! sum (+ sum i))))))

Also in this release:

  • Add for-pairs macro for easier iteration over structs.
  • Remove pair library.