lib/lisp/lisp.x
The Lisp runtime: reader, session, and evaluator.
Primary API
| Function | Summary |
|---|---|
lisp_car | Returns the first element of value, or void when it is nil. |
lisp_cdr | Returns the tail of value, or nil when it is nil. |
lisp_match_replace | Returns the instantiated template when input matches pat. |
lisp_string_lstrip | Trims leading bytes, accepting the same charset values as strip. |
lisp_string_rstrip | Trims trailing bytes, accepting the same charset values as strip. |
lisp_string_strip | Trims the bytes in chars, using whitespace for an empty String. |
lisp_truth | Returns Lisp true for every value except nil and void. |
native_scalar_access | Returns the access record for an exact C scalar type such as (unsigned long), or NULL for any other type. |
Lisp.adopt | Makes lisp read parent’s definitions for names it does not bind. |
Lisp.apply | Applies callable to already evaluated values. |
Lisp.bind | Installs function as name and transfers its storage to lisp. |
Lisp.call_budget | Sets how many calls one evaluation of lisp may make before it is stopped. |
Lisp.eval | Evaluates one Lisp form in lisp. |
Lisp.eval_file | Reads and evaluates every form from source. |
Lisp.eval_string | Reads and evaluates every form in source. |
Lisp.freeze | Marks lisp complete, so nothing produced later may reach it. |
Lisp.kernel | Creates an isolated embedded Lisp session with only evaluator primitives. |
Lisp.new | Creates an isolated session with the standard Lisp environment loaded. |
Lisp.set_interrupted | Sets whether evaluation in lisp is interrupted. |
Lisp.try_get | Writes 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
| Function | Summary |
|---|---|
Lisp.cleanup | Ends the owned lifetime when a managed local leaves its block. |
Lisp.destroy | Releases a Lisp session and invalidates all session-owned state. |
Lisp.read | Reads one Lisp form and returns <value> or <eof>. |
Lisp.set_global | Binds 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.
| Function | Summary |
|---|---|
lisp_add | Concatenates when either operand is String, otherwise adds dynamically. |
lisp_atom | Returns Lisp true unless value is a nonempty List. |
lisp_compare | Compares Lisp numbers by value and returns a boxed negative, zero, or positive. |
lisp_divide | Divides the first value by each later one; one value reciprocates it. |
lisp_eq | Returns Lisp true when a and b are equal by Var.equal. |
lisp_eq_chain | Reports whether every neighbouring pair of numbers compares equal. |
lisp_ge_chain | Reports whether two or more numbers never increase. |
lisp_gt_chain | Reports whether two or more numbers strictly decrease. |
lisp_le_chain | Reports whether two or more numbers never decrease. |
lisp_list | Returns Lisp true when value is List-typed, including nil. |
lisp_lt_chain | Reports whether two or more numbers strictly increase. |
lisp_minus | Subtracts each later value from the first; one value negates it. |
lisp_number | Returns Lisp true when value has an integer or floating kind. |
lisp_pair | Returns Lisp true when value is a nonempty List. |
lisp_plus | Adds or concatenates every value left to right; no values gives 0. |
lisp_procedure | Returns Lisp true when value is a native function or Lambda. |
lisp_read_file | Reads path completely, closes it, and returns its boxed String contents. |
lisp_repr | Boxes the readable representation of value. |
lisp_source_function | Marks the actual Lambda installed for one lowered source function. |
lisp_str | Boxes the display String of value. |
lisp_string | Returns Lisp true when value is a String. |
lisp_string_append | Returns the boxed concatenation of left and right. |
lisp_string_downcase | Returns a boxed lower-case copy of string. |
lisp_substring | Returns the boxed unit-step slice string[start:stop]. |
lisp_symbol | Returns Lisp true when value has Symbol kind. |
lisp_times | Multiplies every value; no values gives 1. |
lisp_type | Returns the runtime tag of value. |
lisp_write_file | Replaces path with text and reports Lisp success. |
Lisp.active | Borrows the session executing the current native Lisp callback. |
Lisp.automatic_storage | Borrows the current lowered source activation’s automatic storage. |
Lisp.result_storage | Borrows the caller’s storage for a lowered record result. |
Lisp.storage | Borrows 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
| Type | Kind | Summary |
|---|---|---|
Lisp | struct | Represents one isolated embedded Lisp session. |
NativeScalarAccess | struct | Describes one exact C scalar type in native bytes: its Var tag, size, alignment, load, and store. |
NativeScalarLoad | callback | Reads one exact C scalar from bytes; a wide result is boxed in owner. |
NativeScalarStore | callback | Writes 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.