Changelog¶
0.1.21¶
- The respelling, step 4 (spec/lir.md 2): every lIR text fibber owns is in the new spelling: the runtime (
rt/*.lir), the lIR the emitter, the live server and the live loader write by hand, the inlinelirbodies inlib/and the cases, the planted faults of the scripts, and the lIR quoted in the specs, ADRs and design documents. Everyfibcandlairfthe build runs hasFIB_LIR_SPELLING=new, so the old spelling is refused everywhere but one place: the seed, 0.1.20, embeds its runtime in the old spelling and is run withFIB_LIR_SPELLING=old(BUILDER_ENVin mk/config.mk) until a seed built from this tree replaces it. lair keeps--old-spellingfor that seed; it goes once the seed reads the new spelling. - lIR (the pinned copy moves from lir b3d6ad39 to 714c626f): symbolic ids,
(ORDINAL T SET "NAME")and(ROW TABLE SET "NAME" T VALUE)(spec/lir.md 4.7.1), numbered and joined by the program loader, so a library compiled once can name a type id or a table row without a program-wide pass; the ownership verifier hands a tail call's result to the caller instead of reporting a leak, verifies every function that holds a managed value (one whose only managed value was a call's result was skipped), and consumes a call's owned positions before it borrows the others (rule 2);lairf respellkeeps the arguments of a macro use and skips text it cannot lex; the runtime C function table holds the 15 functions it lacked, with the 32-bit narrowing of the ones that take or return a word. scripts/sync-lir.shregenerates docs/reference after a sync (the copied files move the lines the pages cite).
0.1.20¶
- lIR has compile-time macros (spec/lir.md 4.6):
(define-macro NAME (P..) block+)is a function from form objects to a form, written in lIR, compiled into the module's own JIT session when it is read and run between reading and parsing;(require-macros "FILE")loads a file of them. The form objects arelir.sexp.*(symbol, integer, float, string, list, each with its file, line, column and byte span;lir.sexp.atcopies a position onto a made form,lir.sexp.setis the dual of nth,lir.sexp.expandexpands a form from inside a macro,lir.sexp.gensymcounts per program read). A top-levelbeginis a splice of items, so one use can define several.(module-macro ..)runs at the end of the module over the forms it collected,(macro-import "FILE")puts a runtime module into the macro session as its state, and(include "FILE")reads a file's text in place. A module with no macros reads as before. (import "FILE")(spec/lir.md 4.7): a program is the union of its modules, joined as llvm-link joins them. The importer sees the imported module's exported functions, globals, structs and the macros of its own file; each module is loaded once per program, in dependency order, identified by its canonical path, and reads under its own readtable.- Reader macros (spec/lir.md 4.8):
define-reader-macrobinds a character of the module's readtable to an lIR function run at read time over a stream (lir.read.peek,next,position,skip,form,fail),define-dispatch-macrobinds the character after#, anddefine-token-readeris called after every atom with the atom's text as a symbol;define-reader-classsets a character's class and the nesting depth is the readtable's (1024 unless set). Forms carry byte spans; a byte order mark is skipped. The bindings a required library makes are the requiring module's. A module with no bindings reads as before. - Ownership in lIR (spec/lir.md 6.14): the managed pointer type, owned parameters,
unsafe,mutableand the ownership form are read, typed and printed, and lair verifies them (one dataflow per function, the ten rules of 6.14.5) on every path it compiles:FIB_LIR_OWN=verify|report|off,reportthe default (one summary line on stderr, the program accepted),verifymakes a violation an error. The forms are erased after the optimisation slot, before LLVM and the C, JS and WGSL printers. A program has one ownership form, carried in the interface of the module that holds it. noinlineandcold, LLVM's function attributes, on adefine;defuntakes:noinlineand:coldafter its parameters (spec/syntax.md 3.1). lair no longer makes a function noinline for a name ending-slow: an attribute is written, not inferred from a name.(dependent-library "NAME"), LLVM's!llvm.dependent-libraries, is a module item and replaces the;; link-lib:comment and the libs argument on every path (AOT, liro, the JIT and the live JIT, the C route, shared libraries). fibber's emitter writes it for each:lib;:libin fibber source is unchanged.(export-name "NAME")is a modifier of a define, LLVM'swasm-export-name: the WebAssembly backend exports the symbol with no--exportflag. Library versus executable islair build --library; a shared library exports what the lIR made external, with no symbol list. lair readsFIB_EXPORTSnowhere: the variable is now onlyfibc's own channel from--exportto its front end.(align N)means N on a kernel target too (spec/lir.md 6.9a); fibber's emitter writes a kernel's scalar alignment itself.- Each
(string ..)occurrence is its own constant, as spec/lir.md 3 says: lair no longer marks themunnamed_addr, so LLVM cannot merge two equal ones into one address. The emitter interns a trap's message as one private constant per text (cstr.N): the compiler's own lIR has 10 of them where it had 11,804(string ..)occurrences, and the binary grows by 752 bytes, not 118 KB. - The respelling (spec/lir.md 2): every word lIR owns is upper case (
ADD,FUNCTION,DEFINE), a reference or a type is a form ((GLOBAL f),(STRUCT S),(PTR (ADDRSPACE 1)),(FUNCTION ..),(VECTOR N T),(ARRAY N T),(LITERAL-STRUCT ..)), the lower case is free for the language above, and a name that is a word is refused. The parser reads both spellings; the printer writes the new one. The old spelling (add,@f,%struct.s,(ptr 1),(fn ..),<N x T>,[N x T]) is admitted for this release only:lairfrefuses it by default and admits it with--old-spellingorFIB_LIR_SPELLING=old(--new-spelling,FIB_LIR_SPELLING=newrefuse it);fibcadmits it.lairf respell FILE [--in-place|--check]rewrites a text into the new spelling with its comments and layout kept,lairf wordsprints the table of words, andlairf expand FILEprints a module with its macros expanded, for a backend with no compile-time runtime. - lIR and lair live in their own repository, https://github.com/tailoredshapes/lir, with lIR's cases (
cases/lir), tests, tools (lir2c, lir2js, the JS backend) and designs (lir-language.md, lir-facts.md, lair-in-fibber.md and the rest). fibc compiles lair from source, so fibber keeps a pinned, read-only copy ofcompiler/lir,compiler/native,compiler/llvm,compiler/c,compiler/lir.fib,compiler/lairf.fibandspec/lir.md: the fileLIRnames the repository, the commit and the sha256 of the copied files' manifest,scripts/sync-lir.sh [--repo DIR] [COMMIT]updates the copy, and the quick gate fails when the copy differs from the pin (scripts/lir-drift.sh). A change to lIR or lair starts in that repository. - lIR facts in LLVM's own forms (spec/lir.md 6.13):
(add nsw a b)andnuwon add, sub, mul and shl,(assume c)and(load (range LO HI) T p).FIB_LIR_FACTS=use|trap|ignore:use(the default) gives them to LLVM,trapturns each into a test that traps withlIR fact violated: ..,ignoredrops them. The emitter proves the first ones (the Vec tail read, bounded steps), andmake cases-trapruns ownership and the stdlib undertrapin the full gate. FIB_LIRO_THIN=1: the partitioned build's units are ThinLTO bitcode with summaries, thin-linked insidefibcthrough a C++ shim over LLVM's LTO (Linux and macOS; no LLVMgold.so or linker plugin). The backend cache keys on the unit after importing, so an edit reruns only the backends that import what changed. Opt-in; the default build is unchanged.FIB_LIRO_THIN_JOBS,FIB_LIRO_THIN_IMPORTandFIB_LIRO_THIN_REPORT=FILEtune and report it (docs/design/compile-performance.md).- Performance (docs/design/vec-performance.md 8 and 9): a Vec built whole, or by
conjfrom empty while unique, is flat (every element in its tail), sonthis a load and a unique update is in place; a shared update makes the trie once.vec-nth,vec-assocandvec-conjare small fast paths with the trie work out of line, and the Vec read path is emitted inline.reduceandintoover a Vec or an Array keep the accumulator in a loop variable, so a unique one is updated in place. A literal or named function passed to a defun that calls it, or bound byletand only called, is a direct call; stack and immortal closures called directly skip their counts; a let-bound literal captured only by stack closures stays on the stack. Fused chains over a range with a literal step, or over a vector literal of fn stages, have no fallback branch; a match the checker proved exhaustive falls through tounreachable. - Fixes: the operand of
private-copyescapes, so a closure it copies is a heap closure (it read a dead frame); the live server answers a buffered request line without waiting for more bytes (a client that pipelined two requests hung);lairf cases DIR.. -j Nreads its option instead of walking-jas a path. - Tests and CI: the live test op's status check measures the run, not the entry's compile; the host-threads, live leak and shared
stackcheck tests run on macOS (a mutex and condvar barrier,
psfor the resident size,nm -gUfor Mach-O exports,LLVM_LIBDIRfor the live-mode build); the Linux CI runs the tools withTOOLS_TIMEOUT=1800, as the Mac does; case 8641 counts the tasks the workers ran instead of assuming every task runs on one; the stdlib cases that wrote fixed paths under /tmp name their files by the process id, so two gates at once no longer collide.
0.1.19¶
- Fusion covers more chains: a
mapover arangecall is a counted loop over the range with the stage in line, and chains offilter,remove,keep,take,take-whileandfilterv(over a Vec, an Array or a range, with or withoutmapstages) are one loop that builds the result directly, with no intermediate sequence. :libon macOS:fibc runfinds a library in DYLD_FALLBACK_LIBRARY_PATH (else /usr/local/lib and /usr/lib) and in$HOMEBREW_PREFIX/lib, instead of a Homebrew path compiled intofibc; when a library is not found and HOMEBREW_PREFIX is unset (ssh commands, launchd), the message says so. The darwinfibcagain names no build-machine path.scripts/mac-check.shstep 8 checks it.
0.1.18¶
- Persistent collections keep their uniqueness, so idiomatic updates are in place: a call that reads a value in a sibling
argument and moves it into another is a two-phase move (
(assoc v i (+ (nth v i) 1))),assoctakes its new value owned soupdate,update-orandupdate-optupdate a unique collection in place, andwithtakes a field whose new value reads the old one ((with e (f (assoc (. e f) i x)))). Each was a copy of the trie path per update (370 to 420 ns on a 1M-element Vec) and is now 20 to 60 ns; cases count heap objects so a copy that comes back fails (types §6.3, §6.4). - Fusion writes the stage in line:
mapv,vec/into []overmap, chains ofmapand two-sourcemapover a Vec or Array, with a fn literal or a named function, are counted loops that LLVM auto-vectorises (f64mapv13 ns to 1.4 ns an element; NEON on Apple Silicon).firstis a terminal of the fused table. - A stack overflow is a catchable failure in a program that catches and in a shared library (ADR 0027, reversing ADR 0009's
rule): functions on call cycles check the stack in their prologue;
trycatches it with kind "stack"; library exports setfib_status/fib_error. Programs that never catch keep the signal path at no cost.FIB_STACK_CHECK=0turns it off. fibc build --shared --header: shared libraries with a C ABI, a C header and a module map; a library and a live session are multi-threaded from the start.fibc run(andrepl,run --live,serve,test) loads the native libraries a program declares with:lib; where only the versioned file is installed (libwebp.so.7),runandbuildfind it; a library found nowhere is an error naming what was searched.- Library:
*command-line-args*; theMath/statics Clojure programs write (exp,log10, trig and hyperbolic functions,atan2,hypot,cbrt,PI,E, ...) andmath/pi,math/e;(MArray t)withlong-array,make-array,aget,aset,alength,aclone,amap,areduce,to-array,into-array(§2.11).to-arrayof an empty source traps for now (case 8847, open). - Inline lIR in
unsafe,fib.atomic,(spin-hint),(cache-line), theinlinemodifier (ADR 0026);fibc explain unsafe. - Live sessions forget retired texts (a long session's growth fell from about 8 MB a swap to under 2 MB over 100 swaps),
accept removals on
load, and build their checked base once (start to first result 7.8 s to 4.2 s on fib-solid). - Fixes:
(array 0 x)released its counted fill value; a JIT-compiled thread-key destructor ran after its code was freed.
0.1.17¶
- Live development:
fibc run --live FILEruns a program whose functions can be redefined while it runs, andfibc repl --connect PIDattaches to it (socket$XDG_RUNTIME_DIR/fib-live/PID.sock, JSON lines).evalredefines a function or adef;load FILEandreloadswap what an edited file changed (detected by expanded form);testruns tests inside the process (fibc test --live,fibc test --connect);watchdoes it on save;inspectandtypeanswer from the session's tables;pause/resume/retirefree old generations at quiescence. A swap takes 0.3 to 0.6 s on a 300-module application (a rebuild and restart: 8 to 10 s) and is refused (live/*codes) when it would break the checker or ownership. Redefinabledefis live-only; ahead-of-time builds keep immutable defs. Adefmay change type when its readers still check, and multi-word values are redefinable. Design:docs/design/live-repl.md,live-incremental.md,live-meshql.md. - Retirement follows indirect calls (function values,
dynmethods, library callbacks) to every generation a parked thread may return into, fixing a use-after-free of retired code. fib.os.liveand the project rule for live modules (FIB_LIVE_ROOTS,--live-deps);FIB_LIVE_EMIT=verify,FIB_LIVE_DEBUG=cut.- Gate: the live suites (
sh-live-*stamps) and their mutants (scripts/mutant-live.sh).
0.1.16¶
- The type and ownership checker keeps the checked library between programs:
emit --batch,types --batch,fibc serveandfibc replcheck the library once and reuse it (a warm server check of an edited program 165 ms to 28 ms; REPL input 188 ms to 87 ms). One-shot commands are unchanged.FIB_CHECK_CACHE=off|on|verify(verifychecks every program both ways and fails on any difference). Design and controls:docs/design/persistent-checker.md. fibc run --tracewrites its heap events through a 64 KiB buffer, flushed at exit and before any trap or abort, instead of onewriteper event (the stdlib cases run in 144 s instead of 222 s).FIB_TIME=1prints the phases of the front end (expand, lower, infer, elaborate, own).- Gate: the persistent-checker controls,
lsp-hardeningand the unit runner are faster and parallel; profile indocs/design/gate-profile.md.
0.1.15¶
- Compilation: a cache-off build can partition into units and compile them in parallel
(
FIB_LIRO_PARTITION=1,FIB_LIRO_JOBS=N,FIB_LIRO_IMPORT=Ncopies callees of at most N nodes into each unit); the cold self-build of the compiler drops from about 101 s to 35 s with byte-identical output at 1 and 8 jobs. Default builds and releases are unchanged (whole-program). Measurements and the open questions:docs/design/compile-performance.md. expand --batchexpands many files in one process from a snapshot of the library context (the compiler's golden checks use it: 944 inputs in 16 s instead of 123 s).- The gate prints a budget report (wall, parallelism, critical path) and warns on regressions
against
scripts/gate-budget.tsv(docs/design/build.md, "The gate budget"). - Documentation:
docs/design/test-pyramid.md;fibc replin the tooling guide.
0.1.14¶
- Scheduler: no spinner cap on Linux (2 on Darwin), a hint word for spinning workers,
FIB_SPINNERSandFIB_SPIN_HINT; the thread count is released before its task completes (fixes a rare early-exit race). Measurements:docs/shootout/sched-ryzen.md. - Compilation: the emitter builds structured lIR with no text intermediary (ADR 0025);
compiled-lIR objects are cached and linked per unit (ADR 0024,
--no-cache,--whole-program,--time,--cache-stats); release and bootstrap builds stay whole-program. - Unread run-time definitions and the unreachable runtime are pruned from emitted lIR
(
FIB_PRUNE=0disables); an initialiser that can trap is kept. - GPU: kernel atomics, block and warp reductions, structured control flow in WGSL,
warp shuffles (PTX
shfl.sync, WGSL subgroups), f32 atomics on WebGPU, pinned host memory and asynchronous copies (Pinned,Transfer). - C backend: no
musttailwith an argument over 16 bytes under clang on AArch64. - Documentation: a documentation site, the Hard Way course, checked examples, policy
pages;
fibc replis documented in the tooling guide.
Documentation corrections¶
The documentation now distinguishes the shipped 0.1.13 surface, historical designs and proposed 1.0 promises. No 1.0 stability commitment has been made.
Since 0.1.0 (summary through 0.1.13)¶
This is a summary of the development line, not a claim that each item first shipped in 0.1.13. Exact changes and release dates are recorded in git tags and release notes.
Recent compiler and library changes include:
- A work-stealing pool:
(fork-task f)makes a pool task (joinas any task's), with a Chase-Lev deque per worker, help-while-waiting joins, parking on an eventcount and workers started lazily on the first fork (FIB_THREADS, else the affinity mask and the cgroup quota);fib.parallel(fork,pmap,pfor,preduce,pscan) runs on it, so nested parallel calls fork tasks, not threads;spawnstays the thread tier andasyncthe stackless one. A trap in a pool task is the task's failure. See the parallelism design, 3.1 and 8. - Scalar
Optionvalues stored inline as a tag and payload, including in collection elements, closure captures and task frames. Options of ordinary objects remain nullable pointers; nested options and other payloads retain their boxed representation. See the representation design. - Last-use moves, moves of fields out of dead owned objects, and reuse of unique collection shells and arrays. Persistent updates preserve old versions when another holder exists. See the update rules.
- Fusion of a sequence bound by
letwhen it has one eligible consumer, with tests for effect order and preservation of memoization when reused. - SIMD lane values, arithmetic, masks, reductions and target-dependent widths
through
fib.simd, with native vector lowering. See the SIMD measurements. - FastISel for
fibc run -O 0, plus recorded development-loop timings. The compiler server, incremental checking and session work are described in the development-loop design; that design is not a claim that every planned command exists. - Exclusive views:
with-viewlends a writable window over anArraythat the checker proves nothing else can reach, so a loop writes in place with no copy and no per-element uniqueness test;with-tileshands disjoint windows to tasks. Windows run at about the speed of the array loop at-O 2. See the design. - aarch64:
--target TRIPLE(orFIB_TARGET_TRIPLE) emits objects and assembly for Linux, macOS and iOS triples. On an Apple M1 Ultra the cross-built compiler runs, builds itself, and reaches the same fixed point as on x86;scripts/package.shbuilds a macOS tarball. Darwin arm64 releases have been published since 0.1.7. iOS is cross-emission only; native aarch64 Linux checks are available throughmake k8s-gate K8S_ARCH=arm64. See the aarch64 design and the first numbers. - GraphQL lives in its own repository, lacewing:
lacewing (external repository; use an accessible git URL)(latest tagv0.3.0), pulled in withfibc deps add(see Projects and dependencies). It is a GraphQL query engine in the shape of Clojure's Lacinia (compiled immutable schema, resolvers as plain functions, ordered responses): typed schema construction, schema definition language (SDL) loading with resolvers attached by name, custom scalars, variables, input objects, fragments,@skipand@include, whole-document validation before any resolver runs, and resolvers that see the selections beneath their field. Breaking sincev0.2.0:GqlField.resolveris an(Option GqlResolver)(SDL fields have none until one is attached).v0.3.0can resolve a query's fields in parallel on native tasks (opt-in,execute-with), with the serial response. Not yet: mutations, subscriptions, introspection beyond__typename, enums, interfaces, unions. - meshql in fibber:
meshql-fib(meshql-fib (external repository; use an accessible git URL),v0.2.0) gives an entity a REST write surface and a GraphQL read surface (on lacewing) from one declaration, with point-in-time reads and federation of graphlettes. It is the fourth implementation of the meshql contract and passes all five tiers (37 scenarios) against SQLite (fib-db-sqlite) and PostgreSQL (fib-db-postgres);meshql serve CONFIGreads the HOCON configuration of the other implementations (fib-hocon). - HOCON configuration lives in its own repository, fib-hocon:
fib-hocon (external repository; use an accessible git URL)(tagv0.1.0), modulehocon. It has the parser, substitutions, includes, merging, durations and sizes, aconfig->recordmacro, and a differential harness against Typesafe Config; its README has the features and the measurements. - Databases:
fib.db(next.jdbc's shape:execute!,with-transaction,with-connection,plan), the driver contractfib.db.contractand an in-memory fake driverfib.db.memoryare in the library; drivers are libraries in their own repositories. The SQLite driver isfib-db-sqlite:fib-db-sqlite (external repository; use an accessible git URL), modulesqlite. The PostgreSQL driver isfib-db-postgres:fib-db-postgres (external repository; use an accessible git URL)(tagv0.1.0), modulepostgres: the wire protocol (version 3.0) written in fibber overfib.os.net, with no libpq and no C library of its own; it passesfib.db.contractagainst PostgreSQL 14, 16 and 17 and opens a connection from a libpq-shaped URL (pg/open-url). It cannot yet connect over TLS (sslmode=requireis refused:fib.tls'sSessionis notSend, so it cannot live in a connection that moves between tasks; see the Send-able TLS session design). See the contract. - Gherkin:
fib-gherkin(fib-gherkin (external repository; use an accessible git URL), modulegherkin) reads.featurefiles (Cucumber's parser, all its languages, pickles, Cucumber Expressions) and runs them onfib.testwith step definitions written in fibber, sofibc testprints the scenarios under their Gherkin names and the.featureline that did not hold. It is a front end to the system in the test harness design; the design's "plain-text front end: rejected for now" (section 2.4) is this library, built because a project asked for feature files. - GPU kernels (core, GPU-2):
(defkernel name (params) body)is a core form (spec/syntax.md 3.22); its body is the kernel subset (spec/types.md 2.17: scalars, pointers, scalar cells, arithmetic, loops, thegpu/*builtins:gpu/global-id,gpu/barrier,gpu/sharedblock-shared memory), checked at the source (a string, an allocation, a closure, a Simd value, a task, recursion, dyn dispatch are refused at their positions) and compiled for the host too (fib.gpu/host-launchruns a kernel over a grid on the CPU:fibc run examples/gpu/gpu.fib -I examples/gpu).fibc build --kernel-target nvptx64-nvidia-cudabuilds the executable with the kernels' PTX embedded (gpu/program-ptx) and beside it asOUT.ptx, with the launch ABI (each kernel's signature in the PTX header); a program with a kernel built for a platform with no kernel target is refused (no CPU fallback). The host side is thefib.gpu.deviceprotocols (Platform Device Module Kernel Buffer Stream Event), which a driver implements and a program uses without naming CUDA:fib-gpu-cuda(fib-gpu-cuda (external repository; use an accessible git URL), tagv0.1.0) passes the device contractfib.gpu.contract(7 of 7 scenarios, 3 faults caught). Measured there: fibber's shared-memory GEMM at 17.1 TFLOPS at n = 4096 (47% of cuBLAS, the CUDA C kernel's speed), bit for bit the CPU's; the GPU design has the table and what phase 2 and 3 still owe. - GPU atomics and reductions (GPU-3):
gpu/atomic-*builtins (oneatomicrmw/cmpxchgeach: PTXatom.*, WGSLatomic<u32>buffers),fib.gpu.atomic, block reductions over shared memory (fib.gpu.reduce) and grid reductions (fib.gpu.reduce-kernels) whose integer results equal the CPU's and whose f32 per-block partials are the CPU's bit for bit, run on the RTX 4080 SUPER through PTX and through WebGPU bycompiler/tests/native/gpu-device.sh(the GPU design section 12; pinned/async transfers are not done). - WebGPU (the second kernel backend, WEBGPU-1):
fibc build --target wgsl-unknown-webgpu --emit wgslprints the same kernels as WGSL compute shaders (the WebGPU design: the mapping of the kernel subset to WGSL, what is refused by name (i64, f64, pointer arithmetic beyond an index, builtins WGSL lacks), the binding model, the trap flag). They run on the native host throughfib-gpu-webgpu(fib-gpu-webgpu (external repository; use an accessible git URL), tagv0.0.1, over wgpu-native) and from a fibber program built for wasm32 through the JavaScript glueexamples/webgpu/js/fib-webgpu.mjsovernavigator.gpu(node with Dawn, Chromium). Onedefkernel, five runs:scripts/webgpu-agree.shcompares the CPU, CUDA, wgpu-native, Dawn and Chromium results by hash (bit exact where the host fusesfma; the register-tiled GEMM reaches 9.6 TFLOPS through WGSL on the same GPU where CUDA gives 10.9).
The standard library in lib/ follows Clojure's names and argument shapes,
within fibber's static types and ownership model. Its specification and
remaining work are in spec/stdlib.md. The specifications,
case headers and ROADMAP.md contain both historical records
and current rules; dated amendments identify changes.
The explicit fib.tensor numerical library adds
typed dense tensors, checked strided views, broadcasting, eager arithmetic,
fused axpby, ordered and axis reductions, boolean masks, and matrix multiplication.
Floating arithmetic uses native eight-lane f32 and four-lane f64 kernels;
matrix multiplication uses register tiles and reusable packed panels. Explicit sum-fast/dot-fast
permit reassociated reductions. After rebuilding stage 2, try
./F run examples/tensor.fib; see the
library README for API, safety contracts, and reproducible NumPy comparisons.
Fused t/dense layers apply bias and an activation as each output tile is
stored, and t/softmax and t/layernorm work row by row. On the recorded
single-thread runs, matrix multiplication is within about 1.15x of NumPy with
OpenBLAS, a float32 MLP forward pass is at parity with it, and softmax and
layernorm are faster than NumPy; reductions along the last axis are still
slower (the comparison). This is a dense numerical
foundation, not NumPy feature or performance parity.
The explicit fib.logic relational library adds
finite typed terms, persistent unification with occurs checking, fair sequential
search, and fresh/conde syntax. The same relation can infer missing values or
enumerate answers; try ./F run examples/logic.fib. Parallel search remains
future work, with this engine serving as its tested reference.
Its fib.logic.fd extension adds compact and sparse
finite integer domains, watched propagation for all-different and arithmetic
constraints, batched model setup, and smallest-domain-first search. The port of tsmarsh/sudoku
uses those constraints; build it with ./F build examples/sudoku.fib -I examples -I lib.
The finite-domain design note records
the API, provenance, validation cases, and a comparison with the original
Clojure/core.logic implementation.
The fib.os library provides typed file and descriptor
operations, directories, TCP sockets, polling, clocks, environment variables,
process identity, executable discovery, system information, secure entropy, and
bounded native memory streams. Shared errors and selected platform backends
keep libc flags, layouts, and symbols out of application code. Linux is tested
natively; the Darwin backend ran on Apple Silicon during the aarch64 work (see
its design), but is not yet part of any automated
gate. See the OS design record.
The explicit fib.http library provides shared HTTP
messages, a Ring-style HTTP/1.1 server (a task per connection, graceful stop,
slowloris deadlines) and a Hato-style client (connection pool, redirects, typed
errors, deadlines), both native over a Transport seam: no libcurl, no library
to link, and they build --static. They include binary bodies, repeated
headers, streaming bodies, chunked transfer in both directions, keep-alive and
asynchronous requests. HTTPS uses the explicit fib.tls transport via tls/https-options.
TLS is client-only and UNAUDITED; without a registered TLS transport an
https URL is a typed error, never a downgrade. See security and limits. Build the
server example with ./F build examples/http-server.fib -I lib
and the client example the same way. See the library
README for API contracts and the design record for the architecture,
limits and what is deferred.