The Urn Logo

Latest posts

Version 0.2.6 released

Another update. This time, we’ve started adding some much needed features to the standard library. Here are a couple of highlights:

handler-case

handler-case could be thought of a pumped-up try-catch statement. It executes the body like normal, but if you hit an error it will attempt to pattern match against it, meaning you can handle a whole different host of error types:

(handler-case
  (error! "oh-no")
  [(as string? ?x) (print! x)])

use

I’m sure you’ve had that time where you’ve forgotten to close a stray file handle, and not been able to delete it without rebooting your (ComputerCraft) computer? use takes care of that, ensuring every object is closed when the block exits.

(use [(file (io/open "temp")]
  (print! (self file :read "a")))

setf! and over!

setf! and over! provide a uniform way of modifying values. setf! takes a value to modify and sets the given value to it. over! takes a value, applies the given function, and stores it back where it came from. The real advantage of these is that they work on a whole host of different things: symbols, lists indexes, table keys, etc… This means it is simple to create macros which work on a whole range of values. For instance, you could declare the +=* operator as something like:

(defmacro += (selector val) `(over! ,selector (lambda (,'x) (+ ,'x ,val))))

then use it on values, lists, etc…

(+= foo 2)
(+= (nth bar 2) 3)
(+= (.> baz :qux :quux) 4)

Do note, this will ensure you don’t index a variable more than once, meaning the last example gets compiled to something like:

local temp = baz.qux
temp.quux = baz.quux + 4

*Don’t actually call it this, it isn’t very ‘lispy’ a name.

Version 0.2.5 released

Again, just a minor update to Urn, though with some pretty nifty features and improvements. Once again we’ve got some additional performance improvements - this shaves 0.2-0.3 seconds off the compile time of the main compiler, equating to ~7% faster.

In order to improve the efficiency of Urn, we’ve added a couple of different profiling modes to Urn. The first one monitors function calls, producing a table of how long is spent inside each function. The second profiler simply samples the call stack every 10k instructions. All call stacks are then merged together and printed to the terminal. What is especially useful is the ability to “invert” the trace, seeing what functions call a particular function instead.

There is also the ability to output text suitable for consumption with the FlameGraph tool, allowing you to generate graphics like this:

For reference, this was generated with tacky/cli.lua --profiler --stack-fold --stack-kind=flame --stack-limit=50 urn/cli -- urn/cli | perl flamegraph.pl > out.svg. This simply profiles how long the compiler takes to compile itself. For more information about the options which can be used with the profiler, run tacky.cli --help.

Version 0.2.4 released

Another update to Urn, though just a minor one. We’ve been hard at work improving the speed of Urn, using faster algorithms and generating better code. Due to a couple of nifty changes and optimisations, the Urn compiler is somewhere between 30% and 50% faster.

For instance, building the entire Urn compiler (with inlining enabled) took about 3.8 seconds on the last release, but now takes 2.4 seconds. It’s worth noting that the Urn compiler is rather large by Lua standards (7k LOC - even Howl has less than that): most of your programs will compile well within a second, even with all optimisations turned on.

Version 0.2.3 released

As the clock strikes 12, it’s update time. Firstly, another big shout out to CrazedProgrammer and Lignum for PRs they’ve sent. Thanks to them Urn is better tested and has even more features.

Now onto the changes. This update, much like the Musketeers, comes in three parts:

REPL

The REPL is great for testing and experimenting with Urn. In this update, we’ve added some new features to make it even easier to use:

  • Add :search command to find symbols and documentation matching a given pattern.
  • Add a magic value out, assigned to the value of the last expression.

Libraries

The standard library is growing day by day with new functionality to make life easier. In this update:

  • Add drop and take for making slices of lists
  • Add keys and values for accessing structs.
  • Export string and math libraries by default.
  • Add many more tests for the stdlib

Code generation and optimisation

One of the big problems with Urn currently is that the generated code is rather ugly. Most of it isn’t any less efficient than normal Lua, just significantly more verbose than desired. Thankfully, we’re beginning to take steps to improve code generation. The backend can now recognise branches which could be compiled to and, or or not and emit the appropriate Lua.

We’ve also added function inlining, meaning that simple helper functions will be removed, removing the overhead of function calls. You can see the effect of that here.

  • Add a inlining optimisation pass (disabled by default, enable with -O+inline).
  • Add a new codegen system, with support for not, and and or.
  • Simplify trivial lamda expressions
  • Correctly pack arguments in directly called lambdas
  • Don’t constant fold functions which returned multiple values.
  • Fix code generation issues when calling quoted lists, or expressions involving quoted lists.
  • General performance improvements to the optimiser.

Version 0.2.2 released

It’s update time and oh boy: what an update!

New CLI

First off, in our slow quest to make the Urn compiler self-hosting we’ve ported the Urn command line interface to Urn. However, this wasn’t just a boring old line-for-line port, the rewrite comes with a whole host of new options:

It uses Urn’s new argument parser library meaning it can handle all standard argument formats, as well as providing more informative help messages. This new CLI also offers finer control: allowing you to disable specific optimisations, add shebangs to your files, automatically set the executable bit, etc…

Contributions from other people

I’d like to say a big thanks to CrazedProgrammer and Lignum. CrazedProgrammer has sent a couple of PRs in, adding a fancy io library for file manipulation, as well as several additions to the string library. Lignum has put together a bindings for ComputerCraft, meaning you can use your favourite APIs inside Urn. Check out the repo for more information and installation instructions.

Other improvements

  • Add optional and type patterns to the pattern matcher.
  • Format bold and italic documentation in the REPL.
  • Add more granular system to monitor and control optimisation and analysis passes.
  • Optimise the optimiser.