A month of work on Lunula

It has been exactly one month since I posted but I have a good excuse this time: I have finished a couple of major milestones for Lunula.  The first was the release of version 0.2.1, which includes an evaluator and a read-eval-print-loop (REPL).

The REPL is a very important feature of any lisp system, allowing you to do incremental development by running arbitrary test code on a live system.  Lunula’s evaluator is metacircular, which means it is written in Lunula and can evaluate itself.

Having the REPL gave me a significant boost in productivity.  A compiler and an evaluator gives me a staging environment to work with.  I can test out new code with the evaluator and once it is solid, compile it and integrate it into the system.  This helps with the bootstrapping problem I had before when I only had a compiler.  Any change to the language required me to compile the change with an old compiler, then compile again/run unit tests to make sure I didn’t break anything. With the REPL I can be fairly confident that I didn’t break anything if it evaluates correctly and I can do a lot more work before having to compile the compiler again.

One of the cool things about the metacircular evaluator is it inherits many of the features of the host language.  For example, since Lunula’s compiler supports tail-call optimization (TCO), the evaluator written in Lunula gets support for TCO for free.   I came to this realization when I started writing the evaluator, thinking that I would have to use trampolines there too.   I even wrote a version of the evaluator with trampolines after I got a stack-overflow when running my unit tests.  Later found that it was a bug in my ‘let’ form.  I removed the trampolines and voilà,  the unit tests run and I get TCO for free!

The second milestone was adding the ability for Lunula to compile loadable modules (dll’s) and stand-alone executables.   For example, you can do this to compile a lunula source file and load it into the running system:

> (load (compile-file "hello-world.lun")) ; compiles hello-world.lun to a dll, then loads it.

-or-

> (load "another-module.dll") ; loads a module created at some other time

Supporting modules required me to do some major reorganization of the way the compiler was outputting code.  What I ended up doing was generating a LunulaModule class which contains the compiled representation of all of the code in a single .lun source file.  A LunulaModule has an Init() method which loads the toplevel forms in the module into the running system’s toplevel.   Compiling to an EXE was easy after writing the code for DLLs.  You can do this to compile a stand-alone EXE:

> (compile-file-to-exe "hello-world.lun") ; creates hello-world.exe 

 
For Silverlight and XNA I still support compiling directly to C# source so you can include those in a Visual Studio project.  The module compiler wont run in Silverlight or XNA at all, so any code added at runtime has to use the evaluator.  This is kind-of cool because it gives you a way to run arbitrary code at runtime (there may be a good reason to do this), which C# does not allow you to do on these platforms.

I think the next step is macros for sure.  Module support was a big unknown so I thought I’d get it out of the way before finishing macros. After that, maybe dynamic variables.

Advertisement

One Response to A month of work on Lunula

  1. びっくり says:

    Glad you are posting again. I hope you find more things worthy of your blog so we can read them.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.