Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

lib/lisp/lisp.x

The Lisp runtime: reader, session, and evaluator.

Primary API

FunctionSummary
lisp_carReturns the first element of value, or void when it is nil.
lisp_cdrReturns the tail of value, or nil when it is nil.
lisp_match_replaceReturns the instantiated template when input matches pat.
lisp_string_lstripTrims leading bytes, accepting the same charset values as strip.
lisp_string_rstripTrims trailing bytes, accepting the same charset values as strip.
lisp_string_stripTrims the bytes in chars, using whitespace for an empty String.
lisp_truthReturns Lisp true for every value except nil and void.
native_scalar_accessReturns the access record for an exact C scalar type such as (unsigned long), or NULL for any other type.
Lisp.adoptMakes lisp read parent’s definitions for names it does not bind.
Lisp.applyApplies callable to already evaluated values.
Lisp.bindInstalls function as name and transfers its storage to lisp.
Lisp.call_budgetSets how many calls one evaluation of lisp may make before it is stopped.
Lisp.evalEvaluates one Lisp form in lisp.
Lisp.eval_fileReads and evaluates every form from source.
Lisp.eval_stringReads and evaluates every form in source.
Lisp.freezeMarks lisp complete, so nothing produced later may reach it.
Lisp.kernelCreates an isolated embedded Lisp session with only evaluator primitives.
Lisp.newCreates an isolated session with the standard Lisp environment loaded.
Lisp.set_interruptedSets whether evaluation in lisp is interrupted.
Lisp.try_getWrites the global binding for name to out when present.

Functions

lisp_car

Var lisp_car(Var value)

Returns the first element of value, or void when it is nil. A nonlist operand raises <bad-types>.

Source: lib/lisp/primitives.x:26

lisp_cdr

Var lisp_cdr(Var value)

Returns the tail of value, or nil when it is nil. A nonlist operand raises <bad-types>.

Source: lib/lisp/primitives.x:35

lisp_match_replace

Var lisp_match_replace(List input, Var pat, Var template)

Returns the instantiated template when input matches pat. List.match_replace returns a List, so a template that is a bare binder loses a scalar result. Lisp sees the replacement itself. A miss, malformed pattern, cache pressure, or machine error returns input unchanged.

Source: lib/lisp/primitives.x:246

lisp_string_lstrip

String lisp_string_lstrip(String string, Var chars)

Trims leading bytes, accepting the same charset values as strip.

Source: lib/lisp/primitives.x:234

lisp_string_rstrip

String lisp_string_rstrip(String string, Var chars)

Trims trailing bytes, accepting the same charset values as strip.

Source: lib/lisp/primitives.x:238

lisp_string_strip

String lisp_string_strip(String string, Var chars)

Trims the bytes in chars, using whitespace for an empty String.

Source: lib/lisp/primitives.x:230

lisp_truth

Var lisp_truth(Var value)

Returns Lisp true for every value except nil and void.

Source: lib/lisp/primitives.x:14

native_scalar_access

NativeScalarAccess native_scalar_access(List exact_type)

Returns the access record for an exact C scalar type such as (unsigned long), or NULL for any other type.

Source: lib/lisp/lisp.x:51

Lisp

Lisp.adopt

void Lisp.adopt(Lisp lisp, Lisp parent)

Makes lisp read parent’s definitions for names it does not bind.

Lisp definitions cannot replace names supplied by an ancestor. Lisp.set_global may shadow them in the child. Child writes never reach the parent or another child. The child also takes the parent’s special forms in place of its own, because the evaluator recognizes a special form by the identity of the Func a name resolves to, and the child resolves reserved names in the parent.

The caller keeps parent alive for as long as any child names it, and freezes it with Lisp.freeze before the first child runs: a child’s values belong to a narrower Context than the parent’s, so nothing a child produces may become reachable from the parent.

Source: lib/lisp/sessions.x:165

Lisp.apply

Var Lisp.apply(Lisp lisp, Var callable, List values)

Applies callable to already evaluated values. Macros and evaluator special forms other than the built-in apply are not procedures and are rejected. The built-in accepts a callable and a List and recursively applies those already evaluated values. The Lisp session owns Scope allocations made by the call; returned canonical or caller-supplied values keep their existing owners. The caller retains responsibility for callable, values, and their referents.

Raises: <bad-arg> for a null session, <not-call> for a non-procedure or evaluator-only callable, <bad-arity> or <bad-types> at the call boundary, or a cause raised by the called procedure.

