Introduction

Amber is a small, fast, self-contained array language. The interpreter is portable C99 that builds clean on gcc and clang; the vocabulary on top of it is q/kdb+'s. It is one folder, it installs nothing system-wide, and deleting the folder uninstalls it completely.

v1.9.6 C99 · portable 287 tests AGPLv3

What it is

Amber's interpreter core is built on ngn/k, ngn's compact AGPLv3 implementation of the K array language. Amber keeps that engine's speed and small footprint and layers on:

  • the q/kdb+ working vocabulary — dictionaries, tables and keyed tables with ([]…) literal syntax, qSQL select/exec/update/delete, and the full join family: left, inner, union, plus, equi, as-of and window;
  • column attributes implemented in C`s sorted, `u unique, `p parted, `g grouped — which turn ? (find) from a linear scan into a binary search;
  • native temporal types — date, time and timestamp with literal syntax, type-aware arithmetic and a nanosecond epoch anchored at 2000-01-01;
  • a tick / HFT toolkit — a native C as-of-join kernel, a zero-allocation arena, market-data generators, OHLCV bars, VWAP, Lee-Ready trade signing and effective spread;
  • a modern REPL with a native line editor, Tab completion over your live globals and table columns, Rust-style diagnostics, a workspace inspector, an AST viewer, a bytecode disassembler and a phase profiler.

What it deliberately is not

Not a kdb+ distribution

Amber is an independent language. The interpreter is named amber, never k or q; it reads no QHOME, no config and no dotfiles, and your kdb+, kona or ngn/k installs are untouched.

Not a networked runtime

There is no AI code, no TLS and no listener anywhere in the engine repository. A listener is a policy decision — which port, which framing, which auth — and it lives outside, in amberd.

How the pieces fit

the boot path
   ./a ──► build.sh ──► cc -std=c99 src/*.c ext/*.c ──► ./amber ──► repl.k
                                        │                             │
                                        │                             └─ amber.k · fin.k · std.k
                                        │                                qsql.k · temporal.k
                                        │                                sys.k · hdb.k · ipc.k
                                        │                                lib/ext.k  (optional)
       ┌────────────────────────────────┴─────────────────────────────────┐
       │                          the interpreter                          │
       │  a.c b.c f.c h.c i.c m.c v.c …   ngn/k evaluator core, heap, verbs │
       │  p.c ast.c vm.c                  parser · `\ast` tree · `\disasm`  │
       │  3.c simd.c parallel.c peachpool.c   vector kernels · threads      │
       │  arena.c ser.c csv.c ar.c        HFT arena · -8!/-9! · CSV · Arrow │
       │  e.c diagnostic.c                the Rust-style error reporter     │
       │  inspect.c trace.c               `\v` · `\trace`                   │
       │  ln.c lnk.c                      the line editor and its `rdl` verb│
       │  ext.c                           the extension seam (src/ext.h)    │
       └───────────────────────────────────────────────────────────────────┘

Three properties of that layout are worth stating explicitly, because they are what it is for:

  • No optional feature is switched off. Everything in src/ is compiled, always. There is no build matrix and no feature flag to get wrong.
  • src/ln.c has no interpreter dependency. It includes <termios.h> and src/ext.h and nothing else of Amber's. The editor can be lifted into another project as-is.
  • Extensions never patch src/. An out-of-tree package drops .c files into ext/ and re-runs ./build.sh; they are compiled with the same flags and plug themselves in from a constructor.

A two-minute taste

amber>
/ tables are first-class and render without `show` at the interactive prompt
([]sym:`a`b`c; px:100 200 300)
/  sym px
/  -------
/  a   100
/  b   200
/  c   300

meta ([]sym:`a`b; px:1.5 2.5)      / column types + attributes (c | t a)

/ the join every tick shop needs — as-of (native C kernel since 1.9)
trade:([]sym:`a`b`a; time:3 4 9; px:100 200 300)
quote:([]sym:`a`a`b`a; time:1 5 2 8; bid:10 11 20 12)
aj[`sym`time; trade; quote]        / last quote at or before each trade

/ qSQL — type select/exec/update/delete straight, no sel"…" wrapper
select last px by sym from trade   / grouped aggregate
select from trade where px>150     / filter rows

/ binary serialization: -8! encodes any value to bytes, -9! decodes it back
b:-8!+`a`b!(1 2 3;4 5 6)
(-9!b)~+`a`b!(1 2 3;4 5 6)         / 1b — exact, attributes and nulls included

/ multi-core: peach runs f over items in parallel worker processes (no GIL)
peach[{avg x?1.0}; 8#1000000]
Bare qSQL is a REPL convenience

At the interactive prompt, select … by … from … where … works directly on the input line, and a bare table auto-renders as a grid. Inside a .k script run through ./amber file.k, wrap a bare table in show and use the sel"…" string form (or qselect/qby/qwhere directly).

Where to go next