Skip to content

Built-ins

The KEC Lisp kernel (vendored Fe) ships 26 compiled-in primitives — binding, control flow, list ops, predicates, arithmetic, and one I/O call. This page indexes them with one-line semantics. Everything else you call comes from one of the two layers above the kernel:

SourceFe typeDefined whereExamples
Kernel built-in (this page)FE_TPRIMcompiled into kernel/set, cons, if
Runtime / host primitiveFE_TCFUNCC in runtime/ or host/, bound via kec_bind_fetry, type-of, mod, princ
Core / userFE_TFUNC / FE_TMACROKEC Lisp in core/ (or your code)map, cond, defn, =

So =, map, cond, and defn are not kernel built-ins — they live in Core. The language is the kernel plus Core plus the runtime/host primitives.

Kernel delta from upstream Fe. KEC names assignment set, not =. That frees = to mean equality (supplied by Core). If you’ve read upstream Fe docs, this is the one thing to re-learn. See the CHANGELOG and Fe Kernel — Internals for the full delta and implementation constraints.


Binding and definition

Built-inSemantics
(let sym value)Bind sym. In a body -> a local for the rest of that body; at the top level -> a global. Protected standard globals cannot be rebound. Returns value.
(set sym value)Assignment to an existing binding (or a top-level global). Protected standard globals cannot be rebound.
(fn (params…) body…)Construct a closure (lexical). (fn (a . rest) …) and (fn args …) bind rest/variadic args.
(mac (params…) body…)Construct a macro: args unevaluated, the expansion is re-evaluated.

There is no define / defn / defmacro in the kernel — Core supplies those (they expand to set + fn/mac).

After the runtime loads Core, load-bearing standard names are protected. A script that attempts to rebind a kernel primitive such as cons, a host primitive, a Core function such as map, or a private Core helper such as %append receives a catchable error and the original global value remains in place. Lexical locals are still ordinary bindings.

Control flow

Built-inSemantics
(if cond then else…)Conditional; supports cond-style chaining (if c1 t1 c2 t2 else).
(and a b …)Short-circuit AND.
(or a b …)Short-circuit OR.
(while cond body…)Loop while cond is truthy; returns nil.
(do expr…)Sequence; returns the last value.
(quote x) / 'xSuppress evaluation.

List operations

Built-inSignatureSemantics
(cons a b)Any Any → PairConstruct a pair (allocated from the arena).
(car p)Pair → AnyFirst element. Errors if p is not a pair.
(cdr p)Pair → AnyRest. Errors if p is not a pair.
(setcar p v)Pair Any → nilIn-place mutation of car. Returns nil.
(setcdr p v)Pair Any → nilIn-place mutation of cdr. Returns nil.
(list a b …)Any… → ListBuild a proper list of the evaluated arguments.

No nth, length, append, reverse, member, or assoc in the kernelCore supplies those, written iteratively. Performance-sensitive traversal uses while + setcar/setcdr rather than deep recursion (the GC-root stack is bounded).

Predicates

Built-inSemantics
(not x)True if x is nil.
(atom x)True if x is not a pair (i.e. nil, number, symbol, string, fn, macro, prim, cfunc, or ptr).
(is a b)Equality: numbers by value, strings structurally, pairs and other atoms by identity.

There is no =, nil?, pair?, number?, … in the kernel. (not x) is the null test and atom is leaf detection; Core wraps the rest as named predicates (some using the host type-of primitive).

Arithmetic & comparison

All numeric ops operate on fe_Number (single-precision float); the variadic arithmetic forms fold left.

Built-inSemantics
(+ a b …)Sum; folds left. Needs at least one argument — (+) raises “too few arguments”.
(- a b …)Subtract; folds left from the first argument. No unary negation: (- 5) → 5. Negate with (- 0 5).
(* a b …)Product.
(/ a b …)Float division — (/ 7 2) → 3.5.
(< a b)Strict less-than.
(<= a b)Less-or-equal.

No >, >=, =, mod, abs, or sqrt in the kernel: > / >= / = come from Core; mod / abs / sqrt and friends are host primitives (see the Language Reference).

I/O

Built-inSemantics
(print x …)Write each x to the configured write function, then a newline.

print is the kernel’s only I/O. The runtime/host layers add princ / newline / repr (and, in the FULL profile, file I/O — load / read-file / write-file / append-file, plus require). try / raise are catchable error control. Length-aware read-string parses one value from text and read-all parses every form, both in any profile; macroexpand-1 expands one quoted macro call for inspection. bound? (including bindings whose value is nil), globals, and fn-params are read-only reflection over the live environment (safe in any profile). eval evaluates an already-read data form in the live image (the editor/REPL keystone) but is a FULL-tier capability, deliberately not bound into SANDBOX contexts.

Networking is a host primitive, FULL only

The kernel has no socket I/O. The portable host layer adds eight TCP primitives plus a sleep call, all gated to KEC_PROFILE_FULL exactly as the file and system primitives are, and all absent on a platform without POSIX sockets. A context can test for them the same way it tests any gate: (bound? 'tcp-connect).

PrimitiveSemantics
(tcp-connect host port [timeout-ms])Resolve and connect in cleartext; returns a socket handle. Raises on failure, naming host, port, and the OS reason.
(tls-connect host port [timeout-ms [insecure]])As tcp-connect, then a TLS handshake. Verifies the peer certificate (chain and identity) unless a truthy 4th argument skips it. Returns the same kind of handle, so tcp-send / tcp-recv / tcp-close work on it.
(tcp-send handle value)Write the whole payload, looping on partial writes; returns the byte count. Blobs go verbatim.
(tcp-recv handle max-bytes)Read up to max-bytes; returns a string, or nil at clean EOF.
(tcp-close handle)Close. Idempotent, and a dropped handle is closed by its finalizer.
(tcp-listen port [backlog])Bind and listen on 127.0.0.1; returns a listener handle.
(tcp-accept handle [timeout-ms])Accept one connection; returns a socket handle, or nil on timeout.
(tcp-port handle)The local port this socket is bound to, which is how (tcp-listen 0) reports the ephemeral port it took.
(sleep seconds)Suspend for a fractional number of seconds, resuming across signals.

That is the entire C surface. HTTP/1.1 framing, chunked transfer decoding, URL encoding, and JSON all live in Lisp above it: json-parse / json-stringify in Core, and the client in examples/http/. TLS is the one exception, since it cannot be written in Lisp; see Networking and ADR-0007.

Foreign containers are host primitives, not kernel built-ins. The current portable set includes vectors, flat row-major matrices, hash tables, and binary-safe blobs; see the Language Reference.


Quick lookup — the full kernel set (source order)

let set if fn mac while quote and or do
cons car cdr setcar setcdr list not is atom print
< <= + - * /

26 entries. Anything you call that isn’t in this list is coming from Core (Lisp) or a runtime/host primitive (C) — or, in the KN-86 firmware, from a device primitive bound through the FFI bridge.