The best kittens, technology, and video games blog in the world.

Sunday, July 23, 2006

RLisp - Lisp naturally embedded in Ruby

I just wrote a Lisp interpretter embedded in Ruby. I used ANTLR 3.0ea7 for parsing (it's alpha-quality software, unfortunately).

$ cat examples/fib.rl
(defun fib (n)
(if (<= n 1)
(+ (fib (- n 1)) (fib (- n 2)))
(map fib '(1 2 3 4 5))
$ ./rlisp.rb <examples/fib.rl
#<lambda:0 ...>
(1 2 3 5 8)
The dialect is supposed to be vaguely based on Scheme, but the idea was for it to be naturally embedded in Ruby, so many thing had to be changed compared to Scheme:
  • send function for method calls: (send 2 '+ 2) and syntactic sugar for it [obj method arguments], which evaluates to (obj 'method arguments). So it's possible to write [2 + [3 * 4]], what expands to (send 2 '+ (send 3 '* 4)). The syntax was stolen from Objective C.
  • lists are implemented as arrays. So no cons, car or cdr. Now of course we need some replacement, and I haven't really thought about it. You can send get/set method to Array object, like that ('(a b c) set 0 'd) (or ['(a b c) get 0]).
Things that would be required before RLisp is usable (even as a funky toy):
  • macro system - doh, that's the point of the whole thing
  • links to Ruby object system, so we can define classes, methods etc.
  • some support for iterators, I have no idea what syntax to select for iterators (send-with-iterator '(1 2 3) 'each (lambda (i) (print i))) would probably do the trick, but it's kinda uglyish.
  • support for other basic Ruby objects like hash tables, regular expressions etc. Most of them need little more than (let a (send Hash 'new)), but some might not be very usable in such form.
  • exception handling and callcc support would be cool
Oh, and it uses dynamic binding like Emacs Lisp instead of lexical like Scheme/Common Lisp, because it was much easier to do ;-). It should probably be fixed later.

My box on which the code repository is located is behind a nasty nat, so just mail me if you want the code. :-)


evan said...

I'd be happy to host it for you, either static, or in a subversion repository, if that would be better.

evan said...

Nevermind, I see that you found a host. But still...

taw said...

At the moment I have stuff on 5 different hosts. If you were willing to host everything (jrpg, rlisp, and whatever else I make up) on some nice host, that would be nice. Otherwise, I'll check which of the 5 is the nicest and move everything there. :-)

Notheory said...

A friend and ruby fantatic just linked me to your post, and i would like to say, i have always dreamed of being able to write lisp code, and still interact with things like the Rails action pack.

I had naively contemplated whether a set of Lisp wrappers could be written for the action pack, but this, if completed would probably be even more effective.

Keep it up! i'd love to see more :D

taw said...

Well, new version was just released, and you can even get a free beer for writing cool RLisp programs :-D

linker said...

May I ask you a question?

Why embedding Lisp in Ruby? You know, there's half a dozen of mature Common Lisp implementations out there.

taw said...

linker: There is no such thing as "mature CL implementation", and I wanted Lisp with a decent object oriented system.