====== MiniLisp ======
{{lambda.jpg?150 }}
Many years working with [[lush|Lush]] have taken their toll.
There are many things I really dislike doing in C or C++
when I know how easy they would be in Lisp.
The essential lisp data structure is called the S-Expression.
S-Expressions can represent lots of complicated things
using a simple printable format. These are the main
reason why many people find XML or JSON appealing.
But I keep returning to S-Expression because they are so much simpler.
===== MiniExp =====
At some point I decided to simply write a C++ library
to handle the basic lisp data structure: [[wp>S-expressions]].
The implementation fits in a single C++ file,
including a garbage collector and a pretty printer.
The full documentation is available as comments in
the header file ''miniexp.h''
MiniExp handles four basic types of S-expressions:
* Integers, in range [-229...229-1].
* Symbols, which are small strings represented by a unique handle.
* Pairs, which are the basic components of lists.
* Objects, which encapsulate any C++ object derived from class ''miniobj_t''
Examples:
minivar_t a_symbol = miniexp_symbol("foo");
minivar_t a_number = miniexp_number(23);
minivar_t a_list = miniexp_cons(a_symbol, miniexp_cons(a_number, miniexp_nil));
minivar_t an_object = miniexp_string("Strings are implemented as objects.");
The type of the S-expression is ''miniexp_t''.
But we often store them into variables of type ''minivar_t''.
The difference is garbage collection.
The garbage collector preserves all S-expressions stored in a ''minivar_t''
and all S-expressions recursively pointed by preserved S-expresssions.
To print a S-expression, one could write something like:
if (miniexp_numberp(exp))
printf("%d", miniexp_to_int(exp));
else if (miniexp_symbolp(exp))
printf("%s", miniexp_to_name(exp));
else if (miniexp_consp(exp))
....
But there is an easier way:
miniexp_print(exp);
and a prettier way:
miniexp_pprint(exp, 72); // 72 is the target number of columns
You can also read S-expressions from the standard input
minivar_t exp = miniexp_read();
See the documentation in file ''miniexp.h'' for more details.
===== MiniLisp =====
During the development of ''miniexp.h'' and ''miniexp.cpp'', it
appeared that the best way to test s-expressions was to make
the last step and program a complete lisp interpreter.
Let's see what it can do:
MiniLisp, (C) 2005, Leon Bottou.
Available under the GNU General Public Licence.
(+ 2 3)
= 5
(defun (square x) (* x x))
= square
(square (+ 2 3))
= 25
(defun (sum l) (if (consp l) (+ (car l) (sum (cdr l))) 0))
= sum
(sum '(1 8 7 3))
= 19
(pretty sum)
(defun (sum l) (if (consp l) (+ (car l) (sum (cdr l))) 0))
= ()
(pretty pretty)
(defmacro (pretty f)
(let ((s (if (symbolp f) (list (list quote f)))))
(list (quote let)
(list (list (quote s) (list (quote funcdef) f . s)))
(list (quote pprint) (quote s) 72)
() ) ) )
= ()
The interpreter is very slow because symbol lookup is not optimized.
But it makes a nice example of using MiniExp.
===== Download =====
The most recent MiniExp source code is available from the DjVu Git repository.
* [[http://sourceforge.net/p/djvu/djvulibre-git/ci/master/tree/libdjvu/miniexp.h|miniexp.h]]
* [[http://sourceforge.net/p/djvu/djvulibre-git/ci/master/tree/libdjvu/miniexp.cpp|miniexp.cpp]]
The documentation is in file ''miniexp.h''.
You can also check the MiniLisp source:
* [[http://sourceforge.net/p/djvu/djvulibre-git/ci/master/tree/doc/minilisp/|minilisp (tree)]]