Lisp Library

The Lisp Library feature allows you to extend uLisp with your own library of functions written in Lisp. They are stored as text in flash memory along with the uLisp code, and get loaded when you run uLisp.

Note that this is separate from save-image and load-image, which use the processor's EEPROM or an SD card. The Lisp Library can be used even on platforms with no EEPROM or SD card, where save-image and load-image are not available. Where they are available you can still use them to save a snapshot of your workspace without affecting the Lisp Library.

Introduction

For example, suppose you would like your uLisp environment to include these square and cube functions:

(defun sq (x) (* x x))
(defun cube (x) (* x x x))

You can define these as a Lisp Library by adding the following definition to your uLisp source:

const char LispLibrary[] PROGMEM =
"(defun sq (x) (* x x))"
"(defun cube (x) (* x x x))";

One way is to paste these lines at the beginning of the uLisp source file.

Then, to enable the Lisp Library feature you need to uncomment the #define:

#define lisplibrary

Alternatively, you can keep your Lisp Library definitions separate from the uLisp source code by creating a separate LispLibrary.h file in the same Arduino project folder as the uLisp source file, and put the definition in that. You then need to add a reference to it in the main source file by uncommenting the line:

#include "LispLibrary.h"

Direct commands

You can include a direct call to a function to run a program when the processor is reset.

For example, defining the following Lisp Library:

const char LispLibrary[] PROGMEM =
"(defun b (x) (pinmode 13 t) (digitalwrite 13 x) (delay 1000) (b (not x)))"
"(b t)";

will cause the program to run and blink the LED when the processor is reset.

Listing programs

A convenient way to create a Lisp Library is as follows:

  • Define the functions you want to include in the Lisp Library, and test them from the Serial Monitor.
  • List the functions in the workspace with the command:
(pprintall)
  • Select the listings from the Serial Monitor window and paste them into the source window.
  • Add the line:
const char LispLibrary[] PROGMEM =
  • Add the double quotes at the start and end of each line, and a final semicolon.
  • Escape double quotes in your source, where necessary, as described in the next section.

Quoting and escapes

Due to the string conventions in C each line must start and end with a double-quote, as in the above example.

Also, any double quotes in your Lisp source must be escaped with a backslash. So for example, to include the following function in the Lisp Library:

(defun error (string) (princ "Error:") (princ string) (terpri))

you would need to enter it as:

"(defun error (string) (princ \"Error:\") (princ string) (terpri))"

Backslashes in your uLisp program need to be escaped with an extra backslash, so to include the following program:

(defun wow () (print "She said \"Wow!\""))

it will need to be:

"(defun wow () (print \"She said \\\"Wow!\\\"\"))"