SLip — a Lisp system in your browser

I've put some love into my browser-based Lisp system. This project is so old that I could actually say it's new and nobody would know. I just let it rot for something like 12 years, but since I revamped Ymacs recently, I wanted to fix the “IDE”, which was broken; and then I got carried away.

Before reading further, if you are familiar with Common Lisp and Emacs/SLIME, check out this fine REPL! There you'll also find an info file with some information about the environment. And here's the old “crazy clock demo”, which I showcased in a video when I first announced this project.

This is a Lisp implementation (Common Lisp wannabe, but oh well, we're still far from that) that runs in a JavaScript VM. See the project page for more information about existing features. Recent work includes:

I think performance is OK, for interpreted “bytecode”. It can never get on par with JS code, but a lot can be achieved by making the VM more powerful. For example, the form (pop x) used to compile to 9 instructions (consing an environment frame in between). That felt like a good opportunity to add a dedicated instruction POPLIST, which can do the job without needing a new environment frame; besides a significant reduction in the object file size, it also executes much faster simply because it's a single instruction instead of 9 (and it doesn't cons!).

I've done a similar optimization for (or ...). It was previously a macro, which used let to save the current value (because OR has to return the first non-false value). I thought I could use a VM jump instruction which jumps if the top of the stack is non-NIL, but without popping the stack — so the value would just remain available for whatever code follows, and we don't need to cons an environment frame to save it. To make it work, OR is now a special case in the compiler, rather than just a macro — but it's worth the trouble!

On the other hand, even more could be achieved by making the compiler smarter (and the cases above could partly be improved by a smarter compiler, without the need for special instructions). But I don't feel smart enough to do it 😂. Here's one pattern that occurs a lot in macros:

(defmacro foo (thing ...)
  (let ((val (gensym)))
    `(let ((,val ,thing))  ;; conses a new env frame
       ;; ... do stuff with ,val
      )))

Many times “thing” will be a constant, or a symbol (a variable defined elsewhere), so we could optimize this by using “thing” directly, instead of giving it a new local name (of course, only if it's not reassigned). My compiler currently doesn't do this. Whether it would be faster, I can't be sure without testing — variable access is expensive too, because the VM needs to look up the right environment frame; the closer it is, the faster it is. So a nested environment is not necessarily a bad thing (it does add pressure on the garbage collector though). A VM with registers might work better, but again, I don't feel smart enough for this yet.

All in all, performance is good enough for having fun, which I hope you will! Feedback would be nice — please comment here or drop me an email if you do anything interesting with this!

Get in the REPL!

3 comments. This is HOT!

Add your comment

# vindarel
2025-04-16 14:12
Absolutely outstanding!
# matt
2025-04-16 19:14
This is very cool! I love the idea of fusing a Common Lisp "wannabe" with a multimedia environment like a browser
# Qaffqa
2025-04-17 00:07
I really have to get my hands on learning Lisp more consistently ... these things are amazing!
Apr
12
2025

SLip — a Lisp system in your browser

  • Published: 2025-04-12
  • Modified: 2025-04-12 21:45
  • By: Mishoo
  • Tags: lisp, javascript, compiler
  • Comments: 3 (add)