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.x

The Lisp runtime: reader, session, and evaluator.

Primary API

FunctionSummary
lisp_match_replaceReturns the instantiated template when input matches pat.
Lisp.applyApplies callable to already evaluated values.
Lisp.bindInstalls function as name and transfers its storage to lisp.
Lisp.evalEvaluates one Lisp form in lisp.
Lisp.eval_fileReads and evaluates every form from file.
Lisp.eval_stringReads and evaluates every form in source.
Lisp.newCreates an isolated session with the standard Lisp environment loaded.
Lisp.new_bareCreates an isolated embedded Lisp session with only evaluator primitives.
Lisp.try_getWrites the global binding for name to out when present.

Functions

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.x:697

Lisp

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.x:1594

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. Values inside the Func, including its signature graph, retain their existing owners.

Source: lib/lisp.x:1688

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.x:1579

Lisp.eval_file

Var Lisp.eval_file(Lisp lisp, File source)

Reads and evaluates every form from file. 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.x:1632

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.

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

Source: lib/lisp.x:1605

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.new_bare or Lisp.eval_string.

Source: lib/lisp.x:484

Lisp.new_bare

Lisp Lisp.new_bare(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.x:454

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.x:1655

Advanced and interop API

FunctionSummary
Lisp.apply_valuesApplies a Lisp callable to already evaluated shared-machine values.
Lisp.auto_disableForces calls through the recursive evaluator when disabled is nonzero.
Lisp.auto_instrumentSelects optional detailed machine statistics for later AUTO executions.
Lisp.auto_statsReturns the current cumulative automatic-evaluator statistics for lisp.
Lisp.destroyReleases a Lisp session and invalidates all session-owned state.
Lisp.enterPushes one prepared-Lambda environment for the shared machine.
Lisp.leavePops the innermost environment installed by Lisp.enter.
Lisp.precallHandles a callable that cannot continue through prepared machine dispatch.
Lisp.programReturns the prepared AUTO program for an eligible Lisp Lambda.
Lisp.readReads one Lisp form and returns <value> or <eof>.
Lisp.resolveResolves one Lisp name for the active shared-machine environment.
Lisp.retargetReplaces the current shared-machine environment for a self tail call.
Lisp.set_globalBinds name to value in the embedded Lisp global environment.

Lisp

Lisp.apply_values

Var Lisp.apply_values( void *storage, Var callable, const Var *values, int count)

Applies a Lisp callable to already evaluated shared-machine values. storage names the running context; values may be null only when count is zero, count must not be negative, and the array is borrowed for the call. The active Lisp session owns new Scope allocations; other returned Vars keep their ordinary owners. Raises any cause from argument materialization or the callable.

Source: lib/lisp.x:136

Lisp.auto_disable

void Lisp.auto_disable(Lisp lisp, int disabled)

Forces calls through the recursive evaluator when disabled is nonzero. lisp must be a live session. Re-enabling AUTO preserves published programs, thresholds, statistics, and the instrumentation pointer.

Source: lib/lisp.x:1486

Lisp.auto_instrument

void Lisp.auto_instrument(Lisp lisp, MachineStats *stats)

Selects optional detailed machine statistics for later AUTO executions. lisp must be a live session. stats is borrowed, retained without initialization, and updated in place; it must outlive every evaluation until replaced or cleared with NULL.

Source: lib/lisp.x:1475

Lisp.auto_stats

LispAutoStats Lisp.auto_stats(Lisp lisp)

Returns the current cumulative automatic-evaluator statistics for lisp. lisp must be a live session. The returned structure is a value snapshot and does not reset any counter.

Source: lib/lisp.x:1468

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, transferred Funcs, prepared programs, and machine slots. Borrowed values are not released. A null session does nothing; no evaluation or machine call may remain active. Destroying its still-active Scope raises <bad-state>.

Source: lib/lisp.x:496

Lisp.enter

void Lisp.enter(void *storage, Var callable, const Var *values, int count)

Pushes one prepared-Lambda environment for the shared machine. storage names a running LispMachine context, callable is a prepared Lambda, and values supplies the Lambda’s count borrowed arguments. The array and its values must remain live until the matching Lisp.leave.

Source: lib/lisp.x:93

Lisp.leave

void Lisp.leave(void *storage)

Pops the innermost environment installed by Lisp.enter. Calls must balance in last-in, first-out order; the borrowed argument array is no longer retained afterward.

Source: lib/lisp.x:109

Lisp.precall

int Lisp.precall(void *storage, Var callable, List raw, Var *value)

Handles a callable that cannot continue through prepared machine dispatch. Returns 0 and leaves value unchanged when the machine may proceed. Otherwise it applies the callable to borrowed raw forms, writes value, and returns 1. storage and value must be nonnull and belong to the running LispMachine invocation.

Source: lib/lisp.x:150

Lisp.program

int Lisp.program(Var callable, MachineView *view, int *nparam, Var *body)

Returns the prepared AUTO program for an eligible Lisp Lambda. On success, writes all three nonnull outputs and returns 1. Otherwise it returns 0 and leaves them unchanged. The view and body are borrowed from the Lambda and remain valid only while its owning Lisp session lives.

Source: lib/lisp.x:66

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.x:514

Lisp.resolve

int Lisp.resolve(void *storage, Var name, Var *value)

Resolves one Lisp name for the active shared-machine environment. storage must be the context of a running LispMachine and value must be nonnull. Returns 1 and writes the borrowed binding, or returns 0 and leaves the output unchanged.

Source: lib/lisp.x:83

Lisp.retarget

void Lisp.retarget(void *storage, Var callable, const Var *values, int count)

Replaces the current shared-machine environment for a self tail call. The parent environment is preserved. callable must be its prepared Lambda, count must match its parameters, and the borrowed values remain live until another retarget or the environment is left.

Source: lib/lisp.x:121

Lisp.set_global

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

Binds name to value in the embedded Lisp global environment. The Map retains the canonicalized name and Var value without taking ownership of their referents; their canonical graphs or other owners must outlive the binding or session. 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, <void-op> for a void value, or <alloc-fail>, <size-limit>, or <bad-enc> while canonicalizing or storing the binding.

Source: lib/lisp.x:1668

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 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_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.

Functions

lisp_add

Var lisp_add(Var a, Var b)

Concatenates when either operand is String, otherwise adds dynamically.

Source: lib/lisp.x:578

lisp_atom

Var lisp_atom(Var value)

Returns Lisp true unless value is a nonempty List.

Source: lib/lisp.x:535

lisp_compare

Var lisp_compare(Var a, Var b)

Compares Lisp numbers and returns a boxed negative, zero, or positive. A nonnumeric operand raises <bad-types>.

Source: lib/lisp.x:566

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.x:620

lisp_eq

Var lisp_eq(Var a, Var b)

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

Source: lib/lisp.x:538

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.x:650

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.x:674

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.x:668

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.x:662

lisp_list

Var lisp_list(Var value)

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

Source: lib/lisp.x:544

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.x:656

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.x:599

lisp_number

Var lisp_number(Var value)

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

Source: lib/lisp.x:552

lisp_pair

Var lisp_pair(Var value)

Returns Lisp true when value is a nonempty List.

Source: lib/lisp.x:541

lisp_plus

Var lisp_plus(List values)

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

Source: lib/lisp.x:589

lisp_procedure

Var lisp_procedure(Var value)

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

Source: lib/lisp.x:561

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.x:708

lisp_repr

Var lisp_repr(Var value)

Boxes the readable representation of value.

Source: lib/lisp.x:680

lisp_str

Var lisp_str(Var value)

Boxes the display String of value.

Source: lib/lisp.x:677

lisp_string

Var lisp_string(Var value)

Returns Lisp true when value is a String.

Source: lib/lisp.x:555

lisp_string_append

Var lisp_string_append(String left, String right)

Returns the boxed concatenation of left and right.

Source: lib/lisp.x:683

lisp_string_downcase

Var lisp_string_downcase(String string)

Returns a boxed lower-case copy of string.

Source: lib/lisp.x:690

lisp_substring

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

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

Source: lib/lisp.x:686

lisp_symbol

Var lisp_symbol(Var value)

Returns Lisp true when value has Symbol kind.

Source: lib/lisp.x:558

lisp_times

Var lisp_times(List values)

Multiplies every value; no values gives 1.

Source: lib/lisp.x:611

lisp_type

Symbol lisp_type(Var value)

Returns the runtime tag of value.

Source: lib/lisp.x:574

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.x:717

Public types

TypeKindSummary
LispstructRepresents one isolated embedded Lisp session.
LispAutoStatsstructReports cumulative automatic-evaluator activity for one Lisp session.

Lisp

typedef struct Lisp *Lisp

Represents one isolated embedded Lisp session. Create it with Lisp.new or Lisp.new_bare 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.x:43

LispAutoStats

typedef struct LispAutoStats { long invocations, machine_entries, machine_errors; long analyses, published, ineligible; long guard_failures, remembered_fallbacks; long program_bytes; } LispAutoStats

Reports cumulative automatic-evaluator activity for one Lisp session. Counter values are snapshots since session creation. program_bytes counts published programs still owned by the session; detailed machine counters are collected separately through Lisp.auto_instrument.

Source: lib/lisp.x:54

Design notes

Each Lisp session owns a Scope holding its global environment. Evaluation uses eager left-to-right arguments for lambdas and natives, raw arguments for macros and special forms, macro expansion evaluated once in the caller’s environment, globals able to shadow reserved forms, nil as the only false value, and by-value capture of free locals using the V1 body-flattening rule.

Identifiers use canonical Atoms: compact x2c Symbols when their spelling round-trips exactly, with direct canonical-String <lsym> Vars as the arbitrary-length, case-sensitive fallback. The reader converts shared Tokenizer output into Var and List forms.

The session Scope owns the Lisp record, Maps, Lambdas, bound Func storage, prepared programs, and reusable machine slots. The internal lisp-machine.x decoder executes eligible prepared programs. Maps, Lambda bodies, and captures retain Vars by value without cloning their referents. Canonical graphs and identity-bearing values therefore keep their pool or caller ownership and must outlive every session entry that refers to them. A session is not synchronized; its caller serializes evaluation and mutation and destroys it only after every call has returned.

Tests and examples

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