elisp.js icon indicating copy to clipboard operation
elisp.js copied to clipboard

Emacs Lisp interpreter in JavaScript

Emacs Lisp implementation in JavaScript.

Copyright (c) 2009 Sami Samhuri - [email protected]

Released under the terms of the MIT license. See the included file LICENSE.

Latest version available on github:

http://github.com/samsonjs/elisp.js


  Introduction

(or "You must be kidding")

The idea of editing code directly on github or bitbucket in a web browser is pretty cool, and if you're going to do such a thing why not use the best tools available? IMO those tools are written in Emacs Lisp so I would like to use them in the browser. Maybe with some HTML5 offline goodness thrown in.

Seeing Ymacs[1] in action[2] was also an inspiration to start this project as I've had it on my TODO list for several months now. Emacs in the browser could be a reality; Ymacs is proof.

With Palm's release of "Project Ares"[3] the need for such tools is beginning to be a reality. I'm no longer that uncertain why such a beast would be useful. The question now is whether using something like Google's Native Client and original C version of Emacs is the way to go, or if a slower implementation in JavaScript is feasible for real use.

[1] http://www.ymacs.org/ [2] http://www.ymacs.org/demo/ [3] http://pdnblog.palm.com/2009/12/project-ares-open-beta/ [4] http://code.google.com/p/nativeclient/

Getting Started

I'm currently using CommonJS via Narwhal[1] with the JavaScriptCore engine. I've run the tests under v8 as well and they all pass, but not everything is tested by any means.

[1] http://narwhaljs.org/

If you have rlwrap and narwhal then just run elisp.sh. If not install a JavaScript shell of your choice, and I recommend you install rlwrap (readline wrap). Edit elisp.sh to reflect whether or not you use rlwrap and your shell's name or path, and then run elisp.sh.

Type a 'Q' or 'q' to quit the repl. Or anything that starts with Q, like 'quickly quit lisp!'. (If lisp freaks out because you entered ^D or something ^C or ^Z should still get you out.)

Here's an example:

% cd Projects/elisp.js % ./elisp.sh elisp> (defvar directory "/Users/sjs" "My home directory") nil elisp> directory "/Users/sjs" elisp> (setq foo 1 bar 2 baz 3) 3 elisp> (/ (+ foo bar baz) 3) 2 elisp> (string-match "[a-z]lurgh" (symbol-name 'foo-blurgh)) 4 elisp> q %

(If you know how to print without a trailing newline in JavaScript please let me know.)

There are other interfaces into the parser and evaluator besides the shortcuts. new elisp.parser.Parser([input]) returns a parser object and likewise new elisp.evaluator.Evaluator([exprs]) returns an evaluator object.

Mainly toy functions that do extremely simple operations on numbers and strings can be implemented right now. Stay tuned, or better yet hack away and submit a pull request on github.

What's here?

Not much compared to the real thing but it's a decent start for 1500 lines.

  • parser/reader. there's no lexing to tokens we go straight to tagged data. (ints, floats, strings, symbols, lists, quoted expressions)

  • symbol table, but needs to be replaced ASAP. (functions & variables separate)

  • (broken) lexical scoping

  • expression evaluator

  • primitive types (string, symbol, lambda, number, cons)

  • special forms for defvar, defun, set, setq, if, and quote

  • eval/apply for atoms, function calls, and a few special forms

  • a few primitive math ops (thanks to JS' overloading + works on strings too)