Source: lib/lisp/evaluate.x:770

Lisp.bind

void Lisp.bind(Lisp lisp, String name, Func function)

Installs function as name and transfers its storage to lisp. Invalid arguments raise <bad-arg> without transferring ownership. Once validation succeeds, the Func moves before the global insertion. The caller relinquishes ownership even if name canonicalization or Map growth then raises <alloc-fail>, <size-limit>, or <bad-enc>, but may borrow the pointer while the session lives. A direct function or noncapturing lambda converts to a shared handle that lives for the program; the session only borrows it. Values inside the Func, including its signature graph, retain their existing owners.

Source: lib/lisp/sessions.x:226

Lisp.call_budget

void Lisp.call_budget(Lisp lisp, long budget)

Sets how many calls one evaluation of lisp may make before it is stopped. lisp must be a live session and budget must be positive. The default is LISP_CALL_STEP_MAX, which is large enough that only a computation that does not end reaches it; a test sets a small one to reach it quickly.

The budget belongs to the public entry. Lisp.eval, Lisp.apply, and Lisp.eval_string each open one, and a call that runs it out does not renew it, so one entry reports a runaway once however many calls follow.

Source: lib/lisp/evaluate.x:677

Lisp.eval

Var Lisp.eval(Lisp lisp, Var expression)

Evaluates one Lisp form in lisp. Evaluation is synchronous and may retain the expression or values it reaches in session globals, Lambdas, or captures as described by the module ownership rule. Effects completed before a later failure are not rolled back. Raises: <bad-arg> for a null session, or any evaluator, imported operation, or called-procedure cause.

Source: lib/lisp/evaluate.x:753

Lisp.eval_file

Var Lisp.eval_file(Lisp l, File source)

Reads and evaluates every form from source. Reading starts at the current stream position, consumes through EOF, and leaves the borrowed stream open. Forms run in order, so effects from forms completed before a later read or evaluation failure are not rolled back. A null Lisp session is rejected by Lisp.eval_string only after the stream has been consumed.

Raises: <bad-arg> for a null stream or embedded NUL, <io-fail>, <size-limit>, or <alloc-fail> while reading, or any cause from Lisp.eval_string.

Source: lib/lisp/evaluate.x:811

Lisp.eval_string

Var Lisp.eval_string(Lisp lisp, String source)

Reads and evaluates every form in source. Forms run in source order and the return value is the last result, or Lisp nil for a null, empty, or comment-only source. Globals and other effects completed before a later reader or evaluator failure remain installed. Lambdas retain local values that may become reads after a global callable changes, including names in current data. These captures belong to the session; borrowed referents keep their original lifetimes.

Raises: <bad-arg> for a null session, <incomplete> or <malformed> while reading, or any cause from Lisp.eval.

Source: lib/lisp/evaluate.x:786

Lisp.freeze

void Lisp.freeze(Lisp lisp)

Marks lisp complete, so nothing produced later may reach it.

A frozen session rejects def and Lisp.set_global: a value produced while a narrower Context is current would leave the session holding values that die with that Context.

Source: lib/lisp/sessions.x:179

Lisp.kernel

Lisp Lisp.kernel(void)

Creates an isolated embedded Lisp session with only evaluator primitives. The caller owns a successful session and must pass it to Lisp.destroy. Returns NULL if a long shared name cannot be owned by the active pool chain. Failure of native once initialization writes a diagnostic and aborts the process.

Raises: <alloc-fail> or <size-limit> while creating session storage, or <bad-enc> while interning shared or special-form names.

Source: lib/lisp/sessions.x:96

Lisp.new

Lisp Lisp.new(void)

Creates an isolated session with the standard Lisp environment loaded. The caller owns the result and must pass it to Lisp.destroy. If standard-source evaluation transfers, no handle is returned and the constructed session remains allocated. Raises any cause from Lisp.kernel or Lisp.eval_string.

Source: lib/lisp/sessions.x:133

Lisp.set_interrupted

void Lisp.set_interrupted(Lisp lisp, int interrupted)

Sets whether evaluation in lisp is interrupted. While interrupted is nonzero, every interpreted call raises <interrupt>, including calls made after a catch. The store is async-signal-safe, so a signal handler may interrupt a running evaluation; the owner clears the flag before the next one. lisp must be a live session.

