API Reference

Funlisp Runtime

typedef struct lisp_runtime lisp_runtime

This is a context object, which tracks all language objects which have been created, and is used for garbage collection as well as holding any other information about your instance of the interpreter. The context can be created with lisp_runtime_new() and destroyed with lisp_runtime_free(). The context is passed to nearly every function in the library, and builtin functions receive it as well.

The context may contain a “user context” (simply a void pointer) that an embedding application may want its builtin functions to have access to. Context is added with lisp_runtime_set_ctx() and retrieved with lisp_runtime_get_ctx().

lisp_runtime* lisp_runtime_new(void)

Allocate and initialize a new runtime object. You must use lisp_runtime_free() to cleanup every runtime you create.

Return

new runtime

void lisp_runtime_set_ctx(lisp_runtime * rt, void * user)

Set the user context of a lisp_runtime.

Parameters
  • rt: runtime

  • user: user context to set

void* lisp_runtime_get_ctx(lisp_runtime * rt)

Get the user context from a lisp_runtime.

Return

the user context object

Parameters
  • rt: runtime

void lisp_runtime_free(lisp_runtime * rt)

Clean up all resources and free a runtime object.

Warning

This will invoke the garbage collector, freeing every language object associated with the runtime. Once calling this, ALL pointers to funlisp objects become invalid.

Parameters
  • rt: runtime to free

void lisp_enable_strcache(lisp_runtime * rt)

Enable runtime support for caching strings.

When string caching is enabled, strings created with lisp_string_new() will be looked up from a cache first, and if they already exist, a cached object will be returned. This reduces the number of unique objects and memory objects, which both improves memory utilization and garbage collection times.

Parameters
  • rt: runtime to enable string caching on

void lisp_enable_symcache(lisp_runtime * rt)

Enable runtime support for caching symbols.

When symbol caching is enabled, symbols created with lisp_symbol_new() will be looked up from a cache first, and if they already exist, a cached object will be returned. This reduces the number of unique objects and memory objects, which both improves memory utilization and garbage collection times.

Parameters
  • rt: runtime to enable symbol caching on

void lisp_disable_strcache(lisp_runtime * rt)

Disable string caching.

Parameters
  • rt: runtime to disable caching

void lisp_disable_symcache(lisp_runtime * rt)

Disable symbol caching.

Parameters
  • rt: runtime to disable caching

Lisp Values

typedef struct lisp_value lisp_value

In funlisp, (almost) everything is a lisp_value. That is, it can be cast to a lisp_value * and operated on. Integers, Strings, Code, etc. The only thing which is not a lisp_value is the lisp_runtime.

typedef struct lisp_type lisp_type

A type object is a lisp_value containing operations that must be supported by every type of object. It is not garbage collected, and every lisp_value contains a pointer to its type object (even lisp_types themselves!).

The only external use for a type object is that you can use it wih lisp_is() to type check any lisp_value. Every type named lisp_X will have a corresponding type_X object available.

See

lisp_is()

lisp_type* type_type

Type object of lisp_type, for type checking.

See

lisp_is()

void lisp_print(FILE * f, lisp_value * value)

Prints a string representing value to f. This output is not meant to contain all the information necessary to recreate value, just enough to give you an idea what it is.

Parameters
  • f: file open for writing

  • value: value to print

lisp_value* lisp_eval(lisp_runtime * rt, lisp_scope * scope, lisp_value * value)

Evaluate the lisp_value in a given context. Since lisp values represent code as well as data, this is more applicable to some data structures than others. For example, evaluating a scope will not work. However, evaluating a symbol will look it up in the current scope, and evaluating list l will attempt to call (car l) with arguments (cdr l).

When an error occurs during execution, this function returns NULL and sets the internal error details within the runtime.

Return

the result of evaluating value in scope

Parameters
  • rt: runtime associated with scope and value

  • scope: the scope to use for evaluation (used when looking up symbols)

  • value: the value to evaluate

Return Value
  • NULL: when an error occurs

lisp_value* lisp_call(lisp_runtime * rt, lisp_scope * scope, lisp_value * callable, lisp_list * arguments)

Call a callable object with a list of arguments. Many data types are not callable, in which case a NULL is returned and an error is set within the runtime.

Return

the result of calling callable with args arguments in scope scope.

Parameters
  • rt: runtime

  • scope: scope in which we are being evaluated

  • callable: value to call

  • arguments: a lisp_list containing arguments (which have not yet been evaluated)

Return Value
  • NULL: when an error occurs

int lisp_compare(lisp_value * self, lisp_value * other)

Compare two values for equality by value (not pointer). Generally this comparison should only be valid among objects of the same type.

Return

comparison result as a boolean

Parameters
  • self: value to compare with

  • other: other value

Return Value
  • 0: NOT equal

  • nonzero: equal

int lisp_is(lisp_value * value, lisp_type * type)

Perform type checking. Returns true (non-zero) when value has type type.

lisp_value *v = lisp_eval(rt, some_code, some_scope);
if (lisp_is(v, type_list)) {
    // do something based on this
}
Parameters
  • value: value to type-check

  • type: type object for the type you’re interested in

Return Value
  • true: (non-zero) if value has type type

  • false: (zero) if value is not of type type

Lisp Scopes

typedef struct lisp_scope lisp_scope

Scope objects bind lisp_symbol’s to lisp_value’s. In order for the language to function correctly, the root scope needs to contain all of the language built-in features. You can obtain a scope like this by calling lisp_new_default_scope(), or you can create an empty one with lisp_new_empty_scope().

lisp_type* type_scope

Type object of lisp_scope, for type checking.

See

lisp_is()

lisp_scope* lisp_new_default_scope(lisp_runtime * rt)

Create a new scope containing the default builtins (lambda, define, arithmetic operators, etc). This is just a shortcut for using lisp_new_empty_scope() followed by lisp_scope_populate_builtin().

Return

new default scope

Parameters
  • rt: runtime

lisp_scope* lisp_new_empty_scope(lisp_runtime * rt)

Create a new empty scope. This would be most useful when creating a new nested scope, e.g. for a function body.

Return

new empty scope

Parameters
  • rt: runtime

void lisp_scope_populate_builtins(lisp_runtime * rt, lisp_scope * scope)

Add all language defaults to a scope. This is critical for the language work, at all, since most language elements are implemented as builtin functions. This function is used internally by lisp_new_default_scope().

Parameters
  • rt: runtime

  • scope: scope to add builtins too

void lisp_scope_bind(lisp_scope * scope, lisp_symbol * symbol, lisp_value * value)

Bind a symbol to a value in a scope.

Parameters
  • scope: scope to define the name in

  • symbol: symbol that is the name

  • value: what the symbol is bound to

lisp_value* lisp_scope_lookup(lisp_runtime * rt, lisp_scope * scope, lisp_symbol * symbol)

Look up a symbol within a scope. If it is not found in this scope, look within the parent scope etc, until it is found. If it is not found at all, return NULL and set an error within the interpreter.

Return

value found, or a NULL when not found

Parameters
  • rt: runtime

  • scope: scope to look in

  • symbol: symbol to look up

lisp_value* lisp_scope_lookup_string(lisp_runtime * rt, lisp_scope * scope, char * name)

Lookup a name within a scope. Uses a string argument rather than a lisp_symbol object. Behavior is the same as lisp_scope_lookup().

Return

value found, or NULL when not found

Parameters
  • rt: runtime

  • scope: scope to look in

  • name: string name to look up

Lisp Lists

typedef struct lisp_list lisp_list

Lisp is a list-processing language, and lisp_list is a building block for lists. It is somewhat mis-named, because it actually represents a s-expression, which is just a simple data structure that has two pointers: left and right. Normal lists are a series of s-expressions, such that each node contains a pointer to data in “left”, and a pointer to the next node in “right”. S-expressions may be written in lisp like so:

> '(left . right)
(left . right)

Normal lists are simply syntactic sugar for a series of nested s-expressions:

> '(a . (b . '()))
(a b )

lisp_type* type_list

Type object of lisp_list, for type checking.

See

lisp_is()

lisp_list* lisp_list_new(lisp_runtime * rt, lisp_value * left, lisp_value * right)

Create a new list node with left and right value already specified. This interface only allows you to create lists from end to beginning.

Return

newly allocated lisp_list

Parameters
  • rt: runtime

  • left: item to go on the left side of the s-expression, usually a list item

  • right: item to go on the right side of the s-expression, usually the next lisp_list instance

lisp_list* lisp_singleton_list(lisp_runtime * rt, lisp_value * entry)

Given a lisp_value, put it inside a list of size 0 and return it.

Return

a singleton list

Parameters
  • rt: runtime

  • entry: item to put inside a list

lisp_list* lisp_list_of_strings(lisp_runtime * rt, char ** list, size_t n, int flags)

Convert the array of strings into a lisp list of string objects.

Return

lisp_list containing lisp_string objects

Parameters
  • rt: runtime

  • list: an array of strings

  • n: length of the array

  • flags: same flags passed to lisp_string_new()

int lisp_list_length(lisp_list * list)

Return the length of a list.

Return

length of the list

Parameters
  • list: list to find the length of

lisp_value* lisp_list_get_left(lisp_list * l)

Retrieve the left item of a list node / sexp.

Return

left item of list node

Parameters
  • l: list to retrieve from

void lisp_list_set_left(lisp_list * l, lisp_value * left)

Set the left item of a list node.

Warning

Lisp lists are not mutable! This should only be used during construction of lists.

Parameters
  • l: list node to set

  • left: item to set the left pointer to

lisp_value* lisp_list_get_right(lisp_list * l)

Retrieve the right item of a list node / sexp

Return

right item of list node

Parameters
  • l: list to retrieve from

void lisp_list_set_right(lisp_list * l, lisp_value * right)

Set the right item of a list node.

Warning

Lisp lists are not mutable! This should only be used during construction of lists.

Parameters
  • l: list node to set

  • right: item to set the right pointer to

void lisp_list_append(lisp_runtime * rt, lisp_list ** head, lisp_list ** tail, lisp_value * item)

Append itemto the end of a list. This routine accepts double pointers to the head and tail of a list, so that it can update them if they change.

To create a list, you can append onto nil. After that, you may continue appending onto the list. Here is a complete example:

lisp_list *head, *tail;
head = tail = lisp_nil_new(rt);
lisp_list_append(rt, &head, &tail, (lisp_value*) lisp_integer_new(rt, 1));
lisp_list_append(rt, &head, &tail, (lisp_value*) lisp_integer_new(rt, 2));
lisp_list_append(rt, &head, &tail, (lisp_value*) lisp_integer_new(rt, 3));
lisp_print(stdout, (lisp_value*) head);
// prints (1 2 3 )

Parameters
  • rt: runtime

  • head: double pointer to the first item in the list (or nil, if appending to an empty list)

  • tail: double pointer to the last non-nil item in the list (or nil, if appending to an empty list)

  • item: the value to append

lisp_value* lisp_nil_new(lisp_runtime * rt)

Return a nil instance. Nil is simply a “special” lisp_list, with left and right both set to NULL. It is used to terminate lists. For example, the list '(a b) is internally: lisp_list(a, lisp_list(b, lisp_list(NULL, NULL)))

Note

This function is named “new” for uniformity. However, it does’t actually allocate a “new” nil value every time. Instead, each lisp_runtime has a singleton nil instance, which is never garbage collected.

Return

the nil value

Parameters
  • rt: runtime

int lisp_nil_p(lisp_value * l)

Return true if the lisp_value is “nil” (an empty list).

Parameters
  • l: value to check

Return Value
  • 1: (true) if l is nil

  • 0: (false) if l is non-nil

Lisp Types

typedef struct lisp_text lisp_symbol

Symbols are tokens (non-numeric, non parentheses) which occur in funlisp code, not surounded by double quotes. For example, in the following code:

(define abs
  (lambda (x)
    (if (< x 0)
      (- 0 x)
      x)))

The symbols are: define, abs, lambda, x, if, and <.

typedef struct lisp_integer lisp_integer

lisp_integer contains an int object of whatever size the C implementation supports.

typedef struct lisp_text lisp_string

This is a string (which occurs quoted in lisp source)

typedef struct lisp_builtin lisp_builtin

This data structure contains a native C function which may be called by funlisp code. The C function must be of type lisp_builtin_func.

typedef struct lisp_lambda lisp_lambda

Data structure implementing a lisp lambda function.

typedef struct lisp_module lisp_module

Data structure representing a module.

lisp_type* type_symbol

Type object of lisp_symbol, for type checking.

See

lisp_is()

lisp_type* type_integer

Type object of lisp_integer, for type checking.

See

lisp_is()

lisp_type* type_string

Type object of lisp_string, for type checking.

See

lisp_is()

lisp_type* type_builtin

Type object of lisp_builtin, for type checking.

See

lisp_is()

lisp_type* type_lambda

Type object of lisp_lambda, for type checking.

See

lisp_is()

lisp_type* type_module

Type object of lisp_module

lisp_string* lisp_string_new(lisp_runtime * rt, char * str, int flags)

Return a new string. This function takes a “safe” approach, by copying your string and using the copy. The pointer will be owned by the interpreter and freed when the lisp_string object is garbage collected. This is roughly equivalent to duplicating the string using strdup(), and then creating a new owned string with that pointer.

Note

This is also safe to use with string literals, but it is not the most efficient way, since the string gets copied.

Return

a new lisp_string

See

LS_CPY

See

LS_OWN

Parameters
  • rt: runtime

  • str: string to copy and use in an owned string

  • flags: flags related to copying and ownership of str

char* lisp_string_get(lisp_string * s)

Return a pointer to the string contained within a lisp_string. The application must not modify or free the string.

Return

the contained string

Parameters
  • s: the lisp string to access

lisp_symbol* lisp_symbol_new(lisp_runtime * rt, char * string, int flags)

Return a new symbol. This function will copy the string and free the copy it on garbage collection (much like lisp_string_new()).

Return

the resulting symbol

See

LS_CPY

See

LS_OWN

Parameters
  • rt: runtime

  • string: the symbol to create

  • flags: flags related to copying and ownership of string

char* lisp_symbol_get(lisp_symbol * s)

Return the string contained in the symbol.

Return

the string contained in the symbol

Parameters
  • s: the symbol to retrieve the string from

lisp_integer* lisp_integer_new(lisp_runtime * rt, int n)

Create a new integer.

Return

newly allocated integer

Parameters
  • rt: runtime

  • n: the integer value

int lisp_integer_get(lisp_integer * integer)

Retrieve the integer value from a lisp_integer.

Return

the int value

Parameters

LS_CPY

Flag instructing string/symbol creation routines that they should copy the string buffer itself, and use the copy rather than the original argument. This could be useful in case callers would like to free the string after creating a lisp symbol/string from it.

Warning

If you use this without LS_OWN, you will have memory leaks, because funlisp will allocate a new string, but never free it.

See

LS_OWN

See

lisp_string_new()

LS_OWN

Flag instructing string/symbol creation routines that when the wrapper object (lisp_string/lisp_symbol) is freed, the string itself should also be freed. Put in other words, the lisp context should “own” the reference to the string.

When this is unset, we expect that the string exists for the duration of the lisp_context, and we do not free it under any circumstances. This is good for C string literals, or strings that you know you will keep around for longer than the lisp_runtime will exist.

Warning

If you unset this, but set LS_CPY, you will have memory leaks!

See

LS_CPY

See

lisp_string_new()

Builtin Functions

typedef lisp_value*(* lisp_builtin_func)(lisp_runtime *, lisp_scope *, lisp_list *, void *)

A built-in function. Takes four arguments:

  1. The lisp_runtime associated with it. This may be used to retrieved the runtime’s user context object (see lisp_runtime_get_ctx()).

  2. The lisp_scope this function is being called executed within. Most builtin functions will want to evaluate this with lisp_eval_list().

  3. The arguments to this function, as a lisp_list. These may or may not have been evaluated, depending on whether evald was set when creating the builtin object.

  4. The user context associated with this builtin.

lisp_builtin* lisp_builtin_new(lisp_runtime * rt, char * name, lisp_builtin_func call, void * user, int evald)

Create a new lisp_builtin from a function pointer, with a given name.

Warning

Namse of builtins are not garbage collected, since they are almost always static. If you need your name to be dynamically allocated, you’ll have to free it after you free the runtime.

Return

new builtin object

Parameters
  • rt: runtime

  • name: name of the builtin. the interpreter will never free the name!

  • call: function pointer of the builtin

  • user: a user context pointer which will be given to the builtin

  • evald: non-zero if arguments should be evaluated before being given to this builtin. Zero if arguments should be given as-is.

void lisp_scope_add_builtin(lisp_runtime * rt, lisp_scope * scope, char * name, lisp_builtin_func call, void * user, int evald)

Shortcut to declare a builtin function. Simply takes a function pointer and a string name, and it will internally create the lisp_builtin object with the correct name, and bind it in the given scope.

Parameters
  • rt: runtime

  • scope: scope to bind builtin in

  • name: name of builtin

  • call: function pointer defining the builtin

  • user: a user context pointer which will be given to the builtin

  • evald: non-zero if arguments should be evaluated before being given to this builtin. Zero if arguments should be given as-is.

lisp_list* lisp_eval_list(lisp_runtime * rt, lisp_scope * scope, lisp_list * list)

Given a list of arguments, evaluate each of them within a scope and return a new list containing the evaluated arguments. This is most useful for implementing builtin functions.

Return

list of evaluated function arguments

Parameters
  • rt: runtime

  • scope: scope to evaluate within

  • list: list of un-evaluated function arguments

Return Value
  • NULL: if an error occured during evaluation

lisp_value* lisp_progn(lisp_runtime * rt, lisp_scope * scope, lisp_list * l)

Given a list of lisp_value’s, evaluate each of them within a scope, returning the last value. This is similar to lisp_eval_list(), but rather than constructing a full list of results, it merely returns the last one. It is used in the progn builtin, but it also is useful for doing things like evaluating everything in a file or allowing implimenting “implicit progns”.

Parameters
  • rt: runtime

  • scope: scope

  • l: list of expressions to evaluate

int lisp_get_args(lisp_runtime * rt, lisp_list * list, char * format, ...)

Given a list of function arguments, perform type checking and verify the number of arguments according to a format string. The following formats are recognized:

d - integer
l - list
s - symbol
S - string
o - scope
e - error
b - builtin
t - type
* - anything
R - Rest of arguments

As an example, a function which takes an integer and a string, and prints the string N times, might use the format string dS.

The remaining variadic arguments are pointers to object pointers, and they will be assigned as each argument is parsed. EG:

lisp_integer *arg1;
lisp_string *arg2;
lisp_get_args(rt, args, "dS", &arg1, &arg2);

Note

The format code ‘R’ is special and deserves some more attention. When used, it immediately ends argument processing, so it should only be used at the end of a format string. It will resolve to the remaining unprocessed arguments as a list, provided that there is at least one (i.e. R will fail if the rest of the args is an empty list).

Parameters
  • rt: runtime

  • list: Argument list to type check and count

  • format: Format string

  • ...: Destination pointer to place results

Return Value
  • 1: on success (true)

  • 0: on failure (false)

Modules

lisp_module* lisp_new_module(lisp_runtime * rt, lisp_string * name, lisp_string * file)

Create a new, empty module object.

The module object represents a separate namespace which can contain symbols mapped to builtins, lambdas, constants, and more. It is a great place to store related functionality. The module can represent all of the symbols defined in a single lisp file. It can also represent a collection of resources created by C code.

C code which wishes to create a module should start here, access the scope from the resulting module using lisp_module_get_scope(), and populate the scope with any builtins or other data necessary. Finally, modules should be registered with the runtime using lisp_register_module().

Return

a new, empty module object

Parameters
  • rt: runtime

  • name: the name of the module, used for imports

  • file: filename for the module object. This file is not actually loaded, simply stored as part of the module metadata. If you would like to load a file as a module, see lisp_import_file().

lisp_scope* lisp_module_get_scope(lisp_module * module)

Given a module returned by lisp_new_module(), access its scope.

Return

the scope of that module

Parameters
  • module: A module to get the scope of

void lisp_register_module(lisp_runtime * rt, lisp_module * module)

Given a module object, register it with the runtime.

The module is mapped using the name given at creation time. For example, if a module was given the name foo, then it can be imported with the statement (import foo).

Parameters
  • rt: runtime

  • module: module to register

lisp_module* lisp_import_file(lisp_runtime * rt, lisp_string * name, lisp_string * file)

Load a file of lisp code and return it as a module object.

Return

the resulting module

Parameters
  • name: Name for the resulting module

  • file: Filename to read and load as a module

lisp_module* lisp_do_import(lisp_runtime * rt, lisp_symbol * name)

Given a module name, import and return it if possible, or raise error.

This process works as follows. First, check whether an existing module has already been registered by that name. If so, return it. Second, attempt to read ./NAME.lisp as a lisp file, and return that as a module. Raise error on failure.

Return

the resulting module

Parameters
  • rt: runtime

  • name: name of module to import

Embedding Tools

int lisp_parse_value(lisp_runtime * rt, char * input, int index, lisp_value ** output)

Parse a single expression from input, starting at index. Sets the result as a lisp_value in output. Return the number of bytes parsed from input.

When a parse error occurs, the return value is negative, and output is set to NULL. The error code and line number are set in the runtime, and may be retrieved with lisp_get_error().

When the string contains no expression (only whitespace or comments), the return value will still be non-negative. output will be set to NULL. This situation is typically not an error, either meaning empty REPL input or the end of the file you are parsing.

Return

number of bytes processed from input

Parameters
  • rt: runtime to create language objects in

  • input: string to parse

  • index: position in input to start parsing

  • output: pointer to lisp_value ** where we store the parsed expression.

Return Value
  • -1: when an error occurs during parsing

lisp_value* lisp_parse_progn(lisp_runtime * rt, char * input)

Parse every expression contained in input. Return the parsed code as a list, with the first element being the symbol progn, and the remaining elements being the parsed code. This may be evaluated using lisp_eval().

When a parse error occurs, NULL is returned. Note that parse errors typically occur after memory allocation has occurred. Memory allocated by this function is not cleaned up on error, and must be garbage collected.

Note that if the string is entirely empty, or only contains comments, then the progn will be empty, which currently causes an exception when evaluated.

Return

the code, fully parsed, within a progn block

Parameters
  • rt: runtime

  • input: string to parse

Return Value

lisp_value* lisp_parse_progn_f(lisp_runtime * rt, FILE * file)

Parse every expression contained in file, and return the parsed code as a progn block. This function behaves same as lisp_parse_progn(). Additional errors may be raised due to I/O errors on file.

Return

the code, fully parsed, within a progn block

Parameters
  • rt: runtime

  • file: file to parse

Return Value

lisp_value* lisp_load_file(lisp_runtime * rt, lisp_scope * scope, FILE * input)

Parse a file and evaluate its contents. This is roughly equivalent to:

lisp_value *progn = lisp_parse_progn_f(rt, scope, input)
lisp_eval(rt, scope, progn);
Return

the result of evaluating the last item

Parameters
  • rt: runtime

  • scope: scope to evaluate within (usually a default scope)

  • input: file to load as funlisp code

Return Value
  • NULL: on empty file, or file read error

lisp_value* lisp_run_main_if_exists(lisp_runtime * rt, lisp_scope * scope, int argc, char ** argv)

Lookup the symbol main in the scope, and run it if it exists. Calls the function with a single argument, a lisp_list of program arguments. argc and argv should not include the main executable (just the script name and args).

Return

result of evaluation

Parameters
  • rt: runtime

  • scope: scope to find main in

  • argc: number of arguments

  • argv: NULL-terminated argument list

Return Value
  • a: nil list when there is no main symbol

  • NULL: on error

void lisp_mark(lisp_runtime * rt, lisp_value * v)

Mark an object as still reachable or useful to the program (or you). This can be called several times to mark many objects. Marking objects prevents the garbage collector from freeing them. The garbage collector performs a breadth first search starting from your marked objects to find all reachable language objects. Thus, marking an object like a lisp_scope will save all symbols and language objects contained within it, from being freed. Normal use is to mark and sweep each time you’ve evaluated something:

lisp_value *result = lisp_eval(rt, scope, some_cool_code);
lisp_mark(rt, (lisp_value*) scope);
lisp_mark(rt, result);
lisp_sweep(rt);

Warning

Be explicit about marking. If we had left out the third line of the code sample above, there’s a good chance that result would have been freed when lisp_sweep() was called.

Parameters
  • rt: runtime

  • v: value to mark as still needed. This value, and all values reachable from it, are preserved on the next lisp_sweep() call.

void lisp_sweep(lisp_runtime * rt)

Free every object associated with the runtime, which is not marked or reachable from a marked object.

Parameters
  • rt: runtime

lisp_list* lisp_quote(lisp_runtime * rt, lisp_value * value)

Return value, but inside a list containing the symbol quote. When this evaluated, it will return its contents (value) un-evaluated.

This function is used during parsing, to implement the single-quote syntax feature. For example '(a b c), evaluates to the list containing a, b, and c, rather than calling a on b and c. This is because the expression is transparently converted to the more verbose (quote (a b c)).

Return

value but quoted

Parameters
  • rt: runtime

  • value: value to return quoted

Error Handling

error::lisp_errno

Values:

1
LE_EOF
LE_SYNTAX
LE_FERROR
LE_2MANY
LE_2FEW
LE_TYPE
LE_NOCALL
LE_NOEVAL
LE_NOTFOUND
LE_EXIT
LE_ASSERT
LE_VALUE
LE_ERRNO
LE_MAX_ERR
const char* lisp_error_name[LE_MAX_ERR]
const char* const lisp_version
lisp_value* lisp_error(lisp_runtime * rt, enum lisp_errno err_num, char * message)

Raise an error in the interpreter and return NULL.

This function is meant to be used within code that implements builtins. When an error condition is reached, functions may simply do something like this:

if (some_error_condition())
    return lisp_error(rt, LE_ERROR, "you broke something");

Return

NULL

Parameters
  • rt: runtime

  • err_num: error number, for easy programatic acccess

  • message: message to show the user

void lisp_dump_stack(lisp_runtime * rt, lisp_list * stack, FILE * file)

Dump the execution stack to a file. This is useful if you want to print a stack trace at your current location. This functionality can also be accessed via the dump-stack builtin function.

Parameters
  • rt: runtime

  • stack: When NULL, the runtime’s execution stack is used. When non-NULL, the stack argument is used to specify what stack to dump.

  • file: where to dump stack trace to

void lisp_print_error(lisp_runtime * rt, FILE * file)

Prints the last error reported to the runtime, on file. If there is no error, this prints a loud BUG message to FILE, indicating that an error was expected but not found.

Parameters
  • rt: runtime

  • file: file to print error to (usually stderr)

char* lisp_get_error(lisp_runtime * rt)

Returns the error text of the current error registered with the runtime.

Return

error string

Parameters
  • rt: runtime

enum lisp_errno lisp_get_errno(lisp_runtime * rt)

Returns the error number of the current error registered with the runtime.

Return

error number

Parameters
  • rt: runtime

void lisp_clear_error(lisp_runtime * rt)

Clears the error in the runtime.

Parameters
  • rt: runtime

lisp_error_check(value)

A macro for error checking the return value of a lisp_eval() or lisp_call() function. This will return NULL when its argumnet is NULL, helping functions short-circuit in the case of an error.

lisp_value *v = lisp_eval(rt, my_code, my_scope);
lisp_error_check(v);
// continue using v

Parameters
  • value: value to error check