Source: lib/lisp/evaluate.x:686

Lisp.try_get

int Lisp.try_get(Lisp lisp, String name, Var &?out)

Writes the global binding for name to out when present. Returns 1 only after writing the borrowed value. A null session, name, or output, or an absent name returns 0 and leaves out unchanged. Raises <alloc-fail> or <bad-enc> when a nonempty lookup name cannot be canonicalized.

Source: lib/lisp/sessions.x:189

Advanced and interop API

FunctionSummary
Lisp.cleanupEnds the owned lifetime when a managed local leaves its block.
Lisp.destroyReleases a Lisp session and invalidates all session-owned state.
Lisp.readReads one Lisp form and returns <value> or <eof>.
Lisp.set_globalBinds name to value in the embedded Lisp global environment.

Lisp

Lisp.cleanup

void Lisp.cleanup(Lisp value)

Ends the owned lifetime when a managed local leaves its block.

Source: lib/lisp/lisp.x:64

Lisp.destroy

void Lisp.destroy(Lisp lisp)

Releases a Lisp session and invalidates all session-owned state. This includes its global and reserved Maps, Lambdas, and transferred Funcs. Borrowed values are not released. A null session does nothing; no evaluation may remain active. Destroying its still-active Scope raises <bad-state>.

Source: lib/lisp/sessions.x:145

Lisp.read

Symbol Lisp.read(Lisp lisp, String source, unsigned &?cursor, Var &?out)

Reads one Lisp form and returns <value> or <eof>. A nonnull out receives the form only for <value>; it is otherwise unchanged. New result storage uses the caller’s active Scope and canonical pools, not the temporary token Scope, and remains valid until those owners are released. On success cursor advances past the form, at EOF it becomes the source length, and on a reader error it identifies the failing form’s first token. A null source or cursor returns <eof> without raising. A nonnull cursor must initially hold a byte offset no greater than the source length. A successful session construction must first initialize the shared reader names; afterward lisp is not consulted and may be null.

Raises: <incomplete> for a truncated form, <malformed> for invalid reader syntax, or <alloc-fail>, <size-limit>, or <bad-enc> while tokenizing, constructing, interning, or boxing the form.

Source: lib/lisp/reader.x:173

Lisp.set_global

void Lisp.set_global(Lisp lisp, String name, Var value)

Binds name to value in the embedded Lisp global environment. The session stores the value in a raw slot, so void remains distinct from Lisp nil. The binding does not take ownership of value referents; their canonical graphs or other owners must outlive the binding or session. A host binding may shadow an inherited name in this session; it does not change the ancestor. Lisp def still rejects inherited names, including a name the host has shadowed locally. Binding an x2c. name protects that namespace from later Lisp def forms, but direct calls to this function may replace such a binding.

Raises: <bad-arg> for a null session or name, or <alloc-fail>, <size-limit>, or <bad-enc> while canonicalizing or storing the binding.

Source: lib/lisp/sessions.x:205

Runtime-internal callables

These callables connect runtime translation units. They are documented for source readers but are not supported as user API.

FunctionSummary
lisp_addConcatenates when either operand is String, otherwise adds dynamically.
lisp_atomReturns Lisp true unless value is a nonempty List.
lisp_compareCompares Lisp numbers by value and returns a boxed negative, zero, or positive.
lisp_divideDivides the first value by each later one; one value reciprocates it.
lisp_eqReturns Lisp true when a and b are equal by Var.equal.
lisp_eq_chainReports whether every neighbouring pair of numbers compares equal.
lisp_ge_chainReports whether two or more numbers never increase.
lisp_gt_chainReports whether two or more numbers strictly decrease.
lisp_le_chainReports whether two or more numbers never decrease.
lisp_listReturns Lisp true when value is List-typed, including nil.
lisp_lt_chainReports whether two or more numbers strictly increase.
lisp_minusSubtracts each later value from the first; one value negates it.
lisp_numberReturns Lisp true when value has an integer or floating kind.
lisp_pairReturns Lisp true when value is a nonempty List.
lisp_plusAdds or concatenates every value left to right; no values gives 0.
lisp_procedureReturns Lisp true when value is a native function or Lambda.
lisp_read_fileReads path completely, closes it, and returns its boxed String contents.
lisp_reprBoxes the readable representation of value.
lisp_source_functionMarks the actual Lambda installed for one lowered source function.
lisp_strBoxes the display String of value.
lisp_stringReturns Lisp true when value is a String.
lisp_string_appendReturns the boxed concatenation of left and right.
lisp_string_downcaseReturns a boxed lower-case copy of string.
lisp_substringReturns the boxed unit-step slice string[start:stop].
lisp_symbolReturns Lisp true when value has Symbol kind.
lisp_timesMultiplies every value; no values gives 1.
lisp_typeReturns the runtime tag of value.
lisp_write_fileReplaces path with text and reports Lisp success.
Lisp.activeBorrows the session executing the current native Lisp callback.
Lisp.automatic_storageBorrows the current lowered source activation’s automatic storage.
Lisp.result_storageBorrows the caller’s storage for a lowered record result.
Lisp.storageBorrows the storage owner for callback state retained by this session.

Functions

lisp_add

Var lisp_add(Var a, Var b)

Concatenates when either operand is String, otherwise adds dynamically.

Source: lib/lisp/primitives.x:114

lisp_atom

Var lisp_atom(Var value)

Returns Lisp true unless value is a nonempty List.

Source: lib/lisp/primitives.x:17

lisp_compare

Var lisp_compare(Var a, Var b)

Compares Lisp numbers by value and returns a boxed negative, zero, or positive. Integer and floating encodings of one number compare equal. A nonnumeric operand raises <bad-types>.

Source: lib/lisp/primitives.x:105

lisp_divide

Var lisp_divide(List values)

Divides the first value by each later one; one value reciprocates it. An empty input raises <bad-arity>.

Source: lib/lisp/primitives.x:151

lisp_eq

Var lisp_eq(Var a, Var b)

Returns Lisp true when a and b are equal by Var.equal.

Source: lib/lisp/primitives.x:42

lisp_eq_chain

Var lisp_eq_chain(List values)

Reports whether every neighbouring pair of numbers compares equal. Fewer than two values raise <bad-arity>; a nonnumber raises <bad-types>.

Source: lib/lisp/primitives.x:181

lisp_ge_chain

Var lisp_ge_chain(List values)

Reports whether two or more numbers never increase. Fewer than two values raise <bad-arity>; a nonnumber raises <bad-types>.

Source: lib/lisp/primitives.x:205

lisp_gt_chain

Var lisp_gt_chain(List values)

Reports whether two or more numbers strictly decrease. Fewer than two values raise <bad-arity>; a nonnumber raises <bad-types>.

Source: lib/lisp/primitives.x:199

lisp_le_chain

Var lisp_le_chain(List values)

Reports whether two or more numbers never decrease. Fewer than two values raise <bad-arity>; a nonnumber raises <bad-types>.

Source: lib/lisp/primitives.x:193

lisp_list

Var lisp_list(Var value)

Returns Lisp true when value is List-typed, including nil.

Source: lib/lisp/primitives.x:48

lisp_lt_chain

Var lisp_lt_chain(List values)

Reports whether two or more numbers strictly increase. Fewer than two values raise <bad-arity>; a nonnumber raises <bad-types>.

Source: lib/lisp/primitives.x:187

lisp_minus

Var lisp_minus(List values)

Subtracts each later value from the first; one value negates it. An empty input raises <bad-arity>.

Source: lib/lisp/primitives.x:130

lisp_number

Var lisp_number(Var value)

Returns Lisp true when value has an integer or floating kind.

Source: lib/lisp/primitives.x:56

lisp_pair

Var lisp_pair(Var value)

Returns Lisp true when value is a nonempty List.

Source: lib/lisp/primitives.x:45

lisp_plus

Var lisp_plus(List values)

Adds or concatenates every value left to right; no values gives 0.

Source: lib/lisp/primitives.x:120

lisp_procedure

Var lisp_procedure(Var value)

Returns Lisp true when value is a native function or Lambda.

Source: lib/lisp/primitives.x:65

lisp_read_file

Var lisp_read_file(String path)

Reads path completely, closes it, and returns its boxed String contents. Raises the open, read, size, or allocation cause reported by File. An opened stream is still closed on transfer.

Source: lib/lisp/primitives.x:256

lisp_repr

Var lisp_repr(Var value)

Boxes the readable representation of value.

Source: lib/lisp/primitives.x:213

lisp_source_function

Var lisp_source_function(Var callable)

Marks the actual Lambda installed for one lowered source function.

Source: lib/lisp/evaluate.x:827

lisp_str

Var lisp_str(Var value)

Boxes the display String of value.

Source: lib/lisp/primitives.x:210

lisp_string

Var lisp_string(Var value)

Returns Lisp true when value is a String.

Source: lib/lisp/primitives.x:59

lisp_string_append

Var lisp_string_append(String left, String right)

Returns the boxed concatenation of left and right.

Source: lib/lisp/primitives.x:216

lisp_string_downcase

Var lisp_string_downcase(String string)

Returns a boxed lower-case copy of string.

Source: lib/lisp/primitives.x:223

lisp_substring

Var lisp_substring(String string, int start, int stop)

Returns the boxed unit-step slice string[start:stop].

Source: lib/lisp/primitives.x:219

lisp_symbol

Var lisp_symbol(Var value)

Returns Lisp true when value has Symbol kind.

Source: lib/lisp/primitives.x:62

lisp_times

Var lisp_times(List values)

Multiplies every value; no values gives 1.

Source: lib/lisp/primitives.x:142

lisp_type

Symbol lisp_type(Var value)

Returns the runtime tag of value.

Source: lib/lisp/primitives.x:68

lisp_write_file

Var lisp_write_file(String path, String text)

Replaces path with text and reports Lisp success. The file is opened with truncation and always closed. A write or close failure returns nil after any accepted bytes; this operation is not atomic. An open failure transfers its File cause. Null text writes an empty file.

Source: lib/lisp/primitives.x:264

Lisp

Lisp.active

Lisp Lisp.active(void)

Borrows the session executing the current native Lisp callback.

Source: lib/lisp/sessions.x:235

Lisp.automatic_storage

Scope *Lisp.automatic_storage(Lisp lisp)

Borrows the current lowered source activation’s automatic storage.

Source: lib/lisp/sessions.x:239

Lisp.result_storage

Scope *Lisp.result_storage(Lisp lisp)

Borrows the caller’s storage for a lowered record result.

Source: lib/lisp/sessions.x:242

Lisp.storage

Scope *Lisp.storage(Lisp lisp)

Borrows the storage owner for callback state retained by this session.

Source: lib/lisp/sessions.x:237

Public types

TypeKindSummary
LispstructRepresents one isolated embedded Lisp session.
NativeScalarAccessstructDescribes one exact C scalar type in native bytes: its Var tag, size, alignment, load, and store.
NativeScalarLoadcallbackReads one exact C scalar from bytes; a wide result is boxed in owner.
NativeScalarStorecallbackWrites value, converted to one exact C scalar type, to bytes.

Lisp

typedef struct Lisp *Lisp

Represents one isolated embedded Lisp session. Create it with Lisp.new or Lisp.kernel and end it with Lisp.destroy. The module header describes its owned and borrowed state. A session is mutable and requires caller serialization.

Source: lib/lisp/lisp.x:59

NativeScalarAccess

typedef struct NativeScalarAccess { Symbol tag; size_t size, alignment; NativeScalarLoad load; NativeScalarStore store; } *NativeScalarAccess

Describes one exact C scalar type in native bytes: its Var tag, size, alignment, load, and store. Compile-time code that keeps C objects in bytes, and the compiler’s layouts, select a row with native_scalar_access.

Source: lib/lisp/lisp.x:37

NativeScalarLoad

typedef Var (*NativeScalarLoad)(const void *bytes, Scope *owner)

Reads one exact C scalar from bytes; a wide result is boxed in owner.

Source: lib/lisp/lisp.x:30

NativeScalarStore

typedef void (*NativeScalarStore)(void *bytes, Var value)

Writes value, converted to one exact C scalar type, to bytes.

Source: lib/lisp/lisp.x:32

Design notes

Lisp owns embedded compile-time Lisp sessions: the reader, the evaluator, and each session’s global environment. Lambdas and natives receive their arguments evaluated left to right, macros and special forms receive them raw, nil and void are false, and a Lambda captures by value the free locals its body reads. Names are canonical Atoms, and bind reaches native operations through the table that lisp-targets.x builds.

The session Scope owns the Lisp record, its Maps, Lambdas, and bound Func storage, which hold Vars by value without cloning their referents. Those referents keep their own pool or caller owners and must outlive every session entry that refers to them. A session is not synchronized: its caller serializes evaluation and destroys it only after every call has returned.

Tests and examples

make verify (unittest/test-lisp.x) and make examples.