k10
This is k10. A small array-language runtime in one C file.
A note up front. The source below is a skeleton. Many of the functions are placeholders. It does not build today. The roadmap that follows is what I intended to build on top of it: broader features, performance work, concurrency, the whole shape of a real runtime.
I pivoted before I got there. I started a different runtime and an algorithm synthesizer alongside it. That work is seeing traction with early adopters and customers, so I put k10 down. I may come back to it later and revisit.
I'm publishing the skeleton and the design notes as they were. The annotations are what I had planned for the next push. The source is the substrate they were going to land on.
The plan was to be fast because the invariants are simple. Fixed object layout. Per-thread allocation with no global locks on the common path. Dense bytecode. Zero-copy I/O. Vector kernels that specialize hard before falling back to generic logic. Hard caps where corruption would otherwise be silent.
What follows are notes on how the pieces were meant to fit. Then the source.
Object model and symbols
An 8-byte object header per value. A signed type tag distinguishes scalars from vectors. Extended tags exist only when they buy real capability.
The symbol table is treated as a performance-critical data structure, not a generic hash map. Hashing is DJB2-XOR: h = (h*33) ^ b. Cheap, branch-light. Probing uses two regions during growth so old and new can coexist. Rehashing moves a small fixed number of buckets per insert. No visible pause.
High-frequency names are pre-interned at startup so they don't re-hash on every reference. Bytecode carries interned symbol pointers where it can. Names get looked up once.
A small variadic bridge walks the platform va_list and turns variadic C calls into runtime list values. One path serves local calls, remote stubs, and internal dispatch. Errors return through a small recognizable sentinel so C-level functions can fail without being mistaken for ordinary values.
Memory
Allocation is per-thread, predictable, cheap. A pop from a free list.
Twenty-four size classes, doubling from 16 bytes upward. The size class lives in the byte just before the payload. Free is cheap. The next adjacent byte holds allocator flags: mmap-backed, arena-owned, deferred-free, special object.
Class rounding is ceil(log2((n + 7) / 16)) with bit scans. The 8-byte header fits inside a 16-byte minimum block. Buddy splits push the right half into the next lower free list.
Cross-thread free does not touch another thread's free list. It pushes onto that thread's deferred-free list, drained at safe points. Single-thread refcounts are plain ++/--. Atomics turn on only when the runtime enters multi-threaded mode.
Refcount underflow is fatal. There is a catastrophic upper ceiling on impossible allocations, well below the point where arithmetic overflow could mask the bug. Mmap-backed objects carry a marker so they release through munmap, never through the arena. Fatal paths use raw stderr; they don't trust a runtime that's already dying.
Lexer, parser, VM
Bytes are classified once through a 256-byte table. The lexer is a DFA whose states are encoded as readable single-character codes (start, digit, identifier, reject, and so on) so each transition row stays compact and cache-friendly. Comments, escaped strings, and adverb continuations are handled inside the lexer, not by parser backtracking.
Numeric suffixes resolve through a single small lookup string. Brackets are normalized into paren-like forms early so the AST and bytecode compiler stay simple.
Bytecode is dense. One byte holds a 3-bit operand shape and a 5-bit opcode. Eight operand shapes: inline, 1/2/4/8-byte immediate, object pointer, interned-symbol pointer, reserved. The first byte of a function packs local count and capability flags.
Constants and interned symbols can ride directly in the instruction stream where lifetime rules are clear. Common primitives have op-wrapped forms so the call doesn't pay full general-call overhead.
The VM stack is heap-allocated with a max-stack hint from the function header. Active frame and recursion depth live in hot thread-local slots. Lookup is O(1). Try/throw goes through longjmp. Refcounts are restored on the way out. A frame walker recovers local names and values during error reporting.
Primitives and kernels
One dispatch table for primitives, keyed by operation and arity. Not scattered conditionals. The parser and the runtime share the same operation ordering, so the IDs always agree.
AVX2 integer kernels run in 32-byte strides where the CPU allows it. Scalar fallback handles unaligned tails and older machines. SIMD output is bit-identical to scalar on edge cases; that's tested.
Atom-against-vector operations scan once with no materialization. Group-by is implemented as a dictionary from distinct value to index list, not as repeated scans. Fill-coalesce reuses the original vector and only writes the null positions. Conversion from a homogeneous record-of-arrays to a table flips by retagging in place when the shape is already valid. Generic lists promote to typed vectors when they're already homogeneous.
Radix sort handles narrow integer domains in O(N), including 16-bit integer vectors with 65,536 buckets. Structural match treats identical null sentinels as equal. It depth-checks recursion so pathological structures don't exhaust the C stack.
Serialization, IPC, compression
Predictor first, allocator once, emitter last. Nested serialization never reallocs.
Ordinary frames keep their compact length. Extended length is signaled by the high bit of an attribute byte; an 8-byte length follows when set. Attributes are clamped to a small range for external wire compatibility. UUID-shaped fields byte-swap by the envelope's byte-order flag. Symbol vectors serialize as back-to-back NUL-terminated strings.
Compression is an LZ77 variant. A 256-entry dictionary keyed by the XOR of two adjacent input bytes. LSB-first control bits, one byte per eight literal/match decisions. A match reads (index, length) and copies length + 2 bytes from the dictionary slot. The dictionary updates on every pair copied during a match run, not only on literals.
Output is hard-capped at 1 TiB before allocation. Invalid streams fail boundedly. After decode, the envelope flag is rewritten to raw so downstream logic doesn't double-decompress. The pointer-as-symbol fast path is gated to same-process traffic. It never leaves the box.
Storage, paths, and mmap I/O
Descriptor behavior is a table lookup; one per-descriptor op slot replaces repeated branching. A small registry handles path schemes: object stores, named pipes, local files, anonymous in-memory storage. Path-shaped names route to disk write, distinct from in-memory binding.
Column-table directories are recognized by a metadata-file probe before the generic directory mapping kicks in. Large columns are mmap-loaded with madvise hints: random for indexed access, sequential for streaming scans. Small reads avoid mmap overhead; large reads avoid the copy.
Codec selection inspects a fixed offset in the disk frame. Optional libraries are dlopen'd lazily so the baseline doesn't pay for codecs you never use. An absent codec is a clean runtime error, not a link-time failure.
Atomic table updates use anonymous temp files with mkstemp plus immediate unlink. Validate, then rename to commit. Mmap-backed objects release through munmap exactly once.
Event loop, sockets, HTTP, WebSocket
One epoll reactor. Sockets, TLS, timers, callbacks share it.
Timer heap indices live inside the descriptor record. No side allocations. The cleanup path drops refs, clears SSL state, and unregisters callback state in one loop. SSL_ERROR_WANT_READ and SSL_ERROR_WANT_WRITE are normalized to EAGAIN so the loop doesn't need to know about TLS. Outbound IPC uses non-blocking connect with POLLOUT or epoll writability.
DNS happens on a background pthread with condition-variable handoff. The event loop never stalls on hostname resolution. Hostnames are canonicalized before interning and connection caching.
Protocol detection is a first-byte compare against a compact HTTP method table. Native IPC, HTTP, and WebSocket can share a port. WebSocket is a five-phase state machine: head, extended length, mask, payload, unmask. Text, binary, and close opcodes are recognized explicitly.
User-defined hook handlers run under an alarm-based timeout. On expiry, evaluator state is restored; refs are not leaked. Console output is buffered through a small thread-local ring (4 KiB) to cut write calls.
Parallel evaluation and worker contexts
Worker context is small: dispatch semaphore, result slot, error slot, local arena pointer.
The parent preallocates the result list. Each worker writes into its assigned slot. No copy at the boundary. Worker allocations stay local until the result is transferred. Cross-thread release uses the owner's deferred-free list.
Entering parallel mode flips a runtime flag. Refcounts switch to atomic-safe mode. Worker errors propagate without leaking partial results. Parallel map is deterministic.
Diagnostics
Refcount underflow terminates with a clear diagnostic. Descriptor mismatch aborts the unsafe path. Fatal allocator and signal paths use raw stderr; they don't allocate, format through complex IO, or rely on a healthy runtime.
The heartbeat stops on workspace-full so a debugger can attach. SIGALRM from a callback timeout routes through a controlled stop path. Frame introspection exposes locals and stack frames on error. Top-level truncation is configurable so large values print predictably.
JSON parsing is non-recursive, with parallel stacks for state, key, value, and characters. UTF-16 surrogate pairs are handled across DFA cycles. Hostile nesting fails safely.
The rule
Every optimization declares its invariant.
- A pointer-shaped bytecode operand is valid only while its constant pool or intern table is alive.
- A mmap-backed object never returns to an arena free list.
- A pointer-as-symbol IPC frame never crosses a process or machine boundary.
- A promoted homogeneous list preserves the original semantics for type, nulls, and attributes.
- A worker writes only to its assigned parent result slot.
The intent was to be fast because these invariants are narrow, explicit, and tested. The intent stayed an intent.
Source
One translation unit. As noted above, this is a skeleton with placeholders and does not currently build. It's archived here as the substrate the design notes were going to land on.
/* (c) Praveen Vaddadi 2020 thynktank@gmail.com */
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/epoll.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <fcntl.h>
#include <errno.h>
#include <dlfcn.h>
#include <termios.h>
#include <signal.h>
#include <immintrin.h>
typedef long J;
typedef int I;
typedef char *S;
typedef void V;
typedef double F;
typedef unsigned char G;
typedef unsigned long uJ;
typedef unsigned int uI;
typedef short I16;
typedef unsigned short uI16;
#define R return
#define K_WAIT(f, e) epoll_wait(f, \
(struct epoll_event *)&e, 1, -1)
typedef struct {
long nproc, mem, phys;
I epoch, server;
char *script;
} K10Main;
typedef __m256i int256_t;
typedef struct {
__m256i lo;
__m256i hi;
} int512_t;
typedef struct {
G size_class;
G _pad[3];
I refcount;
I length;
G _pad2[3];
G type;
} KObjectHeader;
enum KTypeTag {
K_TYPE_LIST = 0,
K_TYPE_PAIR_CHAIN = 1,
K_TYPE_DICT = 6,
K_TYPE_FUNC = 7,
K_TYPE_BOOL = 8,
K_TYPE_SHORT = 12,
K_TYPE_INT = 13,
K_TYPE_LONG = 14,
K_TYPE_PAIR = 15,
K_TYPE_FLOAT = 0x21,
K_TYPE_SYM = 0x32,
K_TYPE_CHAR_BOX = 0x38,
K_TYPE_CHAR = 0x30,
K_TYPE_PAIR_IMMEDIATE = 0xfa,
K_TYPE_DEPTH_MARKER = 0xfc,
K_TYPE_PAIR_CELL = 0xfd,
K_TYPE_KEYED_PAIR = 0xfe,
K_TYPE_LITERAL_FUNC = 0xff
};
#define P(c, a) if (c) R a
#define K_IS_ERR(x) ((uJ)((x) - 1) < 0xfu)
#define K_IS_HEAP(x) (((uJ)(x) >> K_TAG_SHIFT) == 0 && \
(uJ)(x) >= K_HEAP_LOW_ADDR)
#define K_SYM_INDEX_CUTOFF 0x100000ULL
#define K_MAX_VECTOR_LEN 0x10000000
#define K_MIN_VALID_HEAP_ADDR 0x100ULL
#define K_ERR_PAYLOAD_MAX 0xfu
#define K_TAG_SHIFT 56
#define K_TAG_MASK 0xff00000000000000ULL
#define K_PTR_MASK 0x0000ffffffffffffULL
#define K_TAG(t) \
((uJ)(G)(t) << K_TAG_SHIFT)
#define XC(x) (*(G *)((J)(x) - 16))
#define XR(x) (*(I *)((J)(x) - 12))
#define XT(x) (*(G *)((J)(x) - 5))
#define XN(x) (*(I *)((J)(x) - 4))
#define XA(x) (*(G *)((J)(x) - 6))
#define TAG(x) ((G)((uJ)(x) >> K_TAG_SHIFT))
#define UNMASK(x) ((J)(x) & K_PTR_MASK)
#define EPOCH_2001_OFFSET_S 978307200LL
#define NS_PER_SEC_F 1e9
#define K_LINE_HISTORY_CAP 100
#define K_TAGCLASS_HEAP_BOXED 0x7800e0e0c005ULL
#define K_TAGCLASS_PAIR_PAYLOAD 0x500000008000ULL
#define K_TAGCLASS_ATOMIC_BOX 0x2800e0e04005ULL
#define K_TAGCLASS_INT32_LANE 0x4001f1f2000ULL
#define K_TAGCLASS_SCALAR_IMMED 0x7ff1f1f3ffaULL
#define IS_IN_CLASS(cls, tag) (((cls) >> (tag)) & 1ULL)
#define TEST_BITQ(mask, bit) IS_IN_CLASS(mask, bit)
#define IPC_MAX_CLIENTS 16
#define IPC_BYTE_ORDER_LE 0x01u
#define IPC_MSG_TYPE_ASYNC 0
#define IPC_MSG_TYPE_SYNC 1
#define IPC_MSG_TYPE_RESPONSE 2
#define IPC_OKK_MAX_BODY (1u << 30)
#define IPC_SYNC_TIMEOUT_MS 30000
#define BYTECODE_LOCALS_MAX 32
#define BYTECODE_STACK_DEPTH 1024
#define K_BC_STACK_SLOTS BYTECODE_STACK_DEPTH
#define K_BYTECODE_LOCALS_OFF 0
#define K_BYTECODE_GLOBALS_OFF 1
#define K_BC_OP_INDEX_LO 0x60
#define K_OP_LOCAL_THRESHOLD 0x80
#define K_OP_GLOBAL_THRESHOLD 0xc0
#define K_OP_CLASS_EXTENDED 0xff
#define K_NAMESPACE_SLOTS 128
#define KMINI_MAX_BINDINGS 16
enum K10Opcode {
OP_PUSH = 0x01, OP_LOAD = 0x02, OP_STORE = 0x03,
OP_JMP = 0x04, OP_JIF = 0x05, OP_RETURN = 0x06,
OP_DISPATCH = 0x07, OP_CALL_VERB = 0x08
};
#define K_ASCII_SPACE 32
#define K_BYTE_HIGH_BIT_MASK 0xfe
#define K_TYPE_PAIR_IMMEDIATE_LO 0xfa
#define K_MMAP_HIGH_BUDGET_LO 0x100000
#define K_MMAP_HIGH_BUDGET_HI 0x10000000
#define K_PRINT_TAB_INDEX 0x32
#define K_VERB_GROUP_PRIME 0x2b
#define K_BIT_INDEX_DIGIT_BASE 0x30
#define K_BIT_INDEX_DIGIT_END 0x39
#define K_BIT_INDEX_DOT 0x2e
#define K_BIT_INDEX_COLON 0x3a
#define K_TYPE_BASE_BOX_TAG 0x40
#define K_TYPE_DICT_TAG 0x80
#define K_BIGINT_LIMB_BYTES 4
#define K_BIGINT_LIMB_BITS 32
#define K_UTF8_ASCII_MAX 0x80
#define K_UTF8_CONT_HEADER 0x80
#define K_UTF8_2BYTE_LEAD 0xc0
#define K_UTF8_3BYTE_LEAD 0xe0
#define K_UTF8_4BYTE_LEAD 0xf0
#define K_UTF8_2BYTE_BOUND 0x800
#define K_UTF8_3BYTE_BOUND 0x10000
#define K_UTF16_SURROGATE_HI 0xd800
#define K_UTF16_SURROGATE_LO 0xdc00
#define K_UTF16_SURROGATE_END 0xe000
#define K_UTF16_HALF_BITS 10
#define K_TLS_HEAP_PAD_BYTES 0x80
#define K_HEX_LITERAL_DIGITS 0xf
#define K_TYPE_TAG_LITFUNC 0xff
#define K_TYPE_TAG_KEYEDPAIR_LO 0xfe
#define K_TYPE_TAG_PAIRIMM_LO 0xfa
#define K_BIGINT_LIMB_MAX 0xffffffff
#define K_PAYLOAD_BITS_64_HIGHHALF 0xffffffff00000000ULL
#define K_LANE_BYTES_8 8
#define K_BYTECODE_OPCODE_BITS 5
#define K_BYTECODE_SHAPE_BITS 3
#define K_DEFAULT_TAB_WIDTH 8
#define K_FRAME_HEAD_BYTES_8 8
#define K_DICT_INIT_BUCKETS 0x10
#define K_REGISTER_BYTES 8
#define K_ASCII_TAB 0x09
#define K_ASCII_NEWLINE 0x0a
#define K_ASCII_CR 0x0d
#define K_ASCII_PRINTABLE_LAST 0x7e
#define K_ASCII_DEL 0x7f
#define K_TYPE_TAG_RANGE_MAX 0x3e
#define K_MAX_ATOM_RANGE 0x3f
#define K_OP_LOCAL_BIAS 0xc0
#define K_BYTECODE_LOCAL_LIMIT 0x1f
#define K_LOG2_BITS_INDEX_MASK 0x23
#define K_KEYWORD_REF_TAG 0x2b
#define K_REPL_LINE_BUF_BYTES 0x100
#define K_PRECOMPILED_F0 0xf0
#define K_TYPE_PAIR_PACK 0x10
#define K_TOP_TAG(x) ((G)((uJ)(x) >> K_TAG_SHIFT))
#define K_TAG_INT_FAMILY(t) ((t) == K_TYPE_INT || (t) == K_TYPE_LONG)
#define K_TAG_NUMERIC_MIX(t) (K_TAG_INT_FAMILY(t) || (t) == K_TYPE_FLOAT)
#define K_PAYLOAD_PTR(x) ((V *)((uJ)(x) & K_PAYLOAD_BITS_48))
#define K_VEC_BYTES(n, t) ((uJ)(n) << k_type_log2_bits_table[(t)])
#define K_RUNTIME_HEADER_OK(p) ((p) != 0 && (uJ)(p) >= K_HEAP_LOW_ADDR)
#define K_BSR_TO_CLASS(b) ((b) > K_SLOT_LOG2_BASE ? (b) - K_SLOT_LOG2_BASE : 0)
#define K_IS_ERR_RETURN(x) K_IS_ERR(x)
#define K_CLIENT_FD_OK(fd) ((fd) >= 0 && (fd) < IPC_MAX_CLIENTS)
#define K_CLIENT_FLAG_SET(fd,v) (client_established_flags[fd] = (v))
#define K_CLIENT_IS_ESTABLISHED(fd) (client_established_flags[fd])
#define K_BYTE_MAX 0xffu
#define K_NIBBLE_MAX 0xfu
#define K_BYTE_SIGN_BIT 0x80u
#define K_LANE_BYTES_16 16
#define K_LANE_BYTES_32 32
#define K_AVX2_STRIDE_BYTES 32
#define K_TYPE_TAG_MASK 0x3fu
#define K_HEAP_LOW_ADDR 0x100u
#define K_TYPE_F64_VEC 0x2a
#define K_TYPE_LIT_AST_VERB 0x21
#define K_PAGE_BYTES 0x1000
#define K_PAYLOAD_BITS_48 0xffffffffffffULL
#define K_PAYLOAD_BITS_32 0xffffffffu
#define K_PAYLOAD_BITS_16 0xffffu
#define K_PAYLOAD_BITS_8 0xffu
#define K_HEX_8BIT_HIGH 0x80
#define K_HEX_BRACKET_CLASS 0x10
#define K_HEADER_BYTES 16
#define K_ALLOC_ROUND 16
#define K_SLOT_LOG2_BASE 4
#define K_LOG2_BITS_TO_CLASS_BIAS 3
#define K_CLASS_MAX 24
#define KA_ARENA_BYTES (1ull << 20)
#define K_PAYLOAD_MASK K_PTR_MASK
#define K_TRUTHY_FALSE_MAX 0x10
#define SYMBOL_INTERN_TABLE_SIZE (1 << 16)
#define HISTORY_MAX K_LINE_HISTORY_CAP
#define K_ERR_PARSE 3LL
#define NS_PER_SEC 1000000000LL
#define JULIAN_GREGORIAN_OFFSET 1721119
#define JULIAN_QUAD_FP_SCALE 4LL
#define LAZY_TBL_OPS 0
#define LAZY_TBL_KCSV 1
#define LAZY_TBL_EXT_LIST 2
#define FFI_LAZY 0x1
#define FFI_SIG_INT 'i'
#define FFI_SIG_FLOAT 'f'
#define FFI_SIG_STRING 's'
typedef J (*FFI_0arg)(void);
typedef J (*FFI_1arg)(J);
typedef J (*FFI_2arg)(J, J);
typedef J (*FFI_3arg)(J, J, J);
typedef J (*FFI_4arg)(J, J, J, J);
enum KValKindEnum {
K_VAL_LONG = 1, K_VAL_FLOAT, K_VAL_SYM, K_VAL_LIST,
K_VAL_CHAR_VEC, K_VAL_LONG_VEC, K_VAL_FLOAT_VEC
};
enum KAstKindEnum {
K_AST_LIT = 1, K_AST_NAME, K_AST_VERB, K_AST_LAMBDA,
K_AST_EACH, K_AST_OVER, K_AST_SCAN, K_AST_INDEX,
K_AST_BIND, K_AST_DYAD
};
enum KTokKindEnum {
KTOK_END = 0, KTOK_LP, KTOK_RP, KTOK_LB, KTOK_RB,
KTOK_LCURLY, KTOK_RCURLY, KTOK_OP, KTOK_LONG, KTOK_FLOAT,
KTOK_NAME, KTOK_STR, KTOK_SYM, KTOK_SEMI, KTOK_TICK
};
enum KLexErr {
KLEX_ERR_NONE = 0, KLEX_ERR_BAD_BYTE,
KLEX_ERR_UNTERM_STR, KLEX_ERR_NEEDS_FULL_PARSER
};
typedef G K_U8;
typedef uI U32;
typedef I KTokKind;
typedef I KAstKind;
typedef I KValKind;
typedef struct KTok {
KTokKind kind;
char op;
J lval;
F fval;
char text[256];
} KTok;
typedef struct KLex {
const char *src;
I err;
KTok cur;
} KLex;
typedef V (*KLexHandler)(KLex *, G);
typedef struct TokenSpan {
const char *start;
const char *end;
KTokKind kind;
} TokenSpan;
typedef struct KAst {
KAstKind kind;
char op;
char name[32];
struct KAst *a, *b;
struct KAst **kids;
I n_kids;
struct KAst **params;
I n_params;
struct KAst *arena_next;
J l;
F f;
J lval;
F fval;
} KAst;
typedef struct KVal {
KValKind kind;
uJ n;
J l;
F f;
char sym[32];
J *list;
J *lvec;
F *fvec;
char *cvec;
} KVal;
typedef struct SymbolInternEntry {
const char *name;
I len;
J value;
uJ hash;
I used;
I index;
} SymbolInternEntry;
typedef struct FFIModule {
V *handle;
const char *name;
const char *path;
I flags;
struct FFIModule *next;
} FFIModule;
typedef struct HashDictEntry {
J key;
J val;
uJ hash;
I used;
} HashDictEntry;
typedef struct HashDict {
HashDictEntry *entries;
uJ cap;
uJ capacity;
uJ count;
J *keys;
J *vals;
} HashDict;
typedef struct GradeNode { I idx; I orig_idx; J key; J value; } GradeNode;
typedef struct CommandLineArgs {
I argc;
char **argv;
const char *script_path;
const char *expression;
I port;
I memory_mb;
I verbose;
I quiet;
} CommandLineArgs;
typedef struct LineReader {
I fd;
char *buf;
char *buffer;
I pos;
I buffer_pos;
I cap;
I buffer_used;
I eof_seen;
} LineReader;
typedef struct ReplHistory {
char **lines;
I count;
I head;
I cursor;
} ReplHistory;
typedef struct StdoutBuffer {
char *buf;
char *bytes;
uJ off;
uJ cap;
uJ length;
} StdoutBuffer;
typedef struct StringBuilder {
char *buf;
uJ off;
uJ cap;
uJ length;
uJ capacity;
} StringBuilder;
typedef struct SimpleSpinLock {
volatile I held;
volatile I locked;
} SimpleSpinLock;
typedef struct KMiniBinding {
char name[32];
J val;
KVal *value;
char storage[1024];
I used;
} KMiniBinding;
typedef J *K;
typedef V (*HeapVisitorFn)(V *obj, V *user);
typedef V *(*K_alloc_into_fn)(V *dst, J payload);
typedef V *(*K_unary_fn)(V *);
typedef V *(*K_unary_atom_fn)(J);
typedef V *(*K_dyadic_atom_fn)(J, J);
typedef V *(*K_dyadic_left_fn)(J, V *);
typedef V *(*K_promote_fn)(V *target, V *vec);
typedef V *(*K_triadic_each_fn)(V *, V *, V *);
J runtime_heap_size_bytes;
J runtime_heap_base;
J extension_keyword_table;
J loader_keyword_table;
J dyadic_keyword_table;
J *runtime_sym_table_charvecs;
J runtime_root_namespace_anchor;
G k_type_log2_bits_table_alias[64];
#define k_type_log2_bits_table k_type_log2_bits_table_alias
G k_type_column_class_table[64];
extern G *numeric_suffix_letters;
extern G month_letter_signature_table[12];
extern G *temporal_suffix_letters_a;
extern G *temporal_suffix_letters_b;
extern G date_field_letters_a[24];
extern G date_field_letters_b[24];
uJ terminal_size_packed;
char stdin_line_buffer[K_REPL_LINE_BUF_BYTES];
I epoll_instance_fd;
I epoll_scratch_fd;
struct epoll_event epoll_scratch_event;
I connected_client_count;
I client_established_flags[IPC_MAX_CLIENTS];
J pending_reply_queue [IPC_MAX_CLIENTS];
struct ipc_send_chunk {
struct ipc_send_chunk *next;
char *data;
I len;
I off;
};
struct ipc_client_state {
I fd;
I have_hdr;
I have_body;
I body_len;
G hdr[16];
char *body;
struct ipc_send_chunk *send_head;
struct ipc_send_chunk *send_tail;
};
struct ipc_client_state *ipc_client_table[IPC_MAX_CLIENTS];
I primary_client_send_fd;
J primary_client_send_buffer;
J secondary_send_buffer;
G ieee_f64_sign_lane[16] __attribute__((aligned(16))) = {
0,0,0,0,0,0,0,0x80, 0,0,0,0,0,0,0,0x80
};
J verb_dispatch_primary[256];
J verb_dispatch_secondary[256];
extern const G *const k10_punct;
#define LEX_BYTE_CLASS k10_punct
typedef struct K10VM {
char *ip;
char *end;
J *sp;
V *locals;
V *globals;
J *gv;
J *gv3;
J *err;
} K10VM;
G compare_left_class [128];
G compare_right_class [128];
G compare_promote_class [128];
G bracket_pair_class [128];
G adverb_continuation_set [128];
G keyword_table_aggregate [128];
G keyword_table_select [128];
G keyword_table_temporal [128];
G stmt_terminator_set [128];
#define K_OP_CONSTPOOL_BIAS 0xa0
#define K_OP_EXT_BIAS 0xff
#define HASH_DICT_INITIAL_CAP 16
#define STDOUT_BUFFER_SIZE 4096
#define K_AST_NIL 0x10
#define K_AST_LONG 0x11
#define K_AST_FLOAT 0x12
#define K_AST_SYM 0x13
#define K_AST_LIST 0x14
#define K_AST_PAREN 0x15
typedef uI16 uH;
typedef V *(*K_triadic_verb) (V *, V *, V *);
typedef V *(*K_tetradic_verb) (V *, V *, V *, V *);
J parse_cursor;
J parse_token_start;
J parse_function_locals;
J parse_in_dyadic_context;
J csv_format_lambda;
J runtime_long_vector_16mb;
J runtime_long_vector_25mb;
J runtime_combined_pair_chain;
J runtime_inv_sqrt_lambda;
J runtime_random_lambda;
J runtime_count_dispatch;
J runtime_xyz_sym_vector;
J runtime_empty_atom_list_sentinel;
J runtime_builtin_sym_table;
J *symbol_intern_table;
G k_type_cast_gradient_table[64];
G k_type_dyadic_index_table[64];
G k_type_log2_bits_compare_table[64];
G verb_class_classifier_def[256];
#define verb_class_classifier verb_class_classifier_def
G list_format_template[256];
V *verb_byte_apply_at (G op, V *l, V *r) { (void)op;(void)l; return r; }
V *verb_byte_index_at (G op, V *l, V *r) { (void)op;(void)l; return r; }
V *verb_byte_take_from_left(G op, V *l, V *r) { (void)op;(void)r; return l; }
V *verb_byte_drop_from_left(G op, V *l, V *r) { (void)op;(void)r; return l; }
V *apply_unary_each(K_unary_fn f, V *vec) {
if (!f || !vec) return vec;
I n = XN(vec);
J *out = allocate_typed_vector(K_TYPE_LIST, n);
for (I i = 0; i < n; i++)
out[i] = (J)f((V *)((J *)vec)[i]);
return out;
}
V *apply_unary_or_singleton(V *vec, J aux, I flg) {
(void)aux; (void)flg; return vec;
}
V *apply_functor_atomic(V *f, V *arg, J aux, I flg) {
(void)aux; (void)flg;
if (!f) return arg;
return ((K_unary_fn)f)(arg);
}
V *format_value_recursive (V *val) { return val; }
V *format_one_node_for_display(V *node){ return node; }
V *render_node_passthrough (V *node) { return node; }
V *emit_pad_for_print_lhs(I pad_total, J *value) {
(void)pad_total; return (V *)value;
}
I compare_lt_general(V *a, V *b) { return (uJ)a < (uJ)b ? -1 : (a == b ? 0 : 1); }
V *generic_atom_lt (V **a, V **b, I op, I flg) {
(void)op; (void)flg;
return (V *)(uintptr_t)((uJ)a < (uJ)b);
}
I tagged_atom_equal (J a, J b) { return a == b; }
V *index_at_atom_adapter (V *vec, J idx) {
if (!vec) return 0;
return (V *)((J *)vec)[idx & (XN(vec) - 1)];
}
V *index_at_vector_adapter(V *vec, V *idxs) { (void)idxs; return vec; }
V *cast_dyadic_pair_chain (V *l, V *r, I flg){ (void)r; (void)flg; return l; }
V *bitwise_complement_in_place(V *vec) {
if (!vec) return vec;
uJ n = (uJ)XN(vec);
G *p = (G *)vec;
for (uJ i = 0; i < n; i++) p[i] = ~p[i];
return vec;
}
V *long_vector_neg (V *vec) {
if (!vec) return vec;
J *p = (J *)vec; I n = XN(vec);
for (I i = 0; i < n; i++) p[i] = -p[i];
return vec;
}
V *monadic_reverse (V *vec) {
if (!vec) return vec;
J *p = (J *)vec; I n = XN(vec);
for (I i = 0, j = n - 1; i < j; i++, j--) {
J t = p[i]; p[i] = p[j]; p[j] = t;
}
return vec;
}
V *monadic_distinct_long(V *vec) { return vec; }
V *monadic_where_indices(V *vec) { return vec; }
V **canonicalize_int_typed (J *vec, J a2, J a3, I flg)
{ (void)a2;(void)a3;(void)flg; return (V **)vec; }
V **canonicalize_other_typed (J *vec, J a2, J a3, I flg)
{ (void)a2;(void)a3;(void)flg; return (V **)vec; }
V **canonicalize_pair_chain_typed(J *vec, J a2, J a3, I flg)
{ (void)a2;(void)a3;(void)flg; return (V **)vec; }
V **canonicalize_temporal_typed (J *vec, J a2, J a3, I flg)
{ (void)a2;(void)a3;(void)flg; return (V **)vec; }
V *box_immediate_to_heap(J v) {
J *out = allocate_typed_vector(K_TYPE_LONG, 1);
if (out) out[0] = v;
return out;
}
V *ensure_singleton_or_box(V *v, J aux, I flg) {
(void)aux; (void)flg; return v;
}
V *dict_keys(V *dict) {
if (!dict) return 0;
return (V *)((J *)dict)[0];
}
V *read_file_to_charvec(const char *path) {
if (!path) return 0;
I fd = open(path, O_RDONLY);
if (fd < 0) return 0;
struct stat st;
if (fstat(fd, &st) < 0) { close(fd); return 0; }
I n = (I)st.st_size;
J *buf = allocate_typed_vector(K_TYPE_CHAR, n);
if (!buf) { close(fd); return 0; }
I off = 0;
while (off < n) {
I r = (I)read(fd, (char *)buf + off, (size_t)(n - off));
if (r <= 0) break;
off += r;
}
close(fd);
return buf;
}
struct TlsHeap {
J bytes_alloc;
J freelist [K_CLASS_MAX + 1];
G pad[K_TLS_HEAP_PAD_BYTES];
J remote_free_head;
uJ remote_drain_count;
};
static V k10_start_main(J c, J v, V (*f)(void));
V _start(J c, J v, V (*f)(void));
V k10_init_pad(void);
V k10_dereg_tm(void);
V k10_reg_tm(void);
V k10_dtors_aux(void);
V k10_j_reg_tm(void);
J k10_now_ns(void);
J k10_write_err(const char *s);
V k10_sig_int(I s);
V k10_sig_term(I s);
I k10_int_was(void);
I k10_shut_was(void);
V k10_sig_init(void);
V k10_line_restore(void);
I k10_line_raw_set(I fd);
I k10_line_raw(void);
V k10_hist_shift(void);
V k10_hist_push(const char *s);
S k10_hist_path(void);
V k10_hist_add_line(char *b);
V k10_hist_load(void);
V k10_hist_save(void);
V k10_line_redraw(const char *pr, I pl, const char *b, I bl, I c);
static V k10_line_reprompt(const char *p, I pl, I *bl, I *c);
static V k10_line_del_at(const char *p, I pl, S b, I *bl, I *c);
static V k10_line_backspace(const char *p, I pl, S b, I *bl, I *c);
static V k10_line_kill_left(const char *p, I pl, S b, I *bl, I *c);
static V k10_line_kill_word(const char *p, I pl, S b, I *bl, I *c);
static V k10_line_home(const char *p, I pl, S b, I *bl, I *c);
static V k10_line_end(const char *p, I pl, S b, I *bl, I *c);
static V k10_line_clear(const char *p, I pl, S b, I *bl, I *c);
static V k10_line_insert(G ch, const char *p, I pl, S b, I *bl, I *c);
static V k10_line_h_load(I i, const char *p, I pl, S b, I *bl, I *c);
static V k10_line_up(const char *p, I pl, S b, I *bl, I *c, I *hi, S sc, I *scl);
static V k10_line_dn(const char *p, I pl, S b, I *bl, I *c, I *hi, S sc, I *scl);
static V k10_line_esc_digit(const char *p, I pl, S b, I *bl, I *c, G s1);
static V k10_line_esc_move(G m, const char *p, I pl, S b, I *bl, I *c, I *hi, S sc, I *scl);
static V k10_line_esc(const char *p, I pl, S b, I *bl, I *c, I *hi, S sc, I *scl);
static V k10_key_eof(const char *p, I pl, S b, I *bl, I *c);
static V k10_key_ctrl(G ch, const char *p, I pl, S b, I *bl, I *c, I *hi, S sc, I *scl);
static V k10_line_dispatch(G ch, const char *p, I pl, S b, I *bl, I *c, I *hi, S sc, I *scl);
static I k10_line_step(const char *p, I pl, S b, I *bl, I *cur, I *hi, S sc, I *scl);
static I k10_line_fin(S out, S b, I bl, I cap);
static I k10_line_loop(const char *p, I pl, S b, I *bl, I *c, I *hi, S sc, I *scl);
static I k10_line_run(const char *p, S out, I cap);
static J k10_read_raw(S p);
static J k10_read_cooked(J pr);
J k10_read_line(J prompt);
J k10_println(V **obj);
J k10_f_to_c(F v);
F k10_strtod(I n, S b);
J k10_p_long(J v);
F k10_p_double(F v);
S k10_ser_typed(S body, V *src, G t, uI n);
S k10_ser_boxed(S base, S body, S *cur, J val, uJ tag);
S k10_ser_list(S base, S body, V *src, uI n);
V k10_ser_v_payload(J *dst, J v, G t);
S k10_ser_val(J *dst, J val);
S k10_ser_obj(S base, J *dst, V *src, I dt);
uJ k10_dec_small(S p, uJ t, I b);
static uJ k10_dec_atom_special(S p, uJ t);
uJ k10_dec_atom(J *c, S p, uJ t);
uJ k10_dec_vec(J *c, S p, S b, G t, uI n);
uJ k10_dec_list(J *c, G t, uI n);
uJ k10_dec_comp(J *c, S p);
uJ k10_dec_val(J *c);
uJ k10_dec_rel(V **b);
V k10_log_init(I *pa);
static V k10_log_msg_append(J *e);
J *k10_log_msg(V **v, J a2, J a3, I a4);
V k10_log_exit(I status);
static J k10_ipc_tag(void);
static S k10_ipc_text(uJ fd, I fl, V *v);
static S k10_ipc_dec(S r);
static S k10_ipc_match(uJ fd, J h, S r, J tag, J s);
static S k10_ipc_wait(uJ fd, J h, S r, J tag);
static S k10_ipc_sync(uJ fd, J h, V *v, V **p, J aux);
static V k10_ipc_enc_req(V **p);
S k10_ipc_send(I fl, V *v, V **p, J aux);
V k10_diag_len(V **wp);
V **k10_diag_fmt(V **f);
V **k10_diag_print(V *v);
J k10_p_rel(J p, uJ *v);
V **k10_fmt_val(V **v, J a2, I a3);
J *k10_read_file_dec(V **m, size_t l, I (*r)[4]);
J *k10_run_cd(V *a, S b, S t);
J *k10_run_l(V *a);
V k10_run_sh_child(I p[2], J *o);
J *k10_run_sh_parent(I fd);
J *k10_run_sh(S b);
J *k10_run_cmd(I n, S b);
J *k10_parse_script(S p);
J k10_chdir_ok(V **p);
J k10_chdir_err(V **p);
J k10_chdir(V **p, J a2, I a3);
static I k_value_pointer_looks_sane(uJ value);
uJ emit_initial_eval_result(uJ value, J a2, J a3, I a4);
static J *k10_eval_print(J *p);
J *k10_eval_line(char *l, J a, I b);
J k10_mmap_high(uJ s);
J k10_mmap_file(I a, J ad, uJ s, I fd);
static J k10_est_atom(K_U8 t, J h);
static J k10_est_vec(K_U8 it, uJ len);
static J k10_est_list(J h, J *v, uJ len);
J k10_est_size(J h, J *v, J a);
static V *k10_ser_vec(int8_t *d, V *v, K_U8 it, uI len);
V *k10_ser_compact(int8_t *c, V *v);
J k10_file_size(char *p);
J k10_res_script(V **a1, char *a2);
uJ k10_send_framed(I fd, V **p);
J k10_read_exact(I fd, I w, J b);
J k10_epoll_add(V *f_arg);
J k10_intern_cstr(J *c);
J k10_char_to_k(V *b);
static uJ k10_res_punct_op(I b);
static uJ k10_res_punct_main(I b, I k, I v);
static uJ k10_res_punct_key(I b, I k, I v);
uJ k10_res_punct(I b);
static J *k10_bc_slot(G i, V *l, V *g, J *v);
static V k10_vm_init(K10VM *v, J *fn, V *l, J *g);
static J *k10_op_ext(K10VM *v, K_U8 op);
static J *k10_op_const(K10VM *v, K_U8 op);
static J *k10_op_slot_const(K10VM *v, K_U8 op);
static J *k10_op_typed_word(K10VM *v, K_U8 op);
static J *k10_op_typed_dot(K10VM *v, K_U8 op);
static J *k10_op_typed(K10VM *v, K_U8 op, K_U8 cls);
static J *k10_prim_idx(K10VM *v);
static J *k10_prim_idxg(K10VM *v);
static J *k10_prim_cmp(K10VM *v);
static J *k10_prim_chk(K10VM *v);
static J *k10_op_prim(K10VM *v, K_U8 op);
static J *k10_vm_step(K10VM *v);
J *k10_eval_bc(J *fn, V *l, J *g);
uJ k10_is_truthy(V **v);
static V *kmini_arena_alloc(size_t n);
static V k10_arena_reset(void);
static KAst *k10_ast_new(KAstKind k);
static KVal *k10_val_new(KValKind k);
static KMiniBinding *k10_bind_lookup(const char *n);
static I k10_persist_vec(KMiniBinding *b, const V *v, size_t n, size_t *o);
static KVal *k10_val_persist(const KVal *s, KMiniBinding *b);
static V k10_bind_store(const char *n, const KVal *v);
static I k10_is_op(char c);
static V k10_lex_comment(KLex *L, G c);
static V k10_lex_paren(KLex *L, G c);
static V k10_lex_bracket(KLex *L, G c);
static V k10_lex_curly(KLex *L, G c);
static V k10_lex_simple(KLex *L, KTokKind k);
static V k10_lex_bang(KLex *L, G c);
static V k10_lex_colon(KLex *L, G c);
static char k10_lex_escape(char c);
static V k10_lex_string(KLex *L, G c);
static V k10_lex_symbol(KLex *L, G c);
static F k10_lex_pow10(I exp);
static V k10_lex_num(KLex *L, G c);
static V k10_lex_name(KLex *L, G c);
static V k10_lex_op(KLex *L, G c);
static V k10_lex_cmp(KLex *L, G c);
static V k10_lex_slash(KLex *L, G c);
static V k10_lex_bad(KLex *L, G c);
V k10_lex_advance(KLex *L);
static I k10_is_primary(const KTok *t);
static I k10_is_verb(char op);
static KAst *k10_post_each(KLex *L, KAst *left);
static KAst *k10_post_over(KLex *L, KAst *left);
static KAst *k10_post_scan(KLex *L, KAst *left);
static KAst *k10_post_as(KLex *L, KAst **as, I *an);
static KAst *k10_post_idx_mk(KAst *left, KAst **as, I n);
static KAst *k10_post_idx(KLex *L, KAst *left);
static KAst *k10_parse_post(KLex *L, KAst *left);
static KAst *k10_ast_list(KAst **src, I n);
static KAst *k10_new_num(KLex *L);
static KAst *k10_absorb_vec(KLex *L, KAst *h);
static I k10_par_p(KLex *L, KAst *lam);
static I k10_par_b(KLex *L, KAst **body);
static KAst *k10_parse_lam(KLex *L);
static KAst *k10_parse_num(KLex *L, KAstKind kind);
static KAst *k10_parse_name(KLex *L, KAstKind kind);
static KAst *k10_parse_str(KLex *L);
static KAst *k10_parse_lam_prim(KLex *L);
static KAst *k10_ast_verb(char op);
static KAst *k10_par_adv(KLex *L, char op);
static KAst *k10_p_vn(KLex *L);
static KAst *k10_p_ls(KLex *L, KAst *f);
static KAst *k10_parse_paren_prim(KLex *L);
static KAst *k10_parse_monad(KLex *L);
static KAst *k10_parse_adv_pre(KLex *L);
static KAst *k10_parse_prim(KLex *L);
static KAst *k10_parse_bind(KLex *L, KAst *left);
static KAst *k10_parse_dyad(KLex *L, KAst *left);
static KAst *k10_parse_expr(KLex *L);
static I k10_is_num_val(const KVal *v);
static F k10_to_f64(const KVal *v, I i);
static J k10_to_i64(const KVal *v, I i);
static I k10_val_len(const KVal *v);
static I k10_is_f64(const KVal *v);
static KVal *k10_mk_i64(J l);
static KVal *k10_mk_f64(F f);
static KVal *k10_mk_i64v(I n);
static KVal *k10_mk_f64v(I n);
static KVal *k10_arith_div(char op, F x, F y, I flt);
static KVal *k10_arith(char op, F x, F y, I flt);
static KVal *k10_cat(KVal *a, KVal *b);
static KVal *k10_at_val(KVal *a, KVal *b);
static KVal *k10_dy_v(char op, KVal *a, KVal *b);
static KVal *k10_dyad(char op, KVal *a, KVal *b);
static KVal *k10_mon_neg(KVal *a, I n);
static KVal *k10_mon_rev(KVal *a, I n);
static KVal *k10_mon_not(KVal *a, I n);
static KVal *k10_mon_where(KVal *a, I n);
static KVal *k10_monad(char op, KVal *a);
static I k10_is_err(const KVal *v);
static KVal *k10_mk_err(const char *name);
static KVal *k10_apply(KAst *fn, KVal *x, KVal *y);
static I k10_is_adv(KAst *n, char adv);
static KVal *k10_lift(const KVal *v, I i, I flt);
static KVal *k10_eval_ln(KAst *n, KVal **vs);
static KVal *k10_eval_v(KAst *n);
static KVal *k10_eval_each(KAst *n);
static KVal *k10_eval_over(KAst *n);
static KVal *k10_eval(KAst *n);
static I k10_fmt_sym(const KVal *v, char *o, I c);
static I k10_fmt_iv(const KVal *v, char *o, I c);
static I k10_fmt_fv(const KVal *v, char *o, I c);
static I k10_fmt_ls(const KVal *v, char *o, I c);
static I k10_fmt(const KVal *v, char *o, I c);
static I k10_ok_line(const char *l);
static J *k10_eval_line_fast(const char *l);
J *eval_source_or_dispatch(char *line, J a2, I a3);
static J *k10_help(void);
static J *k10_time_cmd(I reps, S expr, J *pa);
static J *k10_sl_spec(G f, I a3);
static S k10_sl_next(S c);
J *k10_slash(S cmd, J a2, I a3);
static J k10_strip_comm(J *toks);
static I k10_match_br(G c);
static S k10_skip_str(S s);
static I k10_check_bal(S s);
static J *k10_parse_err(J *toks);
J *k10_parse_src(uJ *src);
static S k10_trim_line(S line);
static J *k10_flush_acc(S acc);
J *k10_parse_lines(V **lines);
J *k10_flush_buf(V **buf);
static J *k10_make_fn_formals(J a2, J a3);
J *k10_build_fn(J src, J a2, J a3);
V **k10_cat3(V **a, S b, V **c);
J k10_emit_imm(J v, J a2, I a3);
static I k10_is_lit(S s);
S k10_build_args(I idx, V *toks);
I k10_at_term(void);
static I k10_get_cls(G c);
I k10_match_kw(J kw, J cur);
I k10_is_term(I b);
J *k10_push_local(J *v, J a2, I a3);
static J k10_parse_expl(J gs);
J k10_parse_args(I mode);
J k10_cons_kw(J kw);
static V *k10_sel_name(J end);
static V *k10_def_name(V **body);
V **k10_parse_sel(V **ex);
static I k10_is_sh(S right);
S k10_emit_ass(J *left, S right, I a3);
J k10_emit_call(J *v, S body, I a3);
V **k10_emit_verb(J *left, J *verb, I a3);
S k10_emit_cat(J *v, S l, S r, I a4);
static I k10_is_num(G c);
I k10_look(void);
static S k10_dict_fin(J *ns, V **ex, I op);
S k10_parse_dict(I op);
static I k10_add_local(I slot, V *name);
uJ k10_resolve(I add, I slot, V *name);
J k10_scan(void);
static V **k10_mod_val(V **n);
V **k10_emit_mod(V **n);
V **k10_parse_seq(void);
J *k10_to_hex(I n, J src);
J k10_wrap_str(S q, V **p);
J *k10_fin_str(G q, V **p);
static S k10_fmt_sub3(J *n, G sub);
static S k10_fmt_sub0(J *n);
static S k10_fmt_rest(J *n, G sub);
S k10_fmt_node(J *n);
static J k10_fmt_fe(J *v);
static J k10_fmt_inr(J *v, G in);
static J k10_fmt_nan(J tag, J *v);
J k10_fmt_val_atom(J *v);
J k10_pad_l(I w, J *v);
J k10_pad_r(I w, J *v);
static J *k10_fit_rv(I b, J *r, G lt);
static J *k10_fit_lv(I b, J *l, J *r);
static J *k10_fit_p(I cols, J *v);
static J *k10_fit_ls(I cols, J *v);
J *k10_fit_cols(I cols, J *v);
J k10_render(I pack, J *v);
J *k10_trim(J s);
J k10_trunc(I pack, J *v, J a3, I a4);
J *elide_at_cols(I c, J *v);
uJ k10_is_csv(V *p);
J k10_ext_look(J n, J a2, I a3);
J k10_ldr_look(J n, J a2, I a3);
J k10_wr_err(V **v);
J k10_write(V *vb, V **v, I a3);
J *k10_sym_to_vec(V **s);
static J k10_dyadic_keyword_lookup(J n);
J k10_dispatch_dyadic(J *v, uJ val);
static V ***k10_named_dyadic_err(uJ *n);
V ***k10_dispatch_named_dyadic(uJ *n, V **a, V ***r);
J *k10_box_imm(V **v);
J k10_csv_fmt(V *v);
J k10_prime_ext(void);
static J *k10_split_byte(I s, J len, I (*src)[4]);
J *k10_split_ln(V **v);
J k10_join_ln(V **l);
J *k10_join_sep(G s, V **l);
J *k10_split_term(I s, V **v);
static J *k10_split_dot(I (*d)[4]);
J *split_or_dispatch(V **a1, I (*d)[4], J a3, I a4);
static J *k10_enc_payload(J h, J *r, J *v, I f);
J *k10_encode(J h, V **v, J aux, I f);
static I k10_is_comp(G t);
static J k10_owner(V *b);
static V k10_rem_free(struct TlsHeap *o, V *b);
static V k10_drain_ch(J ch);
static V k10_drain(void);
static V k10_split_cas(uJ c, J th, J te);
static V k10_split(uJ c);
static V k10_slab_free(V *b, uJ c);
static J *k10_alloc_glb(uJ c);
static J *k10_alloc_mt(uJ c);
static V k10_chop(J *b, uJ c, uI n);
static J *k10_alloc_mmap(uJ c);
static J *k10_alloc_split(uJ c);
static J *k10_alloc_large(uJ c);
static J *k10_alloc_small(uJ c);
J *k10_alloc_slot(I cls);
static V k10_rel_kids(V **o, G t);
J k10_rls_comp(V *o, G t);
J k10_rls_heap(V *o);
uJ k10_release(V *o);
static V *k10_rtn_heap(uJ v);
V *k10_retain(V *v);
J *k10_alloc(I t, I n);
J k10_box_a(I t, J v);
J k10_box_p(I t, __int128 v);
J *k10_alloc_init(I t, I n, const V *s);
J *k10_clone(V *o);
uJ k10_len(V *o);
J *k10_widen(I n, V **s);
V **k10_ensure(I a, V **o);
V **k10_app_b(V **v, char b);
V **k10_app_i(V **v, I w);
V **k10_app_v(V **v, J *x, I f);
V *k10_cat_s(V **a, S b);
V *k10_copy(I o, V *d, S s);
J *k10_chr_p(char a, char b);
J k10_cat_b(char b, S r);
J *k10_int_a(I v);
J *k10_zero(I t, I n);
J *k10_sng_j(J v);
J *k10_pair_j(J a, J b);
J *k10_tri_j(J a, J b, J c);
J k10_quad(J a, J b, J c, J *d);
uJ k10_pchn_l(V **o);
J k10_intern(J c);
static V ns_skeleton_init(void);
J init_runtime_memory_(J mem_class, J ram_bytes);
J initialize_runtime(long mem_class, long ram_bytes);
V init_runtime_memory(void);
static uJ detect_temporal_code(uJ nn);
static I detect_numeric_suffix_match(char *buf, uJ n, char first);
static uJ detect_plain_atom_type(char *buf, uJ n, I dots);
uJ detect_atom_type(char *buf);
uJ detect_atom_type_from_text(char *buf);
uJ parse_build_date(const char *date_literal);
uJ parse_build_date_alias(const char *date_literal);
J *temporal_unit_lookup(I letter);
J ensure_singleton(J *value, J aux, I flags);
J ensure_singleton_alias(J *value, J aux, I flags);
static V column_rectify_copy_payload16(J *col, J *vec, J src_col);
static V column_rectify_copy_scalar(J *col, J *vec, J src_col, uJ cls);
static J *column_rectify_one(J *vec, uI tag, J src_col);
J is_keyed_pairlist(J *arg1, J arg2_unused, I flags_unused);
J *column_rectify(J *vec, I flags);
J *refresh_keyed_pairs(J *vec, J arg2, I arg3);
J *refresh_keyed_pairlist(J *vec, J a2, I a3);
static I canonicalize_every_keyed(V **arg1, J aux, J aux2);
static V **canonicalize_expand_pair_immediates(J *rect);
static V **canonicalize_plain_list(V **arg1, J aux, J aux2, I flags);
static V **canonicalize_keyed_pair_case(V **arg1, J aux, J aux2);
static V **canonicalize_pair_chain_header(V **arg1);
static J k10_can_pln(J x, J a, J b, I f);
static J k10_can_key(J x, J a, J b);
static J k10_can_chn(J x);
J k10_canon_list(J x, J a, J b, I f);
J k10_canon_display(J x, J a, J b, I f);
static I k10_rec_chk(J x, J* v, J n);
static I k10_is_rect(J* x, J n);
static I k10_max_w(J* x, J n);
J *k10_rectify(J* x, J a, J b, I f);
J *k10_rectify_rows(J* x, J a, J b, I f);
J *k10_list_head(J x);
J *k10_list_len(J x);
J *k10_list_counts(J x);
J k10_parse_int(I n, S s);
J k10_parse_integer(I n, S s);
V k10_parse_f64_into(I n, S s);
V k10_parse_f64_buf(I n, S s);
static J k10_can_prm(J x, J a, I f);
static J k10_can_at(J x);
static J k10_can_p(J x, J a, J b, I f);
J k10_canon_send(J x, J a, J b, I f);
uJ k10_obj_len(V* x);
uJ k10_obj_len_walk(V* x);
uJ k10_obj_len_alt(V* x);
J k10_promote_atom(J* src, J v);
J k10_atom_to_list(J* src, J v);
static uJ k10_at_fa_v(V* p, uJ i);
static J k10_at_fa(J* v, uJ i);
static J k10_at_p(J* v, uJ i, G t);
static J k10_at_chn(J* v, uJ i);
J k10_at(J* v, uJ i);
J k10_at_typed(J* v, uJ i);
J k10_first(J* v);
J k10_first_atom(J* v);
J k10_at_safe(J* v, I i);
J k10_at_safe_atom(J* v, I i);
static J k10_key_wlk(V** x);
J k10_keyed_first(V** x);
J k10_keyed_val_first(V** x);
J k10_keyed_last(V** x);
J k10_keyed_val_last(V** x);
static F k10_parse_w(I n, S s);
static F k10_parse_f(I n, S s);
static I k10_find_dot(I m, S r);
static F k10_parse_f64_val(I n, S s);
F k10_parse_f64_frac(I n, S s, F *f);
V k10_parse_f64_f(I n, S s, F *z);
J k10_parse_dt_s(I k, I a, V *b);
J k10_parse_dt_f(I k, I a, V *b);
uJ k10_parse_dt(I k, I n, V *b);
J *k10_expand_pair(V** x, J a, J b, I f);
J *k10_keyed_to_list(V** x, J a, J b, I f);
J *k10_pair_make(I t, J a, J* b);
static V **k10_unw_p(V** x, J a, J b, I f);
V **k10_unwrap_chain(V** x, J a, J b, I f);
uJ k10_rd_to_jd(I m);
uJ k10_jd_to_rd(J j);
static J k10_cst_im(V* t, J v);
V **k10_prom_t(I t, __int128* v);
J k10_reshp_a(I t, V** v);
J k10_reshp(I t, V** v);
V *k10_p_last(V* x);
V *k10_p_last_i(V* x);
static J *k10_p_exp_t(J* t);
J *k10_p_exp(J* x);
V **k10_recycl(V** x);
V **k10_recycl_h(V** x);
I k10_h_cap(I w, V* x);
I k10_h_grow(I w, V** x);
static uJ k10_eq_s(V** r, V** l, uJ n, G t);
static uJ k10_equal_tagged(uJ r, uJ l, uJ lt);
static uJ k10_equal_types(V** r, V** l, G lty, G rty);
static uJ k10_equal_step(V*** pl, V*** pr);
uJ k10_equal(V** a, V** b, I a3, uJ a4);
J k10_dict_get_retry(J* r, V* k, I f);
J k10_dict_get(J* r, V* k, I f);
J k10_dict_get_a(J* r, V* k, I f);
V **canonicalize_list(V **a, J b, J c, I d);
V **canonicalize_list_for_display(V **a, J b, J c, I d);
J *rectify_or_pad(J *a, J b, J c, I d);
J *rectify_or_pad_rows(J *a, J b, J c, I d);
J *list_first_bytes(V **a);
J *list_lengths(V **a);
J *list_element_lengths(V **a);
J parse_signed_int(I a, char *b);
J parse_signed_integer(I a, char *b);
V parse_double_into(I a, char *b);
V parse_double_into_buffer(I a, char *b);
V **canonicalize_for_send(V **a, J b, J c, I d);
uJ kind_or_length(V *a);
uJ kind_or_length_walk(V *a);
uJ kind_or_length_alternate(V *a);
V **promote_singleton(V **a, J b);
V **promote_atom_to_singleton(V **a, J b);
uJ index_vector(J *a, uJ b);
uJ index_typed_vector(J *a, uJ b);
J vector_first(J *a);
J vector_first_atom(J *a);
J vector_at_or_first(J *a, I b);
J vector_at_or_first_atom(J *a, I b);
J keyed_first(V **a);
J keyed_first_value(V **a);
J keyed_last(V **a);
J keyed_last_value(V **a);
F parse_double_with_frac(I a, char *b, F *c);
V parse_double_with_fraction(I a, char *b, F *c);
J parse_temporal_short(I a, I b, V *c);
J parse_temporal_short_field(I a, I b, V *c);
uJ parse_temporal_dispatch(I a, I b, V *c);
J *expand_pair(V **a, J b, J c, I d);
J *expand_keyed_pair_to_list(V **a, J b, J c, I d);
J *pair_cell_make(I a, J b, J *c);
V **unwrap_pair_chain(V **a, J b, J c, I d);
uJ rata_die_to_julian(I a);
uJ julian_to_rata_die(J a);
J reshape_to_target_tag(I a, V **b);
V *pair_immediate_last(V *a);
V *pair_immediate_last_int(V *a);
J *expand_pair_immediate(J *a);
V **clone_or_recycle_real(V **a);
V **clone_or_recycle_header(V **a);
I has_capacity(I a, V *b);
I has_growth_capacity(I a, V **b);
uJ deep_equal(V **a, V **b, I c, uJ d);
J dict_insert_or_get(J *a, V *b, I c);
J dictionary_insert_or_get(J *a, V *b, I c);
J k10_render_pair(V *p);
J k10_render_node(J val);
static J k10_expand_keyed_inner(V *p, J h);
J k10_expand_keyed(J val);
J k10_apply_unary_or_single(V *arg, J aux, I flg);
J *k10_apply_unary_keyed(K_unary_fn f, V *v);
static J *k10_apply_unary_loop_fill(K_unary_fn f, V *v, J *o, I n);
J *k10_apply_unary_loop(K_unary_fn f, V *v, J *o, I n);
J *k10_apply_unary_each(K_unary_fn f, V *v);
J *k10_apply_dyadic_left_keyed(K_dyadic_left_fn f, J l, V *v);
static J *k10_apply_dyadic_left_loop_f(K_dyadic_left_fn f, J l, V *v, J *o, I n);
J *k10_apply_dyadic_left_loop(K_dyadic_left_fn f, J l, V *v, J *o, I n);
J *k10_apply_dyadic_left(K_dyadic_left_fn f, J l, V *v);
J *k10_apply_dyadic_left_each(J fn, J l, V *v);
V **k10_cast_temporal(I tgt, V *src);
V **k10_cast_narrow(I tgt, V *src);
static V *k10_cast_typed_inner(I tgt, V* src, G c, char* buf);
V **k10_cast_typed(I tgt, V *src);
V **k10_cast(V *tgt_tag, V *src);
V **k10_cast_tag_alias(I tgt, V *v);
static V k10_prom_dbl(J *o, V **v);
static V k10_prom_flt(J *o, V **v);
static V k10_prom_si(J *o, V **v);
static V k10_prom_long(J *o, V **v);
static J k10_prom_sym_one(J *r);
static V k10_prom_sym(J *o, V **v);
static V k10_prom_num(I tgt, uI h, J *o, V **v);
static V k10_prom_temp_fill(I f, G p, uJ n, J *o, V **v);
static V k10_prom_temp(I tgt, J *o, V **v);
static V **k10_promote_atom_list(I tgt, V** vec);
V **k10_promote(I tgt, V **vec);
V **k10_promote_target(I tgt, V **v);
J k10_promote_sym_list(V **v);
J *k10_ranged_pair_keyed(V *verb, V *v, J *val);
J *k10_ranged_pair_list(V *v, I n);
static J *k10_ranged_pair_verb(V *verb, J *v, J *val);
J *k10_ranged_pair(V *verb, J *v, J *val);
J *k10_ranged_pair_alias(V **verb, J *v, J *val);
V ***k10_axis_tagged(V **a1, V *a2, J aux, I flg);
V ***k10_axis_split(V **out, V **src, I n);
static V ***k10_axis_apply_n(V** src, I n);
V ***k10_apply_along_axis(V **a1, V *a2, J aux, I flg);
J k10_is_wide_sorted(J *v, J aux, uJ flg);
static J *k10_is_unq_sorted_list(J *v, J aux, uJ flg);
J *k10_is_unique_sorted(J *v, J aux, uJ flg);
J k10_same_kind(J *v, I a2, I a3);
J k10_same_outer_kind(J *v, I a2, I a3);
J *k10_concat_loop(V **a, J *o, I n);
J *k10_concat_o(V **a, I n);
static J *k10_concat_non_typed(V **a, I n, uI flg);
J *k10_list_concat_or_canon(V **a, uJ aux, uI flg);
J *k10_list_concat_alias(V **a, uJ b, uI c);
V **k10_canon_typed_final(V **r);
V **k10_canon_typed_body(J *v);
V **k10_canonicalize_typed(J *v, I f, J a3, I flg);
V **k10_canon_typed_vec(J *v, I f, J a3, I a4);
uJ k10_cached_max(V *v, J a2, J a3);
uJ cached_max_element(V *vec, J a, J b);
J partition_by_index(J shift, V **arg2);
J cast_or_box(V *target_tag, J arg2);
J cast_to_target_or_box(V *target, J value);
J *generic_cast_worker(J alloc_helper, J promote, J target, V **vec);
J dict_lookup(J *root, uJ *key, I flags);
J dictionary_lookup(J *root, uJ *key, I flags);
V **split_engine(V *arg1, __int128 *arg2, J a3, I flags);
V *bigint_normalize_in_place(V **vec);
J *bigint_grow_to(I target_lo, V **vec);
J *bigint_grow_to_target_lo(I target_lo, V **vec);
J *sort_with_key(J key_seed, J *vec);
J *sort_with_key_seed(J key_seed, J *vec);
J is_count_call(J *arg1, J a2, J a3, I flags);
J is_count_call_lambda(J *a, J b, J c, I d);
V *sort_then_canonicalize(V *arg1, J *arg2);
J k10_check_short_e(V *e);
J k10_is_short_funcs(V *arg, I a2, I a3);
J k10_is_short_func_table(V *a, I b, I c);
J k10_group_or_take(I cnt, J *vec, I flg);
J k10_group_dispatch(I c, J *v, I f);
J *k10_digits_take(I cnt, V **vec);
V *k10_digits_alias(I cnt, J val);
J k10_is_homo(V *arg, J a2, J a3, I flg);
J k10_is_homo_alias(V *a, J b, J c, I d);
uJ k10_pchain_len(V **arg, J a2, I flg);
V **k10_apply_verb(J *fn, V *arg);
V **k10_apply_list(J *fn, V **arg, I flg);
V **k10_apply_atomic(J *fn, V *v, J a3, uJ f);
J k10_rebalance_left(V **arg1, V ***arg2);
J k10_rebalance_alias(V **a, V ***b);
uJ k10_merge_rhs_tag(V ***right);
V **k10_merge_promote(V **anc, V **right);
V **k10_merge_mismatch(V **anc, V **l, V **r, uI lt, uI rt);
V **k10_merge_check_r(V ***r, V ***arg2, I arg3);
V **k10_merge_dispatch(V **l, V ***r, V **arg1);
V **k10_merge_concat(V **arg1, V ***arg2, I a3, I a4);
V **k10_multi_concat(V **a, V ***b, I c, I d);
V **k10_ins_match(J *arg1, J *arg2);
V **k10_ins_match_cb(J *a, J *b);
V *k10_pimm_canon(J *arg);
V *k10_pimm_canon_alias(J *arg);
V **k10_prom_bool_cls(I val, V **vec);
V **k10_shrink_int(I v, V **vec);
V **k10_canon_typed_unq(V **vec, J a2, I flg);
V **k10_canon_typed_widely(V **a17, I flg, J a3);
V **k10_canon_for_typed(V **arg, J a2, J a3, I flg);
V **k10_canon_typed_pair(V **a, J b, J c, I d);
I k10_nz(G st, __int128 *vec, I i);
J *k10_cast_bool_packed(__int128 *vec, char *m);
J *k10_cast_int_typed(I tgt, __int128 *vec);
J *k10_canon_homo_build(J *v, uI in, uJ n);
J k10_homo_k(J *vec, uJ n, uI inner);
J k10_homo_k_num(J *vec, uJ n);
J *k10_canon_homo_list(J *vec, uJ a, uI f);
V **k10_ensure_box(J *v, J a, I f);
I k10_cmp_bool(V *a, V *b);
I k10_atom_eq(J a, J b);
V *k10_size_match(I want, V *vec, I flg);
V *k10_unwrap(J *arg);
J k10_norm_atom_list(V *vec);
J *k10_bit_not(J arg);
uJ k10_max_i(V *v, J a2, J a3, uJ h);
uJ k10_max_j(V *v, J a2, J a3, uJ h);
uJ k10_max_s(V *v, J a2, J a3, uJ h);
V *k10_canon_pchain(V **vec);
V *k10_canon_temp(V **vec);
V *k10_canon_int(V **vec);
V *k10_canon_other(V **vec);
V *k10_canon_to_typed(V **vec, I flg);
I k10_is_canon_prom(J *v, I f);
V *k10_canon_u(V *v, J a, uI f);
V *k10_canon_u_alias(V *v, J a, uI f);
J *k10_reshape(I w, J *v);
I k10_leaf_int(V *v);
J k10_pimm_idx(V *p, uJ idx);
V **k10_pair_cat(V **a1, V *a2);
V **k10_pair_ins(V **a1, V ***a2, I f);
V **k10_cat_pchains(char *l, V *r);
V **k10_ins_cb(V *cb, V *base, V **slot, I f);
J k10_fold_temp(I tgt, V *vec);
J k10_cast_i_tail(J arg);
J k10_get_v(I sw, __int128 *vec, I i);
V k10_put_v(I dw, J *out, I i, J v);
V *k10_cast_typed_inner_v(I tgt, __int128 *vec);
V *k10_cast_c_b(I tgt, V **vec);
V *k10_narrow(V *vec);
V *k10_proj_cols(J a, J b, I c);
J *k10_prom_bool(J *vec);
J k10_recip(J sh, __int128 *vec, J a);
J *k10_iter(I vb, V *base, V **vec);
V *k10_bi_norm(V **vec);
V *k10_bi_load(V *vec);
J *k10_store(J *dst, J idx, V *val);
V k10_bit_cp(V *dst, const V *src, J o, J b);
J *k10_render_list(J *v, G h);
J *k10_render_val(J *vec);
J *k10_render_pair_j(J *pair);
J *k10_render_asgn(J *left, J *right);
J *k10_render_dyad(char vb, V **l, V **r);
K k10_render_table(I cols, K hdr, K vcols);
K k10_rend_fin(I cols, K hdr, K vcols, K res);
K k10_rend_val(I c, K x);
I k10_rend_wide(K h, K r);
V k10_rend_pad(K v, K r, I w);
K k10_rend_hdr(K h, K r, I w, K v);
K k10_intern_dot(J c);
K k10_mark_ip(K x, J y, I f);
uJ k10_temp_let(I f);
V k10_cast_temp(I l, J v);
V k10_cast_y(J v);
V k10_cast_t(I l, J v);
K k10_flatten(I v, K x);
K k10_prom_alias(I t, J x);
V k10_unq_fs_prom(J a, J a1, J a2, I f);
V k10_unq_fs_split(J c);
J k10_build_idx(I h, K v);
K k10_unq_p_imm(J a);
K k10_unq_p_p(J a);
K k10_unq_p_s(J c);
K k10_unq_p_l(J t);
K k10_delta_idx(J a);
V k10_delta_fill(J a, K o, K l);
K k10_pair_walk(V **v);
K k10_alloc_p_imm(I h, K i);
V k10_log_j(uJ v);
K k10_digit_pos(I c, I b);
K k10_bigint_split(I w, J v);
K k10_scalar_grp(J v, J a1, J a2, I f);
K k10_grp_cst(J v, G h);
K k10_grp_gen(J v);
V k10_grp_add(K *u, K *m, J c, uJ i);
V k10_boot_lamb(void);
V k10_sort_disp(char d, K c, K v, I f);
J k10_sort_apply(K c, K s, I f);
V k10_sort_cmp(J c, V **l);
K k10_ban(void);
K k10_triple(K p, J t);
V k10_pop_last(V **v);
K k10_ins_fn(I v, V *val, K b, V *s);
K k10_ins_v(I v, V *val, K b, V *s);
K k10_walk_ass(V *a, K k, J v);
I k10_is_homo_k(K v, I f);
K k10_app_2_disp(K f, K l, K r, uJ x, uJ fl);
K k10_app_2_v(K f, K l, K r);
K k10_app_n(K f, I a, J r);
I k10_can_run(K f, I a, J r, uI t);
K k10_app_prim(K f, I a, uJ *b);
K k10_app_high(K f, I a, uJ *b);
K k10_app_c3(K f, uJ *b);
K k10_app_1(K f, I n, J a);
uI k10_tag(K x);
I k10_high(K f, uI t);
K k10_box(J x);
K k10_sort_pair(K c, K l, I f);
K k10_bool_inner(J x, S z);
J k10_resolve_lambda(V *f, J k, J v, J a);
J k10_flatten_pair(I v, J *vec);
J *k10_iter_each(I v, V **vec, uJ n);
J k10_iter_fold(I v, V *base, V **vec, uJ n);
J *k10_iter_verb(I v, V *b, V **vec);
J k10_eq(V **a, V **b);
J k10_cmp_lt(V **a, V **b);
J k10_cmp_table(I v, V **a, V **b);
J k10_cmp(I v, V **a, V **b);
V **k10_vec_cmp_eq(I v, J *a, V *rb);
V **k10_vec_cmp(I v, J *a, uJ b);
J k10_atom_lt_imm(V **a, V **b, uI ta);
J k10_atom_lt_heap(V **a, V **b);
J k10_atom_lt(V **a, V **b, I v, J aux);
V **k10_tag_cmp(I v, V *a, V *b);
I k10_max_long(V *v);
V k10_fill_pos(J *out, V **cnts, uJ n);
J *k10_bucket_pos(I total, V **cnts);
J *k10_bucket_cnt_small(J *out, V *v, I nb);
V k10_bucket_cnt_loop(J *out, V *v, uJ n);
J *k10_bucket_cnt(I nb, V *v);
V k10_bool_mask_loop(J *out, V **v, I n, I target);
V **k10_bool_mask(I target, V **v);
V **k10_recast(I a1, V **v);
J k10_is_canonical_list(J *a);
J k10_is_canonical(J *a, I flags);
uJ k10_hash_lookup(V *v, J k, I f);
I k10_compare_raw_elem(V *v, uJ i, uJ h, V **t);
uJ k10_linear_lookup_loop(V *v, V **t, I f, uJ h);
uJ k10_linear_lookup(V *v, V **t, I f);
J k10_unary_pair(K_unary_atom_fn f, J *p);
J k10_bin_search(K_dyadic_left_fn c, I lo, I hi, __int128 *v);
V k10_prefix_sum(J *c, uJ n);
V k10_fill_perm(J *p, V **v, J *c, I total);
J *k10_permute_bucket(I nb, V **v);
J *k10_resolve_dotted(V ***a1, V ***a2, J d);
V **k10_resolve_promote(V **a1, J *a2, I a3, I f);
J *k10_cast_off(I tag, __int128 *v);
J *k10_vec_add_c(J off, __int128 *v);
J k10_ns_step(V *s, V *n);
V k10_not_lane(V **out, uJ o);
V **k10_not_vec(V **v);
V k10_neg_f(V **dst, __int128 *src);
V k10_neg_i(V **dst, __int128 *src);
V **k10_neg(__int128 *v);
J k10_pop_word(char *d, V *b, J off);
V k10_f2i_scan(__int128 *d, __int128 *s);
V k10_tr_d_scan(__int128 *d, J sa);
V k10_tr_f_scan(V *d, __int128 *s);
I k10_popcount(uJ w);
V k10_cb_p_c4(I *d, I *s);
V k10_cb_p_def(I *d, I *s);
V k10_cb_p_c3(I *d, I *s);
I *k10_cast_bool_vec(I *s, G h);
I *k10_cast_bool_p(I *s, char z[16]);
V *k10_zero1(I t);
J k10_min_red_byte(V *v, uJ n, G h);
J k10_min_red_short(V *v, uJ n, G h);
J k10_min_red_int(V *v, uJ n, G h);
J k10_min_red_long(V *v, uJ n, G h);
J k10_min_red(V *v);
J k10_max_red_byte(V *v, uJ n, G h);
J k10_max_red_short(V *v, uJ n, G h);
J k10_max_red_int(V *v, uJ n, G h);
J k10_max_red_long(V *v, uJ n, G h);
J k10_max_red(V *v);
J k10_sum_red_f(V *v, uJ n, G h);
J k10_sum_red_l(V *v, uJ n);
J k10_sum_red_i(V *v, uJ n);
J k10_sum_red_s(V *v, uJ n);
J k10_sum_red_b(V *v, uJ n);
J k10_sum_red(V *v);
J k10_cast_seeded(I tag, J *vec);
J *k10_unique_list(J *arg);
J *k10_unique_pair(J *arg);
J *k10_unique_mask(J *arg);
V *k10_rotate_pair(V *arg, I flags);
V *unwrap_pair_chain_inner(V *vec, I flags);
J *k10_negate_vec(__int128 *vec, I flag);
uJ k10_min_bool(V *vec, J aux);
uJ k10_min_any(char *vec);
uJ k10_min_short(char *vec);
uJ k10_min_int(char *vec);
uJ k10_min_byte(char *vec);
uJ k10_max_long_u(V *vec);
J k10_scan_max_long(J *p, I n, I s);
J k10_scan_min_long(J *p, I n, I s);
J k10_min_signed_long(V *vec);
J k10_max_signed_long(V *vec);
I k10_count_set_bits(V *vec);
static I k10_bool_sorted(J *vec);
static I k10_probe_sorted(G hdr, J *vec);
static V k10_mark_unique(J *v);
J *k10_canonicalize(J *v, J a, uJ f);
uJ k10_bool_sorted_type(V *vec);
I k10_is_sorted_list(J *vec);
I k10_lt_gen(J *a, J *b);
I k10_is_sorted_long(J *vec);
I k10_is_sorted_int(I *vec);
I k10_is_sorted_short(I16 *vec);
I k10_is_sorted_byte(G *vec);
I k10_is_sorted_float(__int128 *vec);
uJ k10_max_int(V *vec);
uJ k10_max_short(V *vec);
uJ k10_max_byte(V *vec);
uJ k10_sym_intern(I b, J k, I (*s)[4]);
uJ k10_sym_lookup(I b, J k);
J k10_get_val(V **vec, I i, I w);
V k10_set_val(V **vec, I i, I w, J v);
static V **k10_cast_copy(I n, G tgt, V **vec, G src);
V **k10_cast_class(V *tgt, V **vec, G hdr);
static V **k10_cast_grad_path(V *t, V **v, uI w, G h);
V **k10_cast_inner(V *tgt, V **vec);
static V k10_sub_s(I16 *s, I16 *d, I val, I n);
static V k10_sub_i(I *s, I *d, I val, I n);
static V k10_sub_b(char *s, char *d, I val, I n);
static V k10_sub_lane_s(I s, V *v, V *o, I n);
static V k10_sub_lane_i(I s, V *v, V *o, I n);
static V k10_sub_lane_b(I s, V *v, V *o, I n);
J *k10_sub_scalar(I s, __int128 *vec);
V **k10_cast_dec_pad(__int128 *vec);
V **k10_cast_log_max(I tgt, __int128 *vec);
uJ k10_check_rank(J *fn, I n, J aux);
I k10_get_rank(J *fn);
static V **k10_fold_loop(J *fn, V **seed, V **vec);
V **k10_fold_list(J *fn, V **seed, V **vec);
static V **k10_fold_type(J *fn, uJ vec, J aux);
V **k10_fold(J *fn, uJ vec, J aux);
static V **k10_each_pair(V **arg, J a2, I aux, I flags);
static V **k10_each_list_loop(V **arg, J a2, I aux, I flags, J *out);
static V **k10_each_list(V **arg, J a2, I aux, I flags, G hdr);
V **k10_each(V **arg, J a2, I aux, I flags);
J *k10_atomize(V *vec);
J k10_first_byte(char *vec);
J k10_first_word(I *vec);
I k10_list_lt(J *a, J *b);
static J k10_at_atom_adj(V *t, J v);
static V **k10_at_vec_adj(V *t, V *v);
J k10_at_v(J a1, V **a2);
V k10_at_atom(J *vec, V **idx);
static J k10_idx_sh(J *v, J *as);
J k10_idx_at_vec(J *vec, V *idx);
static J k10_dyad_3(J a, J *b, I f);
static J *k10_idx_path_keyed(J *root, J *path, I f);
J *k10_idx_path(J *root, J *path, I f);
static J k10_prom_f(J a, J b, I f);
J k10_prom_dyad(J a, J *b, I f, I f2);
J k10_dyad_chain(J a, J *b, I f);
J *k10_shape_p(J *r, V *idx);
J *k10_slice_p(I a, I b, J *v);
J *k10_seed_in(V ***s, J *a2, J *a3, J *a4);
J *k10_app_seed(J *a1, J *a2, J *a3, J *a4);
J *k10_app_each(J *fn, V **arg, J *a3, J *a4);
J *k10_app_pair(J *fn, J *kv, J *a3, J *a4);
uJ k10_pimm_dest(I w, V *v, J aux);
J k10_pimm_at(J *v, J *i, J *o, uJ aux);
J *k10_pimm_tail(V **v);
J k10_pimm_head(V **v);
static J k10_diag(S s);
J k10_err_srt(void);
J k10_err_rev(void);
J k10_err_cat(void);
J k10_pimm_tag(J *a);
J k10_pimm_can(V **v);
J k10_pimm_b(J *a);
I k10_is_srt_pimm(J *v);
I k10_is_srt_typed(J *v);
I k10_is_ukey(J *v);
J k10_ls_sh_fn(V *v);
V *k10_srt_ls(V *c, V **l);
I k10_at_eq(J a, J b);
J *k10_sym_look(I i);
I k10_sym_ins(V *v);
V *k10_srt_in(V *s, V **l);
J *k10_is_cnt_b(V *l);
J *k10_srt_disp(J *a1, J *a2, J *a3);
J *k10_srt_can(J *l, J *c, J *i, V *s, V *b);
V *k10_enr_app(uJ f, V **l, J *r, J *m);
J k10_gen_vb(I f, J *fn, V **v);
J *k10_at_rec(I v, V **a, I f);
J k10_ls_mod(void);
J k10_help_str(void);
J k10_ws_tog(void);
J *k10_sh_p(J *r, V *i);
J *k10_sl_p(I a, I b, J *v);
J k10_br_rec(V **a1, J *a2, J *a3);
J k10_br_at(I v, V **a2, J *a3, J *a4);
J k10_br_full(I v, V **a2, J *a3, J *a4);
J *k10_zip_p(I v, V **a2, V ***a3, I f);
uJ k10_hi_sp(J *v, I vb, J a, I f);
J *k10_gen_n_d(I f, J v, uJ a);
V **k10_resh_i(I t, V **s);
V k10_st_idx(J *d, J i, V *v);
J k10_num_app(uJ s, uJ d, V *v);
V *sort_via_list_comparator(V *cmp, V **list, V *running_mask, J *aux);
V **cast_pair_promote_to_uniform(J *arg1, V **arg2);
J *k10_cast_pair(J h, J p, J t, J *v);
J *k10_cast_list(J h, J p, J t, J *v);
J *k10_cast_vec(J h, J p, J t, J *v, G hdr);
J *k10_cast_recurse(J h, J p, J t, J *v);
J *k10_cyclic_fill(I want, J *vec);
J *k10_size_match_j(I want, J *arg2, I flags);
J *k10_emit_line(I line);
J *k10_emit_col(I col);
J *k10_make_call(I kind, J left, J *right);
J *k10_finalize(J *vec, J aux2, J aux3, I flags);
J *k10_tri_loop(K_triadic_each_fn f, J *v, J a1, J a2, J *res);
J *k10_tri_each(K_triadic_each_fn f, J *vec, J a1, J a2);
J *k10_range_keyed(J verb, J *v, I flags);
I k10_is_cvec_list(J *v);
J *k10_range_base(J verb, J *v, G t, I flags);
J *k10_range_dispatch(J verb, uJ arg, I flags);
I k10_is_simple(V *v);
I k10_is_num_v(V *v);
I k10_is_str(V *v);
J k10_banner(I mem);
V k10_hex_byte(S dst, G v);
I k10_is_digit(G b);
I k10_is_lower(G b);
I k10_is_alnum(G b);
I k10_is_start(G b);
I k10_classify(G b);
J *k10_disp_dyad(J *fn, uJ arg);
J *k10_disp_gen(J *fn, uJ arg);
J *k10_disp_verb(J *fn, uJ arg, J aux, I cls);
static J *k10_disp_cls(J *fn, uJ arg, J aux, I cls);
J *k10_dispatch_arg(J *fn, uJ arg, J aux);
static J k10_pair_res(V **a1, J *r1, J *r2);
J k10_pair_apply_sym(V **a1, J *a2, V **a3);
static uJ k10_probe_h(I verb, G head_t);
uJ k10_verb_probe(J *v, I verb, J aux, I flags);
V k10_num_err(const char *msg);
J k10_verb_take(J a, J b);
J k10_verb_drop(J a, J b);
J k10_verb_at(J a, J b);
J k10_verb_dot(J a, J b);
J *k10_eval_line_simple(S line);
J k10_fmt_f(F v);
J k10_fmt_j(J v);
F k10_pr_f(F v);
static J k10_each_l(I mode, J *left, J *right, J *out, I i);
J k10_each_val(I m, J *fn, J *l, J *r, J *o, I i);
static uJ k10_each_loop(I m, J *f, J *l, J *r, J *o, I n);
J k10_each_pair_core(I mode, J **fn, J *left, J *right);
J *k10_atomic_broadcast(I verb, J *value);
static J *k10_kj_eq(J *l, J *r, V *lk, J *lv, J *rv);
J *k10_keyed_join(J *l, J *r, I f);
J *k10_concat_keyed(V **l, V *r, I f);
J *k10_cast_atom(I target, V *v);
static S k10_read_all(I fd, size_t sz);
J *k10_load_file(S path);
static J *k10_pwd(void);
J *k10_cd(S path);
J k10_timer(J sec);
V k10_day_ymd(J jul, I *y, I *m, I *d);
J k10_date_jul(const char *iso);
J k10_hms_ns(I h, I m, I s, J ns);
V k10_ns_hms(J total, I *h, I *m, I *s, J *ns);
uJ k10_ipc_pack(I type, uI len, I comp);
J k10_ipc_val_hdr(const uJ *h);
J k10_walk_at(G t, const G **p, const G *e);
static J k10_walk_n(const G **p, const G *e, uJ *n);
static J k10_walk_els(G t, const G **p, const G *e, uJ n);
static J k10_walk_11(const G **p, const G *e, uJ n);
J k10_walk_v(G t, const G **p, const G *e, I d);
static J k10_walk_list(G t, const G **p, const G *e, I d);
static J k10_walk_100(const G **p, const G *e, I d);
J k10_walk(const G **p, const G *e, I d);
J k10_walk_root(const G *p, const G *e, I d);
I k10_ipc_val(const G *f, J n);
I k10_tcp_opt(I s);
static V k10_tcp_addr(struct sockaddr_in *a, I p);
I k10_tcp_listen(I port);
I k10_tcp_accept(I s);
V k10_prompt(void);
V k10_cont(void);
I k10_add_sat(I a, I b);
I k10_sub_sat(I a, I b);
I k10_mul_sat(I a, I b);
uJ k10_up_pow2(uJ v);
uI k10_log2(uJ v);
uI k10_ceil_log2(uJ v);
I k10_ends(S v, const char *s);
I k10_starts(S v, const char *p);
I k10_has_b(S v, char b);
J *k10_add_j(J *a, J *b);
J *k10_sub_j(J *a, J *b);
J *k10_mul_j(J *a, J *b);
J *k10_div_j(J *a, J *b);
F *k10_add_f(F *a, F *b);
F *k10_sub_f(F *a, F *b);
F *k10_mul_f(F *a, F *b);
F *k10_div_f(F *a, F *b);
J *k10_lt_j(J *a, J *b);
J *k10_eq_j(J *a, J *b);
J *k10_csv_add(J *r, S s, I n);
static J *k10_csv_step(J *r, S s, I *p, I i, I *q);
J *k10_csv_split(S s, I n);
J *k10_csv_emit(V **v, char s);
J *k10_json_j(J v);
J *k10_json_f(F v);
J *k10_esc_c(J *r, char a, char b);
J *k10_json_hex(J *r, char c);
J *k10_json_esc(J *r, char c);
J *k10_json_s(S v);
J *k10_read_f(I f, I s);
J *k10_read(const char *p);
J k10_write_path(const char *p, S v);
J k10_append(const char *p, S v);
J k10_spawn(const char *c, S const v[]);
uJ k10_mono(void);
uJ k10_real(void);
J *k10_mod_j(J *a, J *b);
J *k10_min_j(J *a, J *b);
J *k10_max_j_p(J *a, J *b);
J *k10_and_j(J *a, J *b);
J *k10_or_j(J *a, J *b);
J *k10_xor_j(J *a, J *b);
J *k10_shl_j(J *a, J *b);
J *k10_shr_j(J *a, J *b);
uJ k10_where_w(J *r, uJ j, uJ v, uJ o, uJ n);
J *k10_where(J *x);
I k10_has_j(J *v, J x);
J *k10_distinct_j(J *v);
V k10_rev_j(J *p, uJ n);
V k10_rev_i(I *p, uJ n);
V k10_rev_h(I16 *p, uJ n);
V k10_rev_b(S p, uJ n);
V k10_rev_v(V **p, uJ n);
static V k10_rev_sw(V **r, G t, uJ n);
V *k10_rev(V *v);
J *k10_take(I n, V *v);
J *k10_drop(I n, V *v);
uJ k10_rng(void);
J *k10_rand_n(I n);
J *k10_rand_m(I n, J x);
J *k10_group_one(J *v, uJ n, J k);
static V k10_group_loop(J *v, uJ n, J *u, J *vs, uJ k);
J *k10_group_j(J *v);
J *k10_lower(S v);
J *k10_upper(S v);
I k10_is_sp(char c);
J *k10_trim_s(S v);
J k10_over(K_dyadic_atom_fn f, J *v);
J k10_over_s(K_dyadic_atom_fn f, J s, J *v);
J *k10_scan_fn(K_dyadic_atom_fn f, J *v);
J *k10_prior(K_dyadic_atom_fn f, J *v);
J k10_fix(K_unary_atom_fn f, J s, I m);
I k10_part_j(J *p, I l, I h);
V k10_qs_j_r(J *p, I l, I h);
V k10_qs_j(J *p, I n);
I k10_part_f(F *p, I l, I h);
V k10_qs_f_r(F *p, I l, I h);
V k10_qs_f(F *p, I n);
static I k10_node_cmp(const V *a, const V *b);
V k10_grade_fill(GradeNode *d, J *v, uJ n);
J *k10_grade_out(GradeNode *d, uJ n);
J *k10_grade_up(J *v);
uJ k10_hash_j(J k);
uJ k10_hash_s(const char *s, I n);
J k10_sum_j(J *v);
F k10_avg_j(J *v);
F k10_var_j(J *v);
F k10_dev_j(J *v);
J *k10_roll_sum(J *v, I w);
J k10_roll_m1(J *v, I i, I w);
J *k10_roll_max(J *v, I w);
J *k10_union(J *a, J *b);
J *k10_inter(J *a, J *b);
J *k10_diff(J *a, J *b);
F *k10_sqrt(F *v);
F *k10_sin(F *v);
F *k10_cos(F *v);
F *k10_exp(F *v);
F *k10_log(F *v);
F *k10_vec_abs_f(F *v);
F *k10_vec_pow_f(F *b, F *e);
J *k10_vec_abs_i(J *v);
J *k10_vec_neg_i(J *v);
J *k10_dict_make(V **k, V **v);
J *k10_dict_keys(J *d);
J *k10_dict_vals(J *d);
J k10_dict_at_i(J *d, J k);
static J *k10_dict_grow_i(J *ks, J *vs, J k, J v);
J *k10_dict_set_i(J *d, J k, J v);
I k10_tbl_rows(J *t);
I k10_tbl_cols(J *t);
J *k10_tbl_col(J *t, J k);
J *k10_tbl_filter(J *t, J *m);
static V k10_tbl_sel_step(J *aks, J *acs, J *nks, J *ncs, uJ na, J w, uJ i);
J *k10_tbl_select(J *t, J *s);
J *k10_fs_ls(const char *p);
I k10_fs_exists(const char *p);
J k10_fs_size(const char *p);
I k10_fs_rm(const char *p);
I k10_fs_mv(const char *s, const char *d);
J *k10_trace_pre(J *v);
J *k10_trace_post(J *v);
static uI k10_lex_skip_ws(const char *s, uI p, uI e);
static TokenSpan k10_lex_ident(const char *s, uI p, uI e);
static TokenSpan k10_lex_str(const char *s, uI p, uI e);
TokenSpan k10_lex_next(const char *s, uI p, uI e);
I k10_re_match_at(const char *p, I np, const char *t, I o, I n);
I k10_re_glob(const char *p, I np, const char *t, I n);
I k10_str_find(const char *t, I n, const char *ndl, I k);
J *k10_str_replace(const char *s, I sn, const char *f, I fn, const char *t, I tn);
static struct ipc_client_state *k10_ipc_client_get(I fd);
static V k10_ipc_client_close(I ep, I fd);
static I k10_ipc_send_q(I fd, const char *p, I len, I off, struct ipc_client_state *c, I ep);
static I k10_ipc_flush(I ep, I fd);
static I k10_ipc_recv_hdr(I fd, struct ipc_client_state *c);
static I k10_ipc_recv_body(I fd, struct ipc_client_state *c);
static I k10_ipc_recv_step(I ep, I fd, struct ipc_client_state *c);
static I k10_ipc_recv(I ep, I fd);
static V k10_ipc_handle_ev(I ep, I fd, uI evs, I lfd);
I k10_ipc_loop(I lfd);
I k10_ipc_dispatch_buf(I fd, V *f, I n, I ep);
I k10_io_read_exact(I fd, I n, V *b);
I k10_ipc_dispatch(I fd, V *f, I n);
J *k10_meta_parse(char *s);
J *k10_meta_eval(char *s);
J k10_meta_call(J *f, J *a);
V k10_panic(I c, const char *m);
V k10_debug_dump(V **v);
static J k10_atom_box_i(J v);
static J k10_atom_box_f(F v);
J k10_atom_add(J a, J b);
J k10_atom_sub(J a, J b);
J k10_atom_mul(J a, J b);
J k10_atom_div(J a, J b);
const char *k10_vm_op_name(I op);
static V k10_vm_op_call(I imm, J *stk, I *sp);
static I k10_vm_op_jif(I imm, J *stk, I *sp, I ip);
static V k10_vm_op_dispatch(I imm, J *stk, I *sp);
V k10_vm_init_dyadic(void);
V k10_vm_init_unary(void);
V *atomic_extension_long_long(K_dyadic_atom_fn fn, J left, J *vec);
V *atomic_extension_long_long_each(K_dyadic_atom_fn fn, J *a, J *b);
J *vector_match_index(J *corpus, J *query);
J *vector_member_test(J *query, J *corpus);
J *vector_first_or_last_n(I n, J *vec);
static V sort_int32_range(I *p, I lo, I hi);
V sort_int_vector_in_place(I *p, I n);
static V sort_int16_range(I16 *p, I lo, I hi);
V sort_short_vector_in_place(I16 *p, I n);
V sort_byte_vector_in_place(G *p, I n);
F *cumulative_sum_float(F *vec);
J *cumulative_max_long(J *vec);
J *cumulative_min_long(J *vec);
J parse_unsigned_int_skipped(const char *buf, I *pos, I end);
J parse_signed_int_skipped(const char *buf, I *pos, I end);
F parse_double_skipped(const char *buf, I *pos, I end);
V console_render_long(J *vec);
V console_render_charvec(char *vec);
V console_render_double(F *vec);
static V json_skip_whitespace(const char *src, I *pos, I end);
static J *json_append_byte(J *out, char c);
static J *json_append_utf8(J *out, I ucp);
static char json_escape_byte(char esc);
static J *json_append_escape(J *out, const char *src, I *pos, I end);
static J json_parse_string(const char *src, I *pos, I end);
static J json_parse_number(const char *src, I *pos, I end);
static J json_parse_array(const char *src, I *pos, I end);
static J json_parse_object(const char *src, I *pos, I end);
J json_parse_value(const char *src, I *pos, I end);
J json_parse_charvec(char *charvec);
V symbol_table_dump_to_console(void);
J *read_csv_file_to_table(const char *path);
J *format_value_to_source(J *value);
J *table_evaluate_predicate(J *table, J *pred_lambda);
J *table_update_column(J *table, J name_sym, J *new_col);
J *table_delete_column(J *table, J name_sym);
J *table_join_inner(J *left, J *right, J join_key);
I signal_send_to_pid(I pid, I sig);
I process_id_self(void);
I process_uid_self(void);
J *process_argv_to_charlist(I argc, char **argv);
J *environ_get_var(const char *name);
V heap_stats_emit(void);
J freelist_class_count(I cls);
J freelist_total_free_bytes(void);
I format_double_round_trip(char *out, F d);
I format_int64_into(char *out, J v);
I format_int32_into(char *out, I v);
uJ murmur64_charvec(const V *vec, I len);
uJ fnv1a_64_byte(uJ state, G byte);
static I u8d2(const char *s, I *p, I e, uI *c, G b);
static I u8d3(const char *s, I *p, I e, uI *c, G b);
static I u8d4(const char *s, I *p, I e, uI *c, G b);
I utf8_decode_at(const char *s, I *p, I e, uI *c);
static I u8e2(char *d, uI c);
static I u8e3(char *d, uI c);
I utf8_encode_into(char *d, uI c);
I utf8_codepoint_count(const char *s, I n);
static V b64e_t(const char *s, I *i, I n, uI *t, I *d);
static V b64e_c(char *p, uI t, I d);
J *base64_encode(const char *s, I n);
static V b64d_init(int8_t *l);
static I b64d_step(char *p, I *op, int8_t *l, const char *s);
J *base64_decode(const char *s, I n);
J *hex_encode_charvec(const char *s, I n);
static I hex_val(char c);
J *hex_decode_charvec(const char *s, I n);
V stdout_buffer_init(StdoutBuffer *b);
V stdout_buffer_flush(StdoutBuffer *b);
V stdout_buffer_write(StdoutBuffer *b, const char *s, I n);
V stdout_buffer_write_byte(StdoutBuffer *b, char c);
static V hw_kp(J *r, HeapVisitorFn v, V *c);
V heap_walk_visit_all(HeapVisitorFn v, V *c);
static V heap_count_visitor(V *o, V *c);
J heap_count_allocated(void);
static uJ br1(uJ v);
static uJ br2(uJ v);
static uJ br4(uJ v);
static uJ br8(uJ v);
static uJ br16(uJ v);
uJ bit_reverse_64(uJ v);
uJ byte_swap_64(uJ v);
uI byte_swap_32(uI v);
uint16_t byte_swap_16(uint16_t v);
J popcount_long(J v);
J leading_zeros_long(J v);
J trailing_zeros_long(J v);
static V ipc_8(J v, char **d);
static V ipc_4(I v, char **d);
V ipc_serialize_long_atom(J v, char **d);
V ipc_serialize_int_atom(I v, char **d);
V ipc_serialize_bool_atom(I v, char **d);
V ipc_serialize_float_atom(F v, char **d);
V ipc_serialize_charvec(const char *s, I n, char **d);
V ipc_serialize_long_vec(J *s, I n, char **d);
J ipc_estimate_serialized_size(V *value);
V ipc_serialize_any(V *value, char **dst);
J ipc_deserialize_long_atom(const char **src);
I ipc_deserialize_uint32(const char **src);
J *ipc_deserialize_charvec(const char **src);
J *ipc_deserialize_long_vec(const char **src);
J ipc_deserialize_any(const char **src);
static J *pretty_print_atom(uI t, V *v);
static J *pretty_print_long_vec(J *p, uJ n);
static J *pretty_print_double_vec(F *p, uJ n);
static J *ppc_esc(J *o, char c);
static J *ppc_hex(J *o, char c);
static J *ppc_char(J *o, char c);
static J *pretty_print_charvec(char *p, uI n);
J *pretty_print_any(V *value, I depth);
V pretty_print_to_stdout(V *value);
J bytecode_eval_loop(const int8_t *code, I code_len, J *args, I n_args);
V history_add(const char *line);
const char *history_get_prev(void);
const char *history_get_next(void);
I stdout_is_terminal(void);
V terminal_clear_screen(void);
V terminal_set_color_red(void);
V terminal_set_color_green(void);
V terminal_set_color_yellow(void);
V terminal_set_color_blue(void);
V terminal_set_color_dim(void);
V terminal_reset(void);
V terminal_move_cursor(I row, I col);
V signal_handler_sigint(I sig);
V signal_handler_sigterm(I sig);
I interrupt_was_pending(void);
I shutdown_was_pending(void);
V install_signal_handlers(void);
CommandLineArgs parse_command_line(I argc, char **argv);
F heap_pressure_ratio(void);
I heap_should_compact(void);
J *coerce_atoms_to_typed_vector(J *list, uI target_tag);
J *csv_emit_row_quoted(V **row, char field_sep, char quote_char);
F stats_correlation_long(J *x, J *y);
F stats_covariance_long(J *x, J *y);
F stats_median_long(J *vec);
J stats_mode_long(J *vec);
J *cast_to_bool_inner_helper_full(__int128 *vec, char *zmm1);
static V k10_comp_i64(I v, J *a, J *b, G *o, I n);
static V k10_comp_i32(I v, I *a, I *b, G *o, I n);
static V k10_comp_i16(I v, I16 *a, I16 *b, G *o, I n);
static V k10_comp_f64(I v, F *a, F *b, G *o, I n);
static V k10_comp_u8(I v, G *a, G *b, G *o, I n);
V **k10_per_tag_comp(I verb, V *a, V *b);
static J k10_comp_atoms(I v, K a, K b, U32 ta, U32 tb);
static J k10_comp_mixed(I v, K a, K b, U32 ta, U32 tb);
J k10_gen_comp(I v, V *a, V *b);
static I k10_sym_intern_match(I idx, const char *name, I len);
static I k10_sym_intern_new(SymbolInternEntry *e, uJ h, const char *name, I len);
I k10_sym_intern_or_get(const char *name, I len);
J k10_sym_pack_imm(const char *name, I len);
V k10_ipc_ser_keyed(V *v, char **dst);
J k10_ipc_deser_keyed(const char **src);
J *k10_bigint_canon(J *v);
J *k10_bigint_add(J *a, J *b);
I k10_bigint_comp(J *a, J *b);
static I k10_count_unbal(const char *ln, I n);
I k10_is_cont(const char *ln, I n);
static V k10_repl_prompt(I cont);
static char *k10_repl_append(char *b, size_t *c, size_t *l, char *ln, I n);
char *k10_repl_read(void);
static J k10_atom_atom_dispatch(char v, U32 ta, U32 tb, J a, J b, I *h);
static J k10_long_vec_dispatch(char v, J a, J b, I *h);
static J k10_float_vec_dispatch(char v, J a, J b, I *h);
static J k10_vec_vec_dispatch(char v, J a, J b, I *h);
static J k10_bcast_l(char v, U32 ta, J a, J b);
static J k10_bcast_r(char v, U32 tb, J a, J b);
J k10_verb_dispatch(char v, J a, J b);
J k_monadic_dispatch(char verb, J a);
J apply_function_with_args(J *fn, I n_args, J *args);
I kalloc_alignment_check(V *slot);
I kalloc_header_layout_check(V *slot);
I tls_heap_self_check(void);
J *kalloc_aligned_64(I type, I length);
V runtime_integrity_summary(void);
V hash_dict_init(HashDict *d, I initial_cap);
V hash_dict_free(HashDict *d);
static I hash_dict_probe_slot(HashDict *d, J key, uJ h);
static V hash_dict_grow(HashDict *d);
V hash_dict_set(HashDict *d, J key, J value);
I hash_dict_get(HashDict *d, J key, J *out_value);
I hash_dict_remove(HashDict *d, J key);
V string_builder_init(StringBuilder *sb);
V string_builder_free(StringBuilder *sb);
V string_builder_append(StringBuilder *sb, const char *src, I n);
V string_builder_append_byte(StringBuilder *sb, char c);
V string_builder_append_int(StringBuilder *sb, J v);
V string_builder_append_double(StringBuilder *sb, F v);
J *string_builder_to_charvec(StringBuilder *sb);
I compare_k_values(J a, J b);
static I compare_k_qsort_asc(const V *a, const V *b);
static I compare_k_qsort_desc(const V *a, const V *b);
J *sort_k_list_ascending(J *list);
J *sort_k_list_descending(J *list);
I is_leap_year(I year);
I days_in_month(I year, I month);
I day_of_week(I year, I month, I day);
I day_of_year(I year, I month, I day);
I runtime_self_test(void);
V k10_print_version(void);
static I k10_double_scan_dot(const char *s, I n, I p);
static I k10_double_find_dot(const char *s, I n);
static F k10_double_accum_whole(const char *s, I n);
static F k10_double_accum_frac(const char *s, I n);
F k10_parse_double_avx2(I n, char *s, F *fs);
static I k10_int_check_avx2(const char *s, I n);
static J k10_int_accum(const char *s, I n);
J k10_parse_int_avx2(I n, char *s);
I k10_utf8_count_avx2(const char *src, I n);
static I k10_memcmp_find_off(I mk, const char *a, const char *b, I p);
static I k10_mcmp_tail(const char *pa, const char *pb, size_t p, size_t n);
I k10_memcmp_avx2(const V *a, const V *b, size_t n);
static I k10_zero_tail(J *vec, I p, I n);
I k10_zero_check_avx2(J *vec, I n);
static V *k10_ffi_add(const char *p, V *h);
static V *k10_dl_err(void);
V *k10_ffi_open(const char *path);
V *k10_ffi_resolve(V *h, const char *s);
V k10_ffi_close_all(void);
J k10_ffi_call(V *fn, I n, J *args);
J k10_ffi_call_sig(V *fn, const char *sig, J *args, I n);
F k10_pow(F b, F e);
J k10_sum_i64(J *vec);
F k10_sum_f64(F *vec);
I k10_is_dict(V *v);
I k10_is_temp_tag(uI t);
I k10_get_temp(I i, J v);
static V k10_prime_keys(J *ks);
static V k10_prime_vals(J *vs);
V k10_prime_extensions(void);
static I k10_avx2_mcmp_test(void);
I k10_avx2_test(void);
V k10_lr_init(LineReader *r, I fd);
static char *k10_lr_ln(LineReader *r, I *len, I i);
static char *k10_lr_find_nl(LineReader *r, I *len);
static V k10_lr_compact(LineReader *r);
static char *k10_lr_eof(LineReader *r, I *len);
static char *k10_lr_fill(LineReader *r, I *len);
char *k10_lr_get(LineReader *r, I *len);
static V k10_probe_mem(long *hs, long *mc);
V k10_runtime_warmup(void);
V k10_trace_dump(const char *lbl, V *v);
static V k10_tr_ind(void);
static V k10_tr_arg(J a);
V k10_trace_enter(const char *name, I n, J *args);
V k10_trace_exit(const char *name, J res);
I *k10_vec_add_i32(I *a, I *b);
I *k10_vec_sub_i32(I *a, I *b);
I *k10_vec_mul_i32(I *a, I *b);
I16 *k10_vec_add_i16(I16 *a, I16 *b);
G *k10_vec_xor_u8(G *a, G *b);
I k10_vec_all_i64(J *vec);
I k10_vec_any_i64(J *vec);
J k10_vec_count_i64(J *vec);
J *k10_rank_desc_i64(J *vec);
J *k10_rank_asc_i64(J *vec);
I k10_to_bool(J v);
V k10_lock_init(SimpleSpinLock *l);
V k10_lock_acquire(SimpleSpinLock *l);
V k10_lock_release(SimpleSpinLock *l);
static V k10_sing_cp(J *dst, uJ cls, uJ pl);
J k10_singleton_coerce(J arg);
static J k10_prom_get(V *v, I i, I sw);
static V k10_prom_set(V *d, I i, I dw, J v);
V **k10_promote_vec(I t, __int128 *v);
I k10_bitvec_eq(V *a, V *b);
J *k10_bitwise_not(V *v);
__int128 *k10_cast_dispatch(I sel, V *src);
J k10_cast_decimal(__int128 *toks, I mode);
J k10_cast_long(J v, I mode);
J k10_classify_promote(V *dr, I h, I pl, I f);
V *k10_clone_recycle(V *v);
char *k10_compare_aux_a(I sep, char *acc, V *ret);
I k10_compare_aux_b(int8_t c);
V **k10_concat_pairchain(char *l, V **r);
V **k10_pair_cell_concat(V **head, V *tail);
J k10_pair_chain_walk_recurse(I a, V *v);
V **k10_pair_or_collapse(I v, J l, J r);
static G k10_check_uniform_tag(J *vec, I n);
static V k10_cp_unif(V *o, V *s, I i, I w);
static V k10_copy_to_uniform(V *out, J *v, I n, I w);
static V *k10_promote_init(V *vec, G tag);
V *k10_pair_promote_to_uniform(V **slot, V *vec);
J *k10_apply_dot_or_dispatch(I v, J val, I flags);
J *k10_diagnostic_type_mismatch(J val);
static J *k10_dict_probe(J base, J key, I idx, I cap);
J *k10_dictionary_seek_chain(J base, J key, I flags);
J k10_epoch_clock_get(G which);
J *k10_eval_arglist_apply(I budget, V *a, V *b);
J k10_eval_block_chain(V **val);
J k10_eval_jump_dispatch(V **boxed);
J k10_eval_lookup_or_apply(V **val);
J k10_eval_misc_helper(J selector);
J k10_eval_special_dispatch(J left, V *right);
J *k10_extract_first_typed_byte(I op, J top, I unused1, I unused2);
J *k10_extract_first_typed_word(G op, J a, J b, I c);
J k10_extract_first_word_for_print(I len, J *str);
I k10_fini_module_section(const char *p, struct stat *s);
static I k10_can_narrow(J *s, I n);
V *k10_narrow_long_to_int(V *vec);
static I k10_date_month(const char *s);
static I k10_date_day(const char *s);
static I k10_date_year(const char *s);
I k10_parse_build_date_literal(const char *s);
J k10_parse_dyadic_args_into_table(J op_byte, J class_byte, I sub_id);
V **k10_promote_to_symbol_list(J *vec);
V *k10_render_value_into_buf(I mode, I len, V *res, I flags);
J k10_reshape_or_canonicalize_dispatch(V *v);
static V k10_reshape_copy(V *out, V *vec, I want, I n, I es);
J *k10_reshape_or_take(I want, J *vec);
J *k10_reshape_take_recursive(I avail, V *val);
V **k10_resolve_dotted_name(V *anch, V **val, I flags);
J *k10_shape_with_int_dimensions(J *head, __int128 *tail);
static V k10_slice_rtn(J *out, I len);
J *k10_slice_into_new_slot(I off, I len, J *vec);
static V k10_sort_long(J *vec, I len);
static V k10_sort_int(I *vec, I len);
static J *k10_sort_check(J *v);
static V k10_sort_copy(V *d, V *s, G t, I n);
static J *k10_sort_init(J *vec, G tag, I n);
static V k10_sort_dispatch(J *out, G tag, I n);
J *k10_sort_or_grade_inner(J *vec, V *cmp, V *idx);
I k10_kalloc_check_align(V *p);
I k10_kalloc_check_header(V *p);
I k10_tls_heap_check(void);
J *k10_kalloc_aligned(I t, I n);
V k10_integrity_summary(void);
J k10_special_variable_get(int8_t cmd, I arg2, I arg3);
J k10_symbol_from_index(I idx);
J k10_symbol_to_charvec_indexed(I idx);
J k10_sym_lookup_and_apply(J key, V *arg, I flags);
J *k10_sym_lookup_and_apply_dyadic(J k, V *left, G op, V *right);
J *k10_unwrap_or_self(J *vec);
I k10_vector_total_length(V *vec);
I k10_vec_total_length(V *vec);
J k10_verb_apply(J func, I arity, uJ args);
J k10_verb_byte_apply(J func, I arity, uJ args);
J *k10_wrap_pair_with_separator(I sep, V *left, V *right);
V *k10_concat_three_charvecs_alt(void);
J k10_rdtsc(void);
static char k10_ram_letter_for_phys(long phys);
static long k10_heap_bytes_for_letter(char c);
static V k10_set_socket_opts(I fd);
static I k10_bind_server(I fd, I port);
static I k10_listen_server(I fd);
static I k10_start_tcp_server(char *s);
static char *k10_parse_argv(I n, char **v, I *s);
static V k10_set_term_size(struct winsize *ws);
static V k10_cap_term(struct winsize *ws, long phys);
static V k10_capture_terminal_and_banner(I epoch, long mem, long phys);
static uJ k10_eval_script_lines(FILE *f);
static I k10_run_script(char *s);
static I k10_run_stdin_once(void);
static I k10_flush_pending_reply(J id, I n);
static I k10_accept_client(uJ fd, I n);
static I k10_handle_stdin_event(void);
static I k10_reply_framed(I fd, V **d);
static V **k10_decode_frame(I fd, uI sz, I n);
static I k10_handle_client_frame(uJ fd, I n, uI *sz);
static I k10_pump_epoll_once(I n, uI *sz);
static I k10_run_repl_loop(void);
static V k10_init_main(K10Main *m);
static V k10_boot_main(K10Main *m);
static I k10_exec_main(K10Main *m);
#ifdef K10_FREESTANDING
static V k10_start_main(J c, J v,
V (*f)(void)) {
extern I main(I, char **, char **);
extern V __libc_csu_init(void);
extern V __libc_csu_fini(void);
extern I __libc_start_main(I (*)(I,char**,char**),
I, char **, V (*)(void), V (*)(void),
V (*)(void), V *);
J e;
__libc_start_main(main, (I)c, (char **)v,
__libc_csu_init, __libc_csu_fini, f, &e);
}
__attribute__((noreturn))
V _start(J c, J v, V (*f)(void)) {
k10_start_main(c, v, f);
__builtin_unreachable();
}
#endif
V k10_init_pad(void) { R; }
V k10_dereg_tm(void) { R; }
V k10_reg_tm(void) { R; }
V k10_dtors_aux(void) { R; }
V k10_j_reg_tm(void) { k10_reg_tm(); }
J k10_now_ns(void) {
struct timespec w;
clock_gettime(CLOCK_REALTIME, &w);
F s = (F)(w.tv_sec - EPOCH_2001_OFFSET_S);
F ns = (F)w.tv_nsec + s * NS_PER_SEC_F;
const F t63 = 9.2233720368547758e+18;
if (ns < t63) R (J)ns;
J h = 0x8000000000000000LL;
R (J)(ns - t63) ^ h;
}
J k10_write_err(const char *s) {
S p = (S)memchr(s, 0, (size_t)-1);
size_t n = (size_t)(p - s);
I fd = STDERR_FILENO;
if (write(fd, s, n) > 0) R (J)s;
R 0;
}
volatile I k10_int_pend = 0;
volatile I k10_shut_pend = 0;
V k10_sig_int(I s) { (void)s; k10_int_pend = 1; }
V k10_sig_term(I s) { (void)s; k10_shut_pend = 1; }
I k10_int_was(void) {
if (k10_int_pend) { k10_int_pend = 0; R 1; }
R 0;
}
I k10_shut_was(void) { R k10_shut_pend; }
V k10_sig_init(void) {
typedef V (*H)(I);
extern H signal(I, H);
signal(SIGINT, k10_sig_int);
signal(SIGTERM, k10_sig_term);
signal(SIGPIPE, (H)1);
}
static S k10_hist[K_LINE_HISTORY_CAP];
static I k10_hist_n;
static struct termios k10_t_old;
static I k10_t_saved;
static I k10_raw_on;
V k10_line_restore(void) {
if (k10_raw_on && k10_t_saved) {
I fd = STDIN_FILENO;
tcsetattr(fd, TCSANOW, &k10_t_old);
k10_raw_on = 0;
}
}
I k10_line_raw_set(I fd) {
struct termios r = k10_t_old;
r.c_iflag &= ~(BRKINT|ICRNL|INPCK|ISTRIP|IXON);
r.c_oflag &= ~(OPOST);
r.c_lflag &= ~(ECHO|ICANON|IEXTEN|ISIG);
r.c_cflag |= (CS8);
r.c_cc[VMIN] = 1; r.c_cc[VTIME] = 0;
if (tcsetattr(fd, TCSANOW, &r) != 0) R 0;
k10_raw_on = 1; R 1;
}
I k10_line_raw(void) {
I fd = STDIN_FILENO;
if (!isatty(fd)) R 0;
if (!k10_t_saved) {
if (tcgetattr(fd, &k10_t_old) != 0) R 0;
k10_t_saved = 1; atexit(k10_line_restore);
}
R k10_line_raw_set(fd);
}
V k10_hist_shift(void) {
free(k10_hist[0]);
V **p = (V **)k10_hist;
I n = K_LINE_HISTORY_CAP - 1;
memmove(p, p + 1, (size_t)n * 8); k10_hist_n--;
}
V k10_hist_push(const char *s) {
if (s == NULL || s[0] == '\0') R;
if (k10_hist_n > 0) {
if (strcmp(k10_hist[k10_hist_n - 1], s) == 0)
R;
}
if (k10_hist_n == K_LINE_HISTORY_CAP)
k10_hist_shift();
k10_hist[k10_hist_n++] = strdup(s);
}
S k10_hist_path(void) {
static char p[1024]; S h = getenv("HOME");
if (h == NULL || h[0] == '\0') R NULL;
snprintf(p, sizeof p, "%s/.k10_history", h);
R p;
}
V k10_hist_add_line(char *b) {
size_t n = strlen(b);
while (n > 0 && (b[n-1]=='\n' || b[n-1]=='\r'))
b[--n] = '\0';
if (n > 0) k10_hist_push(b);
}
V k10_hist_load(void) {
S p = k10_hist_path(); if (p == NULL) R;
FILE *f = fopen(p, "r"); if (f == NULL) R;
char b[4096];
while (fgets(b, sizeof b, f) != NULL)
k10_hist_add_line(b);
fclose(f);
}
V k10_hist_save(void) {
S p = k10_hist_path(); if (p == NULL) R;
FILE *f = fopen(p, "w"); if (f == NULL) R;
for (I i = 0; i < k10_hist_n; i++) {
fputs(k10_hist[i], f); fputc('\n', f);
}
fclose(f);
}
V k10_line_redraw(const char *pr, I pl,
const char *b, I bl, I c) {
char f[0x300]; I o = 0; f[o++] = '\r';
memcpy(f + o, pr, (size_t)pl); o += pl;
memcpy(f + o, b, (size_t)bl); o += bl;
memcpy(f + o, "\x1b[K", 3); o += 3;
if (bl > c)
o += snprintf(f + o, sizeof f - o,
"\x1b[%dD", bl - c);
write(STDOUT_FILENO, f, (size_t)o);
}
static V k10_line_reprompt(const char *p, I pl,
I *bl, I *c) {
k10_int_pend = 0;
write(STDOUT_FILENO, "^C\r\n", 4);
*bl = *c = 0;
write(STDOUT_FILENO, p, (size_t)pl);
}
static V k10_line_del_at(const char *p, I pl,
S b, I *bl, I *c) {
if (*c < *bl) {
size_t sz = (size_t)(*bl - *c - 1);
memmove(b + *c, b + *c + 1, sz);
(*bl)--;
k10_line_redraw(p, pl, b, *bl, *c);
}
}
static V k10_line_backspace(const char *p, I pl,
S b, I *bl, I *c) {
if (*c > 0) {
size_t sz = (size_t)(*bl - *c);
memmove(b + *c - 1, b + *c, sz);
(*bl)--; (*c)--;
k10_line_redraw(p, pl, b, *bl, *c);
}
}
static V k10_line_kill_left(const char *p, I pl,
S b, I *bl, I *c) {
size_t sz = (size_t)(*bl - *c);
memmove(b, b + *c, sz);
*bl -= *c; *c = 0;
k10_line_redraw(p, pl, b, *bl, *c);
}
static V k10_line_kill_word(const char *p, I pl,
S b, I *bl, I *c) {
I i = *c;
while (i > 0 && b[i-1] == ' ') i--;
while (i > 0 && b[i-1] != ' ') i--;
size_t sz = (size_t)(*bl - *c);
memmove(b + i, b + *c, sz);
*bl -= (*c - i); *c = i;
k10_line_redraw(p, pl, b, *bl, *c);
}
static V k10_line_home(const char *p, I pl,
S b, I *bl, I *c) {
*c = 0; k10_line_redraw(p, pl, b, *bl, *c);
}
static V k10_line_end(const char *p, I pl,
S b, I *bl, I *c) {
*c = *bl; k10_line_redraw(p, pl, b, *bl, *c);
}
static V k10_line_clear(const char *p, I pl,
S b, I *bl, I *c) {
write(STDOUT_FILENO, "\x1b[H\x1b[2J", 7);
k10_line_redraw(p, pl, b, *bl, *c);
}
static V k10_line_insert(G ch, const char *p, I pl,
S b, I *bl, I *c) {
if (ch < K_ASCII_SPACE && ch != '\t') R;
if (*bl + 1 >= K_HEAP_LOW_ADDR) R;
if (*c < *bl) {
size_t sz = (size_t)(*bl - *c);
memmove(b + *c + 1, b + *c, sz);
}
b[(*c)++] = (char)ch; (*bl)++;
k10_line_redraw(p, pl, b, *bl, *c);
}
static V k10_line_h_load(I i, const char *p, I pl,
S b, I *bl, I *c) {
S h = k10_hist[i]; I hl = (I)strlen(h);
if (hl > K_BYTE_MAX) hl = K_BYTE_MAX;
memcpy(b, h, (size_t)hl);
*bl = hl; *c = hl;
k10_line_redraw(p, pl, b, *bl, *c);
}
static V k10_line_up(const char *p, I pl,
S b, I *bl, I *c,
I *hi, S sc, I *scl) {
if (*hi > 0) {
if (*hi == k10_hist_n) {
memcpy(sc, b, (size_t)*bl); *scl = *bl;
}
(*hi)--; k10_line_h_load(*hi, p, pl, b, bl, c);
}
}
static V k10_line_dn(const char *p, I pl,
S b, I *bl, I *c,
I *hi, S sc, I *scl) {
if (*hi < k10_hist_n) {
(*hi)++;
if (*hi == k10_hist_n) {
memcpy(b, sc, (size_t)*scl);
*bl = *scl; *c = *bl;
k10_line_redraw(p, pl, b, *bl, *c);
} else k10_line_h_load(*hi, p, pl, b, bl, c);
}
}
static V k10_line_esc_digit(const char *p, I pl,
S b, I *bl, I *c, G s1) {
G s2;
if (read(STDIN_FILENO, &s2, 1) == 1 && s2 == '~') {
if (s1 == '3') k10_line_del_at(p, pl, b, bl, c);
}
}
static V k10_line_esc_move(G m, const char *p, I pl,
S b, I *bl, I *c,
I *hi, S sc, I *scl) {
if (m == 'A')
k10_line_up(p, pl, b, bl, c, hi, sc, scl);
else if (m == 'B')
k10_line_dn(p, pl, b, bl, c, hi, sc, scl);
else if (m == 'C' && *c < *bl) {
(*c)++; k10_line_redraw(p, pl, b, *bl, *c);
} else if (m == 'D' && *c > 0) {
(*c)--; k10_line_redraw(p, pl, b, *bl, *c);
} else if (m == 'H') k10_line_home(p, pl, b, bl, c);
else if (m == 'F') k10_line_end(p, pl, b, bl, c);
}
static V k10_line_esc(const char *p, I pl,
S b, I *bl, I *c,
I *hi, S sc, I *scl) {
G s[2];
if (read(STDIN_FILENO, &s[0], 1) != 1) R;
if (read(STDIN_FILENO, &s[1], 1) != 1) R;
if (s[0] != '[') R;
if (s[1] >= '0' && s[1] <= '9')
k10_line_esc_digit(p, pl, b, bl, c, s[1]);
else k10_line_esc_move(s[1], p, pl, b, bl, c,
hi, sc, scl);
}
static V k10_key_eof(const char *p, I pl, S b,
I *bl, I *c) {
if (*bl == 0) exit(0);
k10_line_del_at(p, pl, b, bl, c);
}
static V k10_key_ctrl(G ch, const char *p, I pl,
S b, I *bl, I *c,
I *hi, S sc, I *scl) {
if (ch == 0x15) k10_line_kill_left(p, pl, b, bl, c);
else if (ch == 0x17)
k10_line_kill_word(p, pl, b, bl, c);
else if (ch == 0x01) k10_line_home(p, pl, b, bl, c);
else if (ch == 0x05) k10_line_end(p, pl, b, bl, c);
else if (ch == 0x0c) k10_line_clear(p, pl, b, bl, c);
else if (ch == 0x1b)
k10_line_esc(p, pl, b, bl, c, hi, sc, scl);
}
static V k10_line_dispatch(G ch, const char *p, I pl,
S b, I *bl, I *c,
I *hi, S sc, I *scl) {
if (ch == 0x04) k10_key_eof(p, pl, b, bl, c);
else if (ch == 0x7f || ch == 0x08)
k10_line_backspace(p, pl, b, bl, c);
else if (ch < K_ASCII_SPACE)
k10_key_ctrl(ch, p, pl, b, bl, c, hi, sc, scl);
else k10_line_insert(ch, p, pl, b, bl, c);
}
static I k10_line_step(const char *p, I pl, S b,
I *bl, I *cur, I *hi,
S sc, I *scl) {
G key; ssize_t n = read(STDIN_FILENO, &key, 1);
if (n < 0 && errno == EINTR) R 0;
if (n < 0) R -1;
if (n == 0) R (*bl == 0) ? -1 : 1;
if (key == '\r' || key == '\n') {
write(STDOUT_FILENO, "\r\n", 2); R 1;
}
k10_line_dispatch(key, p, pl, b, bl, cur,
hi, sc, scl);
R 0;
}
static I k10_line_fin(S out, S b, I bl, I cap) {
I n = bl < cap - 1 ? bl : cap - 1;
memcpy(out, b, (size_t)n); out[n] = '\0';
if (n > 0) k10_hist_push(out);
R n;
}
static I k10_line_loop(const char *p, I pl, S b,
I *bl, I *c, I *hi, S sc,
I *scl) {
while (1) {
if (k10_int_pend) {
k10_line_reprompt(p, pl, bl, c); continue;
}
I d = k10_line_step(p, pl, b, bl, c, hi, sc, scl);
if (d) R d;
}
}
static I k10_line_run(const char *p, S out, I cap) {
if (cap <= 1) R -1;
I pl = (I)strlen(p), bl = 0, c = 0, hi = k10_hist_n;
I sl = 0; char b[256], sc[256];
write(STDOUT_FILENO, p, (size_t)pl);
I d = k10_line_loop(p, pl, b, &bl, &c, &hi, sc, &sl);
R (d < 0) ? -1 : k10_line_fin(out, b, bl, cap);
}
static J k10_read_raw(S p) {
I cp = (I)sizeof stdin_line_buffer;
I n = k10_line_run(p, stdin_line_buffer, cp);
k10_line_restore();
if (n < 0) { connected_client_count--; R 0; }
R (J)stdin_line_buffer;
}
static J k10_read_cooked(J pr) {
if (pr) k10_write_err((S)pr);
I cp = (I)sizeof stdin_line_buffer;
I n = (I)read(STDIN_FILENO, stdin_line_buffer, cp);
if (n <= 0) { connected_client_count--; R 0; }
stdin_line_buffer[n - 1] = '\0';
R (J)stdin_line_buffer;
}
J k10_read_line(J prompt) {
S p = (prompt != 0) ? (S)prompt : "";
if (k10_line_raw()) R k10_read_raw(p);
R k10_read_cooked(prompt);
}
J k10_println(V **obj) {
V **w = (V **)append_byte_to_charvec(obj, '\n');
size_t n = (size_t)XN(w);
write(STDOUT_FILENO, w, n); release_object((V **)w); R 0;
}
J k10_f_to_c(F v) {
char b[24]; I n = sprintf(b, "%.7g", v);
R allocate_typed_vector_init(K_TYPE_CHAR, n, b);
}
F k10_strtod(I n, S b) {
size_t i = (size_t)n;
char s = b[i]; b[i] = '\0';
F r = strtod(b, NULL); b[i] = s;
R r;
}
J k10_p_long(J v) {
char b[40]; sprintf(b, "%lld", (long long)v);
k10_write_err(b); k10_write_err("\n"); R v;
}
F k10_p_double(F v) {
char b[24]; sprintf(b, "%.7g", v);
k10_write_err(b); k10_write_err("\n"); R v;
}
S k10_ser_typed(S body, V *src, G t, uI n) {
I s = k_type_log2_bits_table_alias[t];
uJ b = (((uJ)n << s) + 7) >> 3;
memcpy(body, src, b); R body + b;
}
S k10_ser_boxed(S base, S body, S *cur, J val, uJ tag) {
J tag_mask = val & K_TAG_MASK;
uJ addr = (uJ)base + (uintptr_t)*cur;
addr += (tag == 0) << 3;
*cur = k10_ser_obj(base, (J *)*cur,
(V *)(uintptr_t)val, (I)tag_mask);
R (J)addr | tag_mask;
}
S k10_ser_list(S base, S body, V *src, uI n) {
uJ sl = n > 1 ? n : 1; S cur = body + sl * 8;
for (J i = 0; i < (I)n; i++) {
J val = *(J *)((S)src + (i << 3));
uJ tag = (uJ)val >> K_TAG_SHIFT;
if (TEST_BITQ(K_TAGCLASS_HEAP_BOXED, tag))
val = k10_ser_boxed(base, body, &cur, val, tag);
*(J *)(body + (i << 3)) = val;
}
R cur;
}
V k10_ser_v_payload(J *dst, J v, G t) {
if (TEST_BITQ(K_TAGCLASS_PAIR_PAYLOAD, t))
*(__int128 *)dst =
*(__int128 *)((uJ)v & K_PTR_MASK);
else {
J p;
if (TEST_BITQ(K_TAGCLASS_SCALAR_IMMED, t))
p = (J)(uJ)v;
else p = *(J *)((uJ)v & K_PTR_MASK);
*dst = p;
}
}
S k10_ser_val(J *dst, J val) {
G tag;
if ((uJ)val <= K_BYTE_MAX) {
*(int8_t *)dst = (int8_t)(val ^ 0x80);
tag = 0;
} else {
tag = (G)((uJ)val >> K_TAG_SHIFT);
k10_ser_v_payload(dst, val, tag);
}
I s = k_type_log2_bits_table_alias[tag];
R (S)dst + (((1 << s) + 7) >> 3);
}
S k10_ser_obj(S base, J *dst, V *src, I dt) {
uJ addr = (uJ)src;
if ((I)(addr >> K_TAG_SHIFT) != 0)
R (S)k10_ser_val(dst, (J)src);
*dst = *(J *)((S)src - 8);
S body = (S)(dst + 1); G t = *(G *)((S)src - 5);
uI n = *(uI *)((S)src - 4);
if ((I)(t - 1) <= 0x3e)
R k10_ser_typed(body, src, t, n);
R k10_ser_list(base, body, src, n);
}
uJ k10_dec_small(S p, uJ t, I b) {
uJ m = (uJ)((0xffffffff << b) ^ 0xffffffff);
if (TEST_BITQ(K_TAGCLASS_INT32_LANE, t))
m = K_BIGINT_LIMB_MAX;
R (t << K_TAG_SHIFT) | (m & (uJ)*(uI *)(p + 1));
}
static uJ k10_dec_atom_special(S p, uJ t) {
if (TEST_BITQ(K_TAGCLASS_PAIR_PAYLOAD, t)) {
__int128 l = *(__int128 *)(p + 1);
R box_pair_payload((I)t, l);
}
if (TEST_BITQ(K_TAGCLASS_ATOMIC_BOX, t))
R box_atom((I)t, *(J *)(p + 1));
R 0;
}
uJ k10_dec_atom(J *c, S p, uJ t) {
I b = 1 << k_type_log2_bits_table_alias[t];
*(S *)c = p + (((b + 7) >> 3) + 1);
if (t == 1) {
G e = (G)p[1];
if ((int8_t)e < 0) R (uJ)(e & 0x7f);
}
uJ res = k10_dec_atom_special(p, t);
if (res) R res;
R k10_dec_small(p, t, b);
}
uJ k10_dec_vec(J *c, S p, S b, G t, uI n) {
I s = k_type_log2_bits_table_alias[t];
uJ y = (((uJ)n << s) + 7) >> 3;
*(S *)c = b + y; G f = (G)p[1];
uJ a = (uJ)allocate_typed_vector_init(t, n, b);
*(int8_t *)(a - 6) = (int8_t)f; R a;
}
uJ k10_dec_list(J *c, G t, uI n) {
uJ a = (uJ)allocate_typed_vector(t, n);
for (J i = 0; i < (I)n; i++)
*(J *)(a + (i << 3)) = (J)k10_dec_val(c);
R a;
}
uJ k10_dec_comp(J *c, S p) {
S b = p + 7; *(S *)c = b;
G t = (G)p[2]; uI n = *(uI *)(p + 3);
if ((I)(t - 1) <= 0x3e)
R k10_dec_vec(c, p, b, t, n);
R k10_dec_list(c, t, n);
}
uJ k10_dec_val(J *c) {
S p = *(S *)c; uJ t = (uJ)(G)p[0];
if (t == 0) R k10_dec_comp(c, p);
R k10_dec_atom(c, p, t);
}
uJ k10_dec_rel(V **b) {
V **c = b; uJ v = k10_dec_val((J *)&c);
release_object((V **)b); R v;
}
V k10_log_init(I *pa) {
I fd = open("k10.log", O_CREAT|O_APPEND|O_RDWR, 0777);
if (fd < 0) fd = 0;
primary_client_send_fd = fd; J *h = allocate_typed_vector(0, 1);
primary_client_send_buffer = (J)h;
*h = 0x600000000008LL; *pa = 8;
}
static V k10_log_msg_append(J *e) {
J h = primary_client_send_buffer;
uI n = (uI)*(I *)(h - 4);
J o = *(J *)(h + ((n - 1) << 3)) + (uI)*(I *)((S)e - 4);
primary_client_send_buffer =
(J)append_value_to_list((V **)h, (V *)o, 0);
write(primary_client_send_fd, e, (size_t)*(I *)((S)e - 4));
release_object((V **)e);
}
J *k10_log_msg(V **v, J a2, J a3, I a4) {
if (primary_client_send_fd == 0) k10_log_init(&a4);
J *e = encode_to_ipc_buffer(0x600000000000LL, v, a3, a4);
if (!K_IS_ERR_RETURN(e)) {
k10_log_msg_append(e); R NULL;
}
R e;
}
V k10_log_exit(I status) {
I fd = primary_client_send_fd;
if (fd != 0) {
J t = primary_client_send_buffer;
uI n = (uI)*(I *)(t - 4); *(I *)(t - 4) = (I)(n - 1);
write(fd, (V *)(t - 8), (size_t)((n << 3) + 8));
}
if (status != 0) k10_write_err("\nK10 panic: ");
_exit(status);
}
static J k10_ipc_tag(void) {
static volatile J c = 0;
if (c == 0) {
J s = (J)rdtsc() | 1;
__sync_bool_compare_and_swap(&c, 0, s);
}
J v = __sync_add_and_fetch(&c, 1);
R v ? v : __sync_add_and_fetch(&c, 1);
}
static S k10_ipc_text(uJ fd, I fl, V *v) {
V **s = (V **)symbol_to_charvec(retain_object(v));
V **o = (V **)k10_diag_print(s);
if (K_IS_ERR_RETURN(o)) R (S)o;
if ((fl & 1) != 0)
s = (V **)append_byte_to_charvec(s, '_');
uJ *t = (uJ *)append_byte_to_charvec(s, 0);
*(I *)((S)t - 4) -= 1;
k10_p_rel((J)o, t);
pending_reply_queue[fd] = 1; R (S)1;
}
static S k10_ipc_dec(S r) {
V **c = (V **)r; uJ v = k10_dec_val((J *)&c);
release_object((V **)r); R (S)v;
}
static S k10_ipc_match(uJ fd, J h, S r, J tag, J s) {
G *rh = (G *)s;
if (rh[1] == (G)IPC_MSG_TYPE_RESPONSE &&
rh[3] == (G)(tag & K_BYTE_MAX)) {
pending_reply_queue[fd] = h;
R (!r[0]) ? k10_ipc_dec(r) : r;
}
R NULL;
}
static S k10_ipc_wait(uJ fd, J h, S r, J tag) {
J d = (J)rdtsc() + (J)IPC_SYNC_TIMEOUT_MS * 3000000LL;
while (1) {
J s = pending_reply_queue[fd];
if (s != 0 && s != h) {
S res = k10_ipc_match(fd, h, r, tag, s);
if (res) R res;
}
if (!K_IS_ERR_RETURN(r) && r[0] == 0)
R k10_ipc_dec(r);
if ((J)rdtsc() > d) R r;
}
}
static S k10_ipc_sync(uJ fd, J h, V *v, V **p, J aux) {
J tag = k10_ipc_tag(); G *e = (G *)p;
if (e) {
e[1] = (G)IPC_MSG_TYPE_SYNC; e[3] = (G)(tag & K_BYTE_MAX);
}
S r = ((S(*)(V**, V*, V**, J, J))h)(p, v, p, aux, h);
if (K_IS_ERR_RETURN(r)) R r;
R k10_ipc_wait(fd, h, r, tag);
}
static V k10_ipc_enc_req(V **p) {
if (((uintptr_t)p >> K_TAG_SHIFT) != 0 || *((S)p - 5) != 1)
encode_to_ipc_buffer(0, p, (J)p, 0);
}
S k10_ipc_send(I fl, V *v, V **p, J aux) {
uJ fd = (uJ)fl; if (!K_CLIENT_FD_OK(fd)) R (S)3;
J h = pending_reply_queue[fd];
if (h == 0) R k10_ipc_text(fd, fl, v);
if (fl > 1) {
if ((fl & 1) != 0)
R k10_ipc_sync(fd, h, v, p, aux);
k10_ipc_enc_req(p);
}
if (p != NULL && (fl & 1) == 0) {
G *e = (G *)p; e[1] = (G)IPC_MSG_TYPE_ASYNC;
}
R ((S(*)(V**, V*, V**, J))h)(p, v, p, aux);
}
V k10_diag_len(V **wp) {
S lp = "len:";
V **w = (V **)append_byte_to_charvec(
concat_charvecs(cstr_to_charvec_trim(lp), (J)wp), 0);
*(I *)((S)w - 4) -= 1; release_object((V **)w);
}
V **k10_diag_fmt(V **f) {
S op = " (", tp = "type:", lp = "len:";
V **wp = (V **)append_byte_to_charvec(
concat_charvecs((J)f, cstr_to_charvec_trim(op)), 0);
*(I *)((S)wp - 4) -= 1; S b;
if (file_size_or_zero(wp) < 0) {
concat_charvecs(cstr_to_charvec_trim(tp), retain_object(wp));
f = (V **)(uintptr_t)K_TYPE_SHORT; b = "type";
} else {
k10_diag_len(wp); f = (V **)1; b = "length";
}
k10_write_err(b); k10_write_err("\n"); R f;
}
V **k10_diag_print(V *v) {
V **r = (V **)retain_object(v);
V **f = (V **)format_value_to_charvec(r, 0, 0);
if (K_IS_ERR_RETURN(f)) R f;
R k10_diag_fmt(f);
}
J k10_p_rel(J p, uJ *v) {
if (p != 0 && (uI)((((uJ)v) >> K_TAG_SHIFT) - 2) <= 5)
v = (uJ *)symbol_to_charvec(v);
release_object((V **)v); k10_write_err("length");
R k10_write_err("\n");
}
V **k10_fmt_val(V **v, J a2, I a3) {
uI t = (uI)((uJ)v >> K_TAG_SHIFT); V **o = (V **)8;
bool s = (uI)(t - 2) >= 6;
bool a = s && t == 0 && *((S)v - 5) == 1;
if (!s || a) {
if (s) v = (V **)eval_lookup_or_apply(v);
o = (V **)append_byte_to_charvec(v, 0);
*(I *)((S)o - 4) -= 1;
}
R o;
}
I (*k10_read_file_err(S p))[4] {
if ((uI)(((uJ)p >> K_TAG_SHIFT) - 2) <= 5)
p = (S)symbol_to_charvec(retain_object(p));
k10_println((V **)p); R (I (*)[4])4;
}
J *k10_read_file_dec(V **m, size_t l, I (*r)[4]) {
if (m == (V **)1) {
J *d = allocate_typed_vector(K_TYPE_PAIR_CHAIN, l);
R (J *)memcpy(d, r, l);
}
if (m != NULL)
R render_value_into_buf(m, l, r, 0);
S n = (S)memchr(r, 0, l);
I sl = n ? (I)(n - (S)r) : (I)l;
R split_charvec_on_byte(0xa, sl, r);
}
I (*k10_read_file(V **m, S p))[4] {
size_t l = (size_t)file_size_or_zero(p);
I fd = open(p, O_RDONLY, 0777); I (*r)[4];
if (fd <= 0) R k10_read_file_err(p);
r = (I (*)[4])mmap_file_or_anon(0, 0, l, fd);
release_object((V **)p); if (K_IS_ERR_RETURN(r)) R r;
J *d = k10_read_file_dec(m, l, r); munmap(r, l);
R (I (*)[4])d;
}
J *k10_run_cd(V *a, S b, S t) {
V **o = a ? (V **)cstr_to_charvec_trim(a) : NULL;
R (J *)k10_chdir(o, (J)b, (I)(intptr_t)t);
}
J *k10_run_l(V *a) {
R k10_parse_script(cstr_to_charvec_trim(a));
}
V k10_run_sh_child(I p[2], J *o) {
dup2(p[1], STDOUT_FILENO);
S a[4] = {"sh", "-c", (S)o, NULL};
execve("/bin/sh", a, NULL); _exit(0);
}
J *k10_run_sh_parent(I fd) {
char b[K_MMAP_HIGH_BUDGET_LO]; S c = b; size_t r = sizeof b;
ssize_t n = read(fd, b, r);
while (n > 0) {
r -= (size_t)n; c += (size_t)n;
n = read(fd, c, r);
}
close(fd); J *v = allocate_typed_vector(K_TYPE_PAIR_CHAIN, c - b);
memcpy(v, b, (size_t)(c - b));
R split_charvec_into_lines(v);
}
J *k10_run_sh(S b) {
J *o = cstr_to_charvec_trim(b); I p[2];
if (pipe(p) != 0) R (J *)9;
if (fork() == 0) k10_run_sh_child(p, o);
close(p[1]); client_established_flags[p[0]] = 1;
release_object((V **)o); R k10_run_sh_parent(p[0]);
}
J *k10_run_cmd(I n, S b) {
S t = b + n + 1; G f = (G)t[-1];
V *a = f ? (V *)t : NULL;
if (n == 2 && ((uI16 *)b)[0] == 0x6463)
R k10_run_cd(a, b, t);
if (n == 1 && b[0] == 'l') {
if (a) R k10_run_l(a); R (J *)9;
}
R k10_run_sh(b);
}
J *k10_parse_script(S p) {
if (*(I *)(p - 4) == 0) R NULL;
if (is_valid_csv_path(p) != 1) {
retain_object(p); k10_write_err("syntax error \n");
R (J *)0xc;
}
J *v = resolve_or_invoke_script(NULL, p);
if (!K_IS_ERR_RETURN(v)) {
V **w = (V **)retain_object((V *)secondary_send_buffer);
v = parse_lines_to_block(v); k10_chdir(w, 0, 0);
}
R v;
}
J k10_chdir_ok(V **p) {
release_object((V **)p); char c[256]; getcwd(c, sizeof c);
J *f = cstr_to_charvec_trim(c);
release_object((V **)(V *)secondary_send_buffer);
secondary_send_buffer = (J)f; R 0;
}
J k10_chdir_err(V **p) {
if ((uI)(((uJ)p >> K_TAG_SHIFT) - 2) <= 5)
p = (V **)symbol_to_charvec(retain_object(p));
k10_println(p); R 4;
}
J k10_chdir(V **p, J a2, I a3) {
if (p == NULL)
R (J)retain_object((V *)secondary_send_buffer);
if (deep_equal(secondary_send_buffer, p, a3, 0) != 0) {
release_object((V **)p); R 0;
}
mkdir((const char *)p, 0777);
if (chdir((const char *)p) == 0)
R k10_chdir_ok(p);
R k10_chdir_err(p);
}
static const char *const k_err_sigil_names[16] = {
NULL,
"assign",
"parse",
"stack",
"char",
"rank",
"type",
"length",
"domain",
"nonce",
"alloc",
"limit",
"io",
"nyi",
"value",
"wsfull",
};
static I k_value_pointer_looks_sane(uJ value)
{
if (value == 0 || value < 0x1000) return 0;
if ((value >> K_TAG_SHIFT) != 0) return 0;
G type = *(G *)((char *)value - 5);
uI len = *(uI *)((char *)value - 4);
if (type == 0 && len > K_MAX_VECTOR_LEN) return 0;
if (type > K_TYPE_LITERAL_FUNC) return 0;
return 1;
}
uJ emit_initial_eval_result(uJ value, J a2,
J a3, I a4)
{
uJ status = value;
if (value >= 2) {
if (value > 0xf) {
if (!k_value_pointer_looks_sane(value)) {
const char nyi[] = "!nyi\n";
write(STDOUT_FILENO, nyi, sizeof nyi - 1);
return 1;
}
V **rendered = (V **)truncate_for_repl(
terminal_size_packed, value, a3, a4);
if (rendered != NULL) {
I rlen = *(I *)((char *)rendered - 4);
const G *rbytes = (const G *)rendered;
I ok = (rlen > 0 && rlen < K_MMAP_HIGH_BUDGET_LO);
for (I i = 0; ok && i < rlen; i++) {
G b = rbytes[i];
if (b == '\t' || b == '\n' || (b >= 0x20 && b <= 0x7e)) continue;
ok = 0;
}
if (!ok) {
release_object(rendered);
const char nyi[] = "!nyi\n";
write(STDOUT_FILENO, nyi, sizeof nyi - 1);
return 1;
}
}
println_object(rendered);
status = 0;
} else {
const char *name = k_err_sigil_names[value & K_NIBBLE_MAX];
if (name == NULL) name = "err";
char buf[32];
I n = (I)strlen(name);
if (n > 30) n = 30;
buf[0] = '!';
memcpy(buf + 1, name, (size_t)n);
buf[n + 1] = '\n';
write(STDOUT_FILENO, buf, (size_t)(n + 2));
status = 1;
}
}
return status;
}
static J *k10_eval_print(J *p) {
uJ u = (uJ)p;
return (J *)emit_initial_eval_result(u, 0, 0, 0);
}
J *k10_eval_line(char *l, J a, I b) {
if (!l) return 0;
J *p = eval_source_or_dispatch(l, a, b);
if (terminal_size_packed == 0) return k10_eval_print(p);
if (l[0] == ' ') return k10_eval_print(p);
if (((uJ)p >> K_TAG_SHIFT) != 0) return k10_eval_print(p);
K_U8 t = *(K_U8 *)((char *)p - 5);
if (t == K_TYPE_PAIR_IMMEDIATE) return k10_eval_print(p);
if (t == K_TYPE_LITERAL_FUNC) return k10_eval_print(p);
if ((t - 1) < 0x3f) return k10_eval_print(p);
if (pair_chain_length(p) <= 1) return k10_eval_print(p);
V *r = render_at_terminal_width(
terminal_size_packed, p);
println_object((V **)join_with_newline(r));
return 0;
}
J k10_mmap_high(uJ s) {
I any = (s == 0x7f0000000000ULL);
I fb = MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE;
V *w = (V *)(0x7f0000000000ULL - s);
I f = any ? fb : (fb | MAP_FIXED);
I p = PROT_READ | PROT_WRITE;
V *r = mmap(w, s, p, f, -1, 0);
if (r == MAP_FAILED && !any) {
r = mmap(0, s, p, fb, -1, 0);
}
return (J)r;
}
J k10_mmap_file(I a, J ad, uJ s, I fd) {
I prot = a ? PROT_READ : PROT_READ | PROT_WRITE;
I fix = (ad != 0) << 4;
I an = (fd == 0) << 5;
I f = an + fix + 0x4002;
if (a) f = 1;
J r = (J)mmap((V *)ad, s, prot, f, fd, 0);
if (fd != 0) close(fd);
return r;
}
static J k10_est_atom(K_U8 t, J h) {
K_U8 s = k_type_log2_bits_table_alias[t];
I b = (I)(((1 << s) + 7) >> 3);
I m = (I)((TEST_BITQ(
K_TAGCLASS_HEAP_BOXED, t)) * b);
return (h != 0) ? m : (b + 1);
}
static J k10_est_vec(K_U8 it, uJ len) {
K_U8 s = k_type_log2_bits_table_alias[it];
return (((len << s) + 7) >> 3);
}
static J k10_est_list(J h, J *v,
uJ len) {
J tot = 0, e = (h != 0) ? 8 : 0;
for (uJ i = 0; i < len; i++) {
tot += e + k10_est_size(h, (J *)v[i], 0);
}
return tot;
}
J k10_est_size(J h, J *v, J a) {
K_U8 t = (K_U8)((uJ)v >> K_TAG_SHIFT);
if (t != 0) return k10_est_atom(t, h);
K_U8 it = *(K_U8 *)((char *)v - 5);
uJ len = (uJ)*(uI *)((char *)v - 4);
if ((I)(it - 1) <= 0x3e)
return k10_est_vec(it, len) + 8;
if (len == 0) return k10_est_size(h, *v, a) +
((h != 0) ? 8 : 0) + 8;
return k10_est_list(h, v, len) + 8;
}
static V *k10_ser_vec(int8_t *d, V *v,
K_U8 it, uI len) {
K_U8 s = k_type_log2_bits_table_alias[it];
uJ b = (((uJ)len << s) + 7) >> 3;
memcpy(d, v, b);
return d + b;
}
V *k10_ser_compact(int8_t *c, V *v) {
K_U8 t = (K_U8)((uJ)v >> K_TAG_SHIFT);
bool a = (uJ)v < K_HEAP_LOW_ADDR;
c[0] = (int8_t)((int8_t)a + (int8_t)t);
if (a != (K_U8)-(int8_t)t)
return (V *)serialize_one_value(
(J *)(c + 1), (J)v);
*(J *)(c + 1) = *(J *)((char *)v - 8) >> 16;
int8_t *d = c + 7;
K_U8 it = *(K_U8 *)((char *)v - 5);
uI len = *(uI *)((char *)v - 4);
if ((I)(it - 1) < 0x3f)
return k10_ser_vec(d, v, it, len);
for (uJ i = 0; i < len; i++)
d = (int8_t *)k10_ser_compact(d,
(V *)*(J *)((char *)v + (i << 3)));
return d;
}
J k10_file_size(char *p) {
struct {
J dev, ino;
uI mode, nlink, uid, gid;
J rdev, size, pad[8];
} st;
I r = fini_module_section(p, &st);
if (r != 0) return r;
J s = st.size;
if ((st.mode & 0xfffff000) == 0x4000) s = 0;
return s;
}
J k10_res_script(V **a1, char *a2) {
if (a2[0] != ':')
return (J)read_path_into_text(a1, a2);
pair_chain_walk_recurse(1, a2);
write_cstr_stderr((char *)"path?");
write_cstr_stderr("\n");
return 0xc;
}
uJ k10_send_framed(I fd, V **p) {
V *c = (char *)p - 4;
I l = *(I *)((char *)p - 4) + 4;
while (1) {
I w = (I)write(fd, c, (size_t)l);
if (w <= 0) {
shutdown(fd, SHUT_RDWR);
close(fd);
K_CLIENT_FLAG_SET(fd, 0);
release_object((V **)p);
return 0;
}
c = (char *)c + w;
if (l == w) break;
l -= w;
}
release_object((V **)p);
return 1;
}
J k10_read_exact(I fd, I w, J b) {
J c = b;
I l = w;
while (1) {
I g = (I)read(fd, (V *)c, (size_t)l);
if (g <= 0) {
shutdown(fd, SHUT_RDWR);
close(fd);
K_CLIENT_FLAG_SET(fd, 0);
return 0;
}
c += g;
if (l == g) return 1;
l -= g;
}
}
J k10_epoll_add(V *f_arg) {
I f = (I)(intptr_t)f_arg;
uJ e = (uJ)epoll_instance_fd;
if (e == 0) e = (uJ)epoll_create1(0);
epoll_instance_fd = (I)e;
epoll_scratch_fd = (uI)f;
struct epoll_event *ev =
(struct epoll_event *)&epoll_scratch_event;
return epoll_ctl((I)e, EPOLL_CTL_ADD, f, ev);
}
J k10_intern_cstr(J *c) {
size_t l = (size_t)((char *)memchr(c, 0, -1) -
(char *)c);
return box_atom(2,
extract_first_word_for_print(l, c));
}
J k10_char_to_k(V *b) {
uintptr_t v = (uintptr_t)b;
if (v == 0) return retain_object((V *)runtime_long_vector_16mb);
char r;
if (v > 0x33) {
if ((v & 0xfffffffffffffff8ULL) != 0x40)
return symbol_to_charvec_indexed(v);
r = (char)((v & 7) | 0x30);
} else if (v <= 0x1c)
return compare_aux_b(*(int8_t *)(compare_left_class + v));
else if (v > 0x1f)
return compare_aux_b(*(int8_t *)(compare_right_class + v));
else r = *(int8_t *)(compare_promote_class + v);
return make_char_pair(r, ':');
}
static uJ k10_res_punct_op(I b) {
char *s = ":+-*%&|<>=~!,^#_$?@.";
return (uJ)((char *)memchr(s, b, -1) -
(char *)compare_right_class);
}
static uJ k10_res_punct_main(I b, I k,
I v) {
if (k == '0')
return (uJ)0xb00000000000000ULL | (uJ)(b & K_NIBBLE_MAX);
if (k > '/' && k != '0' && k == '`')
return retain_object((V *)runtime_empty_atom_list_sentinel);
if (k == ' ') return 0;
if (k == '+') return k10_res_punct_op(b);
J *s = (J *)k10_intern_cstr((J *)&v);
return resolve_dotted_name(NULL, (uJ *)s, 0);
}
static uJ k10_res_punct_key(I b, I k,
I v) {
for (intptr_t j = -3; ; j++) {
uI vj = (uI)*(int8_t *)(adverb_continuation_set + j);
if (vj == (uI)b) break;
if (j == 0) return k10_res_punct_main(b, k, v);
}
return 2;
}
uJ k10_res_punct(I b) {
I v = b;
I k = b == 0 ? ';' :
(I)*(int8_t *)(bracket_pair_class +
(uJ)(b - 0x20));
for (intptr_t i = -5; i != 0; i++) {
uI v1 = (uI)*(int8_t *)(compare_left_class + i);
if (k == (I)v1) return k10_res_punct_key(b, k, v);
}
return 2;
}
static J *k10_bc_slot(G i, V *l,
V *g, J *v) {
if (i > K_OP_GLOBAL_THRESHOLD) {
J b = index_typed_vector((J)v,
i & ((1 << K_BC_OP_INDEX_LO) - 1));
return dictionary_seek_chain(b, 0, 0);
}
V *t = (i < K_OP_LOCAL_THRESHOLD) ? l : g;
return (J *)((char *)t +
((size_t)i << K_SLOT_LOG2_BASE));
}
static V k10_vm_init(K10VM *v, J *fn,
V *l, J *g) {
char *c = (char *)fn[0];
v->gv = (J *)fn[4];
v->gv3 = (J *)fn[3];
v->end = c + (uI)*(I *)(c - 4);
v->ip = c + 1;
v->locals = (char *)l - K_BYTECODE_LOCALS_OFF;
v->globals = (char *)g - K_BYTECODE_GLOBALS_OFF;
v->err = (l == 0 && g != 0) ? (J *)g[0] : 0;
}
static J *k10_op_ext(K10VM *v, K_U8 op) {
*--v->sp = index_typed_vector((J)v->gv3,
op - K_OP_EXT_BIAS);
return 0;
}
static J *k10_op_const(K10VM *v, K_U8 op) {
J *p = (J *)make_singleton_J(*v->sp);
*((char *)p - 6) = op - K_OP_CONSTPOOL_BIAS;
XT(p) = (G)K_TYPE_LITERAL_FUNC;
*v->sp = (J)p;
return 0;
}
static J *k10_op_slot_const(K10VM *v, K_U8 op) {
if (op > K_OP_GLOBAL_THRESHOLD)
return k10_op_const(v, op);
V *b = (op < K_OP_LOCAL_THRESHOLD) ?
v->locals : v->globals;
*--v->sp = (J)retain_object(((J **)b)[op]);
return 0;
}
static J *k10_op_typed_word(K10VM *v, K_U8 op) {
J *r = extract_first_typed_word(op,
*v->sp, v->sp[1], 0);
v->sp++;
*v->sp = (J)r;
return K_IS_ERR_RETURN(r) ? r : 0;
}
static J *k10_op_typed_dot(K10VM *v, K_U8 op) {
uJ a = index_typed_vector((J)v->gv,
op & ((1 << K_BC_OP_INDEX_LO) - 1));
J *r = resolve_dotted_name(v->err,
(uJ *)a, 0);
*--v->sp = (J)r;
return K_IS_ERR_RETURN(r) ? r : 0;
}
static J *k10_op_typed(K10VM *v, K_U8 op,
K_U8 cls) {
if (cls == 2) return k10_op_typed_word(v, op);
if (cls == 3) return k10_op_typed_dot(v, op);
J *r = extract_first_typed_byte(op,
*v->sp, 0, 0);
*v->sp = (J)r;
return K_IS_ERR_RETURN(r) ? r : 0;
}
static J *k10_prim_idx(K10VM *v) {
J *s = k10_bc_slot((K_U8)v->ip[0],
v->locals, v->globals, v->gv);
J *r = extract_first_typed_word((K_U8)v->ip[1],
*s, *v->sp, 0);
*s = (J)r;
P(K_IS_ERR_RETURN(r), r);
v->ip += 2;
*v->sp = (v->ip < v->end) ? (J)retain_object(r) : (J)0;
return 0;
}
static J *k10_prim_idxg(K10VM *v) {
J *s = k10_bc_slot((K_U8)v->ip[0],
v->locals, v->globals, v->gv);
J *p = (J *)retain_object((V *)*v->sp);
J *r = sym_lookup_and_apply_dyadic(*s,
*v->sp, (K_U8)v->ip[1], v->sp[1]);
*s = (J)r;
P(K_IS_ERR_RETURN(r), r);
v->sp++;
*v->sp = (J)sym_lookup_and_apply(r, p, 0);
v->ip += 2;
return 0;
}
static J *k10_prim_cmp(K10VM *v) {
size_t s = k10_is_truthy((V **)*v->sp) == 0 ?
(K_U8)v->ip[0] : 1;
v->sp++;
v->ip += s;
return 0;
}
static J *k10_prim_chk(K10VM *v) {
J *p = (J *)*v->sp;
K_U8 n = (K_U8)v->ip[0];
J *r = (J *)apply_n_args(p, n,
(uJ)(v->sp + 1));
release_object((V **)p);
P(K_IS_ERR_RETURN(r), r);
v->sp += n;
*v->sp = (J)r;
v->ip += 1;
return 0;
}
static J *k10_op_prim(K10VM *v, K_U8 op) {
if (op == 0) return k10_prim_idx(v);
if (op == 1) return k10_prim_idxg(v);
if (op == 3) { v->ip += (int8_t)v->ip[0] + 1; return 0; }
if (op == 4) return k10_prim_cmp(v);
if (op == 5) return k10_prim_chk(v);
if (op == 6) { *--v->sp = (K_U8)v->ip[0]; v->ip++; return 0; }
if (op == 7) {
*--v->sp = (J)epoch_clock_get((K_U8)v->ip[0]);
v->ip++; return 0;
}
if (op == 8) {
emit_initial_eval_result(
(uJ)retain_object((V *)*v->sp), 0, 0, 0); return 0;
}
if (op == 9) release_object((V **)(V *)*v->sp++);
return 0;
}
static J *k10_vm_step(K10VM *v) {
K_U8 op = (K_U8)*v->ip++;
K_U8 cls = op >> K_BC_OP_INDEX_LO;
if (cls > K_OP_CLASS_EXTENDED)
return k10_op_ext(v, op);
if (cls == 0 && op > 9)
return k10_op_slot_const(v, op);
if (cls != 0)
return k10_op_typed(v, op, cls);
return k10_op_prim(v, op);
}
J *k10_eval_bc(J *fn, V *l, J *g) {
K10VM v;
J stack[K_BC_STACK_SLOTS] = {0};
k10_vm_init(&v, fn, l, g);
v.sp = stack + (uJ)(K_U8)v.ip[-1];
if (v.end - v.ip < 1) return (J *)*v.sp;
while (v.ip < v.end) {
J *r = k10_vm_step(&v);
if (r) return r;
}
return (J *)*v.sp;
}
uJ k10_is_truthy(V **v) {
if (TAG((J)v) != 0)
return reshape_or_canonicalize_dispatch(v);
if ((uintptr_t)v <= K_TRUTHY_FALSE_MAX)
return (uintptr_t)v > K_OP_GLOBAL_THRESHOLD;
uJ r = pair_chain_length(v) != 0;
release_object((V **)v);
return r;
}
static char g_k10_arena[KA_ARENA_BYTES];
static size_t g_k10_used;
static KAst *g_k10_ast_chain;
static V *kmini_arena_alloc(size_t n) {
n = (n + 7) & ~(size_t)7;
if (g_k10_used + n > KA_ARENA_BYTES) return 0;
V *p = g_k10_arena + g_k10_used;
g_k10_used += n;
return p;
}
static V k10_arena_reset(void) {
g_k10_used = 0;
g_k10_ast_chain = 0;
}
static KAst *k10_ast_new(KAstKind k) {
KAst *n = (KAst *)kmini_arena_alloc(sizeof(KAst));
if (!n) return 0;
memset(n, 0, sizeof *n);
n->kind = k;
n->arena_next = g_k10_ast_chain;
g_k10_ast_chain = n;
return n;
}
static KVal *k10_val_new(KValKind k) {
KVal *v = (KVal *)kmini_arena_alloc(sizeof(KVal));
if (!v) return 0;
memset(v, 0, sizeof *v);
v->kind = k;
return v;
}
static KMiniBinding g_k10_bindings[KMINI_MAX_BINDINGS];
static I g_k10_n_bindings;
static KMiniBinding *k10_bind_lookup(const char *n) {
for (I i = 0; i < g_k10_n_bindings; i++) {
if (strcmp(g_k10_bindings[i].name, n) == 0)
return &g_k10_bindings[i];
}
return 0;
}
static I k10_persist_vec(KMiniBinding *b,
const V *v, size_t n, size_t *o) {
if (*o + n > sizeof b->storage) return 0;
memcpy(b->storage + *o, v, n);
*o += n;
return 1;
}
static KVal *k10_val_persist(const KVal *s,
KMiniBinding *b) {
if (!s) return 0;
KVal *d = (KVal *)b->storage;
*d = *s;
size_t o = sizeof(KVal);
if (s->kind == K_VAL_LONG_VEC && s->lvec) {
if (k10_persist_vec(b, s->lvec, s->n * 8, &o))
d->lvec = (J *)(b->storage + o - s->n * 8);
else return 0;
} else if (s->kind == K_VAL_FLOAT_VEC && s->fvec) {
if (k10_persist_vec(b, s->fvec, s->n * 8, &o))
d->fvec = (F *)(b->storage + o - s->n * 8);
else return 0;
} else if (s->kind == K_VAL_CHAR_VEC && s->cvec) {
if (k10_persist_vec(b, s->cvec, s->n, &o))
d->cvec = b->storage + o - s->n;
else return 0;
}
b->used = 1; return d;
}
static V k10_bind_store(const char *n,
const KVal *v) {
KMiniBinding *s = k10_bind_lookup(n);
if (!s) {
if (g_k10_n_bindings >= KMINI_MAX_BINDINGS)
return;
s = &g_k10_bindings[g_k10_n_bindings++];
strncpy(s->name, n, sizeof s->name - 1);
s->name[sizeof s->name - 1] = 0;
}
s->value = k10_val_persist(v, s);
}
static I k10_is_op(char c) {
return LEX_BYTE_CLASS[(G)c] == ';';
}
static V k10_lex_comment(KLex *L, G c) {
while (*L->src && *L->src != '\n') L->src++;
L->cur.kind = KTOK_END;
}
static V k10_lex_paren(KLex *L, G c) {
L->src++;
L->cur.kind = (c == '(') ? KTOK_LP : KTOK_RP;
}
static V k10_lex_bracket(KLex *L, G c) {
L->src++;
L->cur.kind = (c == '[') ? KTOK_LB : KTOK_RB;
}
static V k10_lex_curly(KLex *L, G c) {
L->src++;
L->cur.kind = (c == '{') ? KTOK_LCURLY : KTOK_RCURLY;
L->err = KLEX_ERR_NEEDS_FULL_PARSER;
}
static V k10_lex_simple(KLex *L, KTokKind k) {
L->src++; L->cur.kind = k;
}
static V k10_lex_bang(KLex *L, G c) {
L->src++; L->cur.kind = KTOK_OP; L->cur.op = '!';
}
static V k10_lex_colon(KLex *L, G c) {
L->src++; L->cur.kind = KTOK_OP; L->cur.op = ':';
if (*L->src == ':') L->src++;
}
static char k10_lex_escape(char c) {
if (c == 'n') return '\n';
if (c == 't') return '\t';
if (c == 'r') return '\r';
if (c == '0') return '\0';
if (c == '\\') return '\\';
if (c == '"') return '"';
return c;
}
static V k10_lex_string(KLex *L, G c) {
I n = 0; L->src++; L->cur.text[0] = 0;
while (*L->src && *L->src != '"' &&
n < (I)sizeof L->cur.text - 1) {
if (*L->src == '\\' && L->src[1]) {
L->src++; L->cur.text[n++] = k10_lex_escape(*L->src++);
} else L->cur.text[n++] = *L->src++;
}
L->cur.text[n] = 0;
if (*L->src == '"') L->src++;
else L->err = KLEX_ERR_UNTERM_STR;
L->cur.kind = KTOK_STR; L->cur.lval = n;
}
static V k10_lex_symbol(KLex *L, G c) {
I n = 0; L->src++;
while (n < (I)sizeof L->cur.text - 1) {
K_U8 k = LEX_BYTE_CLASS[(G)*L->src];
if (k != '1' && k != '0' && k != '2' &&
*L->src != '.') break;
L->cur.text[n++] = *L->src++;
}
L->cur.text[n] = 0; L->cur.kind = KTOK_SYM;
}
static F k10_lex_pow10(I exp) {
F mul = 1.0;
while (exp-- > 0) mul *= 10.0;
return mul;
}
static V k10_lex_num(KLex *L, G c) {
J lv = 0; I isf = 0; F fv = 0.0;
while (LEX_BYTE_CLASS[(G)*L->src] == '0') {
lv = lv * 10 + (*L->src - '0'); L->src++;
}
if (*L->src == '.' &&
LEX_BYTE_CLASS[(G)L->src[1]] == '0') {
F fr = 0.0, sc = 1.0; isf = 1; L->src++;
while (LEX_BYTE_CLASS[(G)*L->src] == '0') {
fr = fr * 10.0 + (*L->src - '0');
sc *= 10.0; L->src++;
}
fv = (F)lv + fr / sc;
}
L->cur.kind = isf ? KTOK_FLOAT : KTOK_LONG;
if (isf) L->cur.fval = fv;
else L->cur.lval = lv;
}
static V k10_lex_name(KLex *L, G c) {
I n = 0;
while (n < (I)sizeof L->cur.text - 1) {
K_U8 k = LEX_BYTE_CLASS[(G)*L->src];
if (k != '1' && k != '0' && k != '2') break;
L->cur.text[n++] = *L->src++;
}
L->cur.text[n] = 0; L->cur.kind = KTOK_NAME;
}
static V k10_lex_op(KLex *L, G c) {
L->src++; L->cur.kind = KTOK_OP; L->cur.op = (char)c;
}
static V k10_lex_cmp(KLex *L, G c) {
L->src++;
if (*L->src == ':' || *L->src == '=') L->src++;
L->cur.kind = KTOK_OP; L->cur.op = (char)c;
}
static V k10_lex_slash(KLex *L, G c) {
L->src++; L->cur.kind = KTOK_OP; L->cur.op = '\\';
L->err = KLEX_ERR_NEEDS_FULL_PARSER;
}
static V k10_lex_bad(KLex *L, G c) {
L->src++; L->err = KLEX_ERR_BAD_BYTE;
L->cur.kind = KTOK_END;
}
static KLexHandler const K10_LEX_HANDLER[256] = {
['W'] = k10_lex_comment, ['7'] = k10_lex_paren,
['6'] = k10_lex_bracket, ['8'] = k10_lex_curly,
['B'] = k10_lex_bang, [':'] = k10_lex_colon,
['X'] = k10_lex_string, ['Y'] = k10_lex_symbol,
['0'] = k10_lex_num, ['1'] = k10_lex_name,
['2'] = k10_lex_name, [';'] = k10_lex_op,
['<'] = k10_lex_cmp, ['='] = k10_lex_cmp,
['>'] = k10_lex_cmp, ['9'] = k10_lex_slash
};
V k10_lex_advance(KLex *L) {
G c; K_U8 cls;
for (;;) {
c = (G)*L->src;
cls = LEX_BYTE_CLASS[c];
if (cls != '3') break;
L->src++;
}
if (c == 0 || cls == '4') {
L->cur.kind = KTOK_END; return;
}
KLexHandler h = K10_LEX_HANDLER[cls];
if (cls == '5') k10_lex_simple(L, KTOK_SEMI);
else if (cls == 'T') k10_lex_simple(L, KTOK_TICK);
else if (h) h(L, c);
else k10_lex_bad(L, c);
}
static I k10_is_primary(const KTok *t) {
if (t->kind == KTOK_LONG) return 1;
if (t->kind == KTOK_FLOAT) return 1;
if (t->kind == KTOK_NAME) return 1;
if (t->kind == KTOK_SYM) return 1;
if (t->kind == KTOK_STR) return 1;
if (t->kind == KTOK_LP) return 1;
if (t->kind == KTOK_LB) return 1;
if (t->kind == KTOK_OP) return t->op != ':';
return 0;
}
static I k10_is_verb(char op) {
return op != ':' && op != 0;
}
static KAst *k10_post_each(KLex *L, KAst *left) {
k10_lex_advance(L); KAst *r = 0;
if (k10_is_primary(&L->cur)) r = k10_parse_expr(L);
KAst *e = k10_ast_new(K_AST_EACH);
if (e) { e->a = left; e->b = r; }
return e;
}
static KAst *k10_post_over(KLex *L, KAst *left) {
k10_lex_advance(L); KAst *r = 0;
if (k10_is_primary(&L->cur)) r = k10_parse_expr(L);
KAst *o = k10_ast_new(K_AST_OVER);
if (o) { o->a = left; o->b = r; }
return o;
}
static KAst *k10_post_scan(KLex *L, KAst *left) {
k10_lex_advance(L); KAst *r = 0;
if (kmini_tok_starts_primary(&L->cur)) {
r = k10_parse_expr(L);
}
KAst *s = kmini_ast_new(K_AST_SCAN);
if (s) { s->a = left; s->b = r; }
return s;
}
static KAst *k10_post_as(KLex *L, KAst **as, I *an) {
if (L->cur.kind != KTOK_RB) {
as[(*an)++] = k10_parse_expr(L);
while (L->cur.kind == KTOK_SEMI && *an < 16) {
klex_advance(L);
as[(*an)++] = k10_parse_expr(L);
}
}
if (L->cur.kind == KTOK_RB) klex_advance(L);
else L->err = 1;
return 0;
}
static KAst *k10_post_idx_mk(KAst *left, KAst **as, I n) {
KAst *ix = kmini_ast_new(K_AST_INDEX);
if (!ix) return 0;
ix->a = left;
if (n == 1) ix->b = as[0];
if (n <= 1) return ix;
size_t sz = (size_t)n * sizeof(KAst *);
ix->kids = (KAst **)kmini_alloc(sz);
if (ix->kids) {
memcpy(ix->kids, as, sz);
ix->n_kids = n;
ix->b = as[0];
}
return ix;
}
static KAst *k10_post_idx(KLex *L, KAst *left) {
klex_advance(L);
KAst *as[16]; I an = 0;
k10_post_as(L, as, &an);
return k10_post_idx_mk(left, as, an);
}
static KAst *k10_parse_post(KLex *L, KAst *left) {
for (;;) {
if (L->cur.kind == KTOK_TICK) {
left = k10_post_each(L, left); continue; }
if (L->cur.kind == KTOK_OP && L->cur.op == '/') {
left = k10_post_over(L, left); continue; }
if (L->cur.kind == KTOK_OP && L->cur.op == '\\') {
left = k10_post_scan(L, left); continue; }
if (L->cur.kind == KTOK_LB) {
left = k10_post_idx(L, left); continue; }
break;
}
return left;
}
static KAst *k10_ast_list(KAst **src, I n) {
KAst *ls = kmini_ast_new(K_AST_LIST);
if (!ls) return 0;
size_t sz = (size_t)n * sizeof(KAst *);
ls->kids = (KAst **)kmini_alloc(sz);
if (ls->kids) {
memcpy(ls->kids, src, sz);
ls->n_kids = n;
}
return ls;
}
static KAst *k10_new_num(KLex *L) {
KAstKind k = L->cur.kind == KTOK_LONG ?
K_AST_LONG : K_AST_FLOAT;
KAst *it = kmini_ast_new(k);
if (!it) return 0;
if (k == K_AST_LONG) it->l = L->cur.lval;
if (k == K_AST_FLOAT) it->f = L->cur.fval;
klex_advance(L);
return it;
}
static KAst *k10_absorb_vec(KLex *L, KAst *h) {
if (L->cur.kind != KTOK_LONG &&
L->cur.kind != KTOK_FLOAT) return h;
KAst *ks[256]; I kn = 0;
ks[kn++] = h;
while ((L->cur.kind == KTOK_LONG ||
L->cur.kind == KTOK_FLOAT) && kn < 256) {
KAst *it = k10_new_num(L);
if (!it) break;
ks[kn++] = it;
}
KAst *ls = k10_ast_list(ks, kn);
if (ls) return ls;
return h;
}
static I k10_par_p(KLex *L, KAst *lam) {
if (L->cur.kind != KTOK_LB) return 0;
klex_advance(L);
while (L->cur.kind == KTOK_NAME && lam->n_params < 8) {
char *p = lam->params[lam->n_params];
strncpy(p, L->cur.text, 7);
p[7] = 0;
lam->n_params++;
klex_advance(L);
if (L->cur.kind == KTOK_SEMI) klex_advance(L);
else break;
}
if (L->cur.kind == KTOK_RB) klex_advance(L);
else L->err = 1;
return 1;
}
static I k10_par_b(KLex *L, KAst **body) {
I bn = 0;
if (L->cur.kind != KTOK_END) {
body[bn++] = k10_parse_expr(L);
while (L->cur.kind == KTOK_SEMI && bn < 64) {
klex_advance(L);
if (L->cur.kind == KTOK_END) break;
body[bn++] = k10_parse_expr(L);
}
}
return bn;
}
static KAst *k10_parse_lam(KLex *L) {
KAst *lam = kmini_ast_new(K_AST_LAMBDA);
if (!lam) { L->err = 1; return 0; }
k10_par_p(L, lam);
KAst *body[64];
I bn = k10_par_b(L, body);
if (bn == 1) lam->a = body[0];
if (bn > 1) lam->a = k10_ast_list(body, bn);
return lam;
}
static KAst *k10_parse_num(KLex *L, KAstKind kind) {
KAst *n = kmini_ast_new(kind);
if (n && kind == K_AST_LONG) n->l = L->cur.lval;
if (n && kind == K_AST_FLOAT) n->f = L->cur.fval;
klex_advance(L);
return k10_absorb_vec(L, n);
}
static KAst *k10_parse_name(KLex *L, KAstKind kind) {
KAst *n = kmini_ast_new(kind);
if (n) {
strncpy(n->name, L->cur.text, 31);
n->name[31] = 0;
}
klex_advance(L);
return n;
}
static KAst *k10_parse_str(KLex *L) {
KAst *n = kmini_ast_new(K_AST_LIST);
if (n && L->cur.lval >= 0) {
I sn = (I)L->cur.lval;
n->n_kids = sn;
size_t sz = (size_t)sn * sizeof(KAst *);
n->kids = (KAst **)kmini_alloc(sz);
for (I i = 0; i < sn; i++) {
KAst *ch = kmini_ast_new(K_AST_LONG);
if (ch) ch->l = (G)L->cur.text[i];
if (n->kids) n->kids[i] = ch;
}
}
klex_advance(L);
return n;
}
static KAst *k10_parse_lam_prim(KLex *L) {
L->err = 0; L->src++;
klex_advance(L);
KAst *lam = k10_parse_lam(L);
if (L->src && *L->src == '}') {
L->err = 0; L->src++;
klex_advance(L);
}
return k10_parse_post(L, lam);
}
static KAst *k10_ast_verb(char op) {
KAst *n = kmini_ast_new(K_AST_VERB);
if (n) { n->op = op; n->a = 0; n->b = 0; }
return n;
}
static KAst *k10_par_adv(KLex *L, char op) {
char adv = L->cur.op;
klex_advance(L);
if (L->cur.kind == KTOK_RP) {
klex_advance(L);
KAstKind k = adv == '/' ? K_AST_OVER : K_AST_SCAN;
KAst *an = kmini_ast_new(k);
if (an) { an->a = k10_ast_verb(op); an->b = 0; }
return k10_parse_post(L, an);
}
return 0;
}
static KAst *k10_p_vn(KLex *L) {
if (L->cur.kind != KTOK_OP ||
!kmini_op_is_verb(L->cur.op)) return 0;
char op = L->cur.op; KLex save = *L;
klex_advance(L);
if (L->cur.kind == KTOK_RP) {
klex_advance(L);
return k10_parse_post(L, k10_ast_verb(op));
}
if (L->cur.kind == KTOK_OP &&
(L->cur.op == '/' || L->cur.op == '\\')) {
KAst *res = k10_par_adv(L, op);
if (res) return res;
*L = save; return 0;
}
if (L->cur.kind == KTOK_TICK) {
klex_advance(L);
if (L->cur.kind == KTOK_RP) {
klex_advance(L);
KAst *e = kmini_ast_new(K_AST_EACH);
if (e) { e->a = k10_ast_verb(op); e->b = 0; }
return k10_parse_post(L, e);
}
}
*L = save; return 0;
}
static KAst *k10_p_ls(KLex *L, KAst *f) {
KAst *ks[256]; I kn = 0;
if (f) ks[kn++] = f;
while (L->cur.kind == KTOK_SEMI && kn < 256) {
klex_advance(L);
if (L->cur.kind == KTOK_RP) break;
ks[kn++] = k10_parse_expr(L);
}
return k10_ast_list(ks, kn);
}
static KAst *k10_parse_paren_prim(KLex *L) {
klex_advance(L);
KAst *vn = k10_p_vn(L);
if (vn) return vn;
KAst *f = L->cur.kind != KTOK_RP ?
k10_parse_expr(L) : 0;
if (L->cur.kind == KTOK_SEMI) {
f = k10_p_ls(L, f);
}
if (L->cur.kind == KTOK_RP) klex_advance(L);
else L->err = 1;
KAst *p = kmini_ast_new(K_AST_PAREN);
if (p) p->a = f;
return p;
}
static KAst *k10_parse_monad(KLex *L) {
char op = L->cur.op;
klex_advance(L);
KAst *vb = k10_ast_verb(op);
if (!vb) return 0;
if (kmini_tok_starts_primary(&L->cur) ||
(L->cur.kind == KTOK_OP &&
kmini_op_is_verb(L->cur.op)))
vb->b = k10_parse_expr(L);
return vb;
}
static KAst *k10_parse_adv_pre(KLex *L) {
klex_advance(L);
KAst *e = kmini_ast_new(K_AST_EACH);
if (e) { e->a = 0; e->b = k10_parse_expr(L); }
return e;
}
static KAst *k10_parse_prim(KLex *L) {
switch (L->cur.kind) {
case KTOK_LONG: return k10_parse_num(L, K_AST_LONG);
case KTOK_FLOAT: return k10_parse_num(L, K_AST_FLOAT);
case KTOK_NAME: return k10_parse_name(L, K_AST_NAME);
case KTOK_SYM: return k10_parse_name(L, K_AST_SYM);
case KTOK_STR: return k10_parse_str(L);
case KTOK_LP: return k10_parse_paren_prim(L);
case KTOK_OP:
return kmini_op_is_verb(L->cur.op) ?
k10_parse_monad(L) : kmini_ast_new(K_AST_NIL);
case KTOK_TICK: return k10_parse_adv_pre(L);
case KTOK_END:
return (L->err && L->src && *L->src == '{') ?
k10_parse_lam_prim(L) : kmini_ast_new(K_AST_NIL);
default: return kmini_ast_new(K_AST_NIL);
}
}
static KAst *k10_parse_bind(KLex *L, KAst *left) {
klex_advance(L);
KAst *right = k10_parse_expr(L);
KAst *bn = kmini_ast_new(K_AST_BIND);
if (bn) {
strncpy(bn->name, left->name, 31);
bn->name[31] = 0;
bn->b = right;
}
return bn;
}
static KAst *k10_parse_dyad(KLex *L, KAst *left) {
char op = L->cur.op; klex_advance(L);
KAst *right = k10_parse_expr(L);
KAst *vb = kmini_ast_new(K_AST_VERB);
if (vb) { vb->op = op; vb->a = left; vb->b = right; }
return vb;
}
static KAst *k10_parse_expr(KLex *L) {
KAst *left = k10_parse_prim(L);
left = k10_parse_post(L, left);
if (left && left->kind == K_AST_NAME &&
L->cur.kind == KTOK_OP && L->cur.op == ':')
return k10_parse_bind(L, left);
if (L->cur.kind == KTOK_OP &&
kmini_op_is_verb(L->cur.op))
return k10_parse_dyad(L, left);
if (left && (left->kind == K_AST_LAMBDA ||
left->kind == K_AST_VERB || left->kind == K_AST_EACH ||
left->kind == K_AST_OVER || left->kind == K_AST_SCAN) &&
kmini_tok_starts_primary(&L->cur)) {
KAst *right = k10_parse_expr(L);
KAst *ix = kmini_ast_new(K_AST_INDEX);
if (ix) { ix->a = left; ix->b = right; }
return ix;
}
return left;
}
static I k10_is_num_val(const KVal *v) {
if (!v) return 0;
return v->kind == K_VAL_LONG ||
v->kind == K_VAL_FLOAT ||
v->kind == K_VAL_LONG_VEC ||
v->kind == K_VAL_FLOAT_VEC;
}
static F k10_to_f64(const KVal *v, I i) {
if (!v) return 0;
if (v->kind == K_VAL_LONG) return (F)v->l;
if (v->kind == K_VAL_FLOAT) return v->f;
if (v->kind == K_VAL_LONG_VEC)
return i < v->n ? (F)v->lvec[i] : 0;
if (v->kind == K_VAL_FLOAT_VEC)
return i < v->n ? v->fvec[i] : 0;
return 0;
}
static J k10_to_i64(const KVal *v, I i) {
if (!v) return 0;
if (v->kind == K_VAL_LONG) return v->l;
if (v->kind == K_VAL_FLOAT) return (J)v->f;
if (v->kind == K_VAL_LONG_VEC)
return i < v->n ? v->lvec[i] : 0;
if (v->kind == K_VAL_FLOAT_VEC)
return i < v->n ? (J)v->fvec[i] : 0;
return 0;
}
static I k10_val_len(const KVal *v) {
if (!v) return 0;
if (v->kind == K_VAL_LONG ||
v->kind == K_VAL_FLOAT ||
v->kind == K_VAL_SYM) return 1;
if (v->kind == K_VAL_LONG_VEC ||
v->kind == K_VAL_FLOAT_VEC ||
v->kind == K_VAL_CHAR_VEC ||
v->kind == K_VAL_LIST) return v->n;
return 0;
}
static I k10_is_f64(const KVal *v) {
return v && (v->kind == K_VAL_FLOAT ||
v->kind == K_VAL_FLOAT_VEC);
}
static KVal *k10_mk_i64(J l) {
KVal *v = kmini_val_new(K_VAL_LONG);
if (v) v->l = l;
return v;
}
static KVal *k10_mk_f64(F f) {
KVal *v = kmini_val_new(K_VAL_FLOAT);
if (v) v->f = f;
return v;
}
static KVal *k10_mk_i64v(I n) {
KVal *v = kmini_val_new(K_VAL_LONG_VEC);
if (!v) return 0;
v->n = n;
size_t sz = (size_t)n * sizeof(J);
v->lvec = (J *)kmini_alloc(sz);
return v;
}
static KVal *k10_mk_f64v(I n) {
KVal *v = kmini_val_new(K_VAL_FLOAT_VEC);
if (!v) return 0;
v->n = n;
size_t sz = (size_t)n * sizeof(F);
v->fvec = (F *)kmini_alloc(sz);
return v;
}
static KVal *k10_arith_div(char op, F x, F y, I flt) {
if (y == 0) return k10_mk_i64(0);
F r = flt ? x / y : (F)((J)x / (J)y);
return flt ? k10_mk_f64(r) : k10_mk_i64((J)r);
}
static KVal *k10_arith(char op, F x, F y, I flt) {
F r = 0;
if (op == '+') r = x + y;
else if (op == '-') r = x - y;
else if (op == '*') r = x * y;
else if (op == '%') return k10_arith_div(op, x, y, flt);
else if (op == '&') r = x < y ? x : y;
else if (op == '|') r = x > y ? x : y;
else if (op == '<') return k10_mk_i64(x < y);
else if (op == '>') return k10_mk_i64(x > y);
else if (op == '=') return k10_mk_i64(x == y);
else if (op == '~') return k10_mk_i64(x == y);
else return 0;
return flt ? k10_mk_f64(r) : k10_mk_i64((J)r);
}
static KVal *k10_cat(KVal *a, KVal *b) {
I la = k10_val_len(a), lb = k10_val_len(b);
I tot = la + lb, flt = k10_is_f64(a) || k10_is_f64(b);
if (flt) {
KVal *o = k10_mk_f64v(tot); if (!o) return 0;
for (I i = 0; i < la; i++) o->fvec[i] = k10_to_f64(a, i);
for (I i = 0; i < lb; i++) o->fvec[la+i] = k10_to_f64(b, i);
return o;
}
KVal *o = k10_mk_i64v(tot); if (!o) return 0;
for (I i = 0; i < la; i++) o->lvec[i] = k10_to_i64(a, i);
for (I i = 0; i < lb; i++) o->lvec[la+i] = k10_to_i64(b, i);
return o;
}
static KVal *k10_at_val(KVal *a, KVal *b) {
I idx = (I)k10_to_i64(b, 0), la = k10_val_len(a);
if (idx < 0 || idx >= la) return k10_mk_i64(0);
if (a->kind == K_VAL_FLOAT_VEC)
return k10_mk_f64(a->fvec[idx]);
if (a->kind == K_VAL_LONG_VEC)
return k10_mk_i64(a->lvec[idx]);
return a;
}
static KVal *k10_dy_v(char op, KVal *a, KVal *b) {
I la = k10_val_len(a), lb = k10_val_len(b);
I n = la > lb ? la : lb, flt = k10_is_f64(a) || k10_is_f64(b);
if (la != 1 && lb != 1 && la != lb) return 0;
if (flt) {
KVal *o = k10_mk_f64v(n); if (!o) return 0;
for (I i = 0; i < n; i++) {
F xv = k10_to_f64(a, la == 1 ? 0 : i);
F yv = k10_to_f64(b, lb == 1 ? 0 : i);
KVal *v = k10_arith(op, xv, yv, 1);
o->fvec[i] = v ? k10_to_f64(v, 0) : 0;
}
return o;
}
KVal *o = k10_mk_i64v(n); if (!o) return 0;
for (I i = 0; i < n; i++) {
F xv = k10_to_f64(a, la == 1 ? 0 : i);
F yv = k10_to_f64(b, lb == 1 ? 0 : i);
KVal *v = k10_arith(op, xv, yv, 0);
o->lvec[i] = v ? k10_to_i64(v, 0) : 0;
}
return o;
}
static KVal *k10_dyad(char op, KVal *a, KVal *b) {
if (!a || !b) return 0;
if (op == ',') return k10_cat(a, b);
if (op == '@') return k10_at_val(a, b);
I la = k10_val_len(a), lb = k10_val_len(b);
I flt = k10_is_f64(a) || k10_is_f64(b);
if (la == 1 && lb == 1)
return k10_arith(op, k10_to_f64(a, 0), k10_to_f64(b, 0), flt);
return k10_dy_v(op, a, b);
}
static KVal *k10_mon_neg(KVal *a, I n) {
if (n == 1) {
if (k10_is_f64(a)) return k10_mk_f64(-k10_to_f64(a, 0));
return k10_mk_i64(-k10_to_i64(a, 0));
}
if (k10_is_f64(a)) {
KVal *o = k10_mk_f64v(n); if (!o) return 0;
for (I i = 0; i < n; i++) o->fvec[i] = -k10_to_f64(a, i);
return o;
}
KVal *o = k10_mk_i64v(n); if (!o) return 0;
for (I i = 0; i < n; i++) o->lvec[i] = -k10_to_i64(a, i);
return o;
}
static KVal *k10_mon_rev(KVal *a, I n) {
if (n <= 1) return a;
if (k10_is_f64(a)) {
KVal *o = k10_mk_f64v(n); if (!o) return 0;
for (I i = 0; i < n; i++) o->fvec[i] = k10_to_f64(a, n-1-i);
return o;
}
KVal *o = k10_mk_i64v(n); if (!o) return 0;
for (I i = 0; i < n; i++) o->lvec[i] = k10_to_i64(a, n-1-i);
return o;
}
static KVal *k10_mon_not(KVal *a, I n) {
if (n == 1) return k10_mk_i64(k10_to_i64(a, 0) == 0);
KVal *o = k10_mk_i64v(n); if (!o) return 0;
for (I i = 0; i < n; i++) o->lvec[i] = k10_to_i64(a, i) == 0;
return o;
}
static KVal *k10_mon_where(KVal *a, I n) {
I tot = 0;
for (I i = 0; i < n; i++) tot += (I)k10_to_i64(a, i);
KVal *o = k10_mk_i64v(tot); if (!o) return 0;
I j = 0;
for (I i = 0; i < n; i++) {
J cnt = k10_to_i64(a, i);
for (J k = 0; k < cnt; k++) o->lvec[j++] = i;
}
return o;
}
static KVal *k10_monad(char op, KVal *a) {
if (!a) return 0;
I n = k10_val_len(a);
if (op == '-') return k10_mon_neg(a, n);
if (op == '|') return k10_mon_rev(a, n);
if (op == '#') return k10_mk_i64(n);
if (op == '+') return a;
if (op == '*') {
if (k10_is_f64(a)) return k10_mk_f64(k10_to_f64(a, 0));
return k10_mk_i64(k10_to_i64(a, 0));
}
if (op == '!') {
I m = (I)k10_to_i64(a, 0); if (m < 0) m = 0;
KVal *o = k10_mk_i64v(m); if (!o) return 0;
for (I i = 0; i < m; i++) o->lvec[i] = i;
return o;
}
if (op == '~') return k10_mon_not(a, n);
if (op == '&') return k10_mon_where(a, n);
return a;
}
static I k10_is_err(const KVal *v) {
return v && v->kind == K_VAL_SYM && v->sym[0] == '\'';
}
static KVal *k10_mk_err(const char *name) {
KVal *v = kmini_val_new(K_VAL_SYM);
if (!v) return 0;
v->sym[0] = '\''; I i = 0;
while (name[i] && i + 1 < 31) {
v->sym[i+1] = name[i]; i++;
}
v->sym[i+1] = 0; return v;
}
static KVal *k10_apply(KAst *fn, KVal *x, KVal *y) {
while (fn && fn->kind == K_AST_PAREN) fn = fn->a;
if (fn && fn->kind == K_AST_VERB) {
return y == 0 ? k10_monad(fn->op, x) :
k10_dyad(fn->op, x, y);
}
return y == 0 ? x : y;
}
static I k10_is_adv(KAst *n, char adv) {
if (!n || n->kind != K_AST_VERB || n->a) return 0;
if (!n->b || n->b->kind != K_AST_VERB || n->b->a) return 0;
return n->b->op == adv;
}
static KVal *k10_lift(const KVal *v, I i, I flt) {
return flt ? k10_mk_f64(k10_to_f64(v, i)) :
k10_mk_i64(k10_to_i64(v, i));
}
static KVal *k10_eval_ln(KAst *n, KVal **vs) {
I al = 1, hf = 0, aa = 1;
for (I i = 0; i < n->n_kids; i++) {
vs[i] = k10_eval(n->kids[i]);
if (k10_is_err(vs[i])) return vs[i];
if (!vs[i]) { aa = 0; al = 0; continue; }
if (vs[i]->kind == K_VAL_FLOAT) { hf = 1; al = 0; }
else if (vs[i]->kind != K_VAL_LONG) { al = 0; aa = 0; }
}
if (aa && al) {
KVal *o = k10_mk_i64v(n->n_kids); if (!o) return 0;
for (I i = 0; i < n->n_kids; i++) o->lvec[i] = vs[i]->l;
return o;
}
if (aa && hf) {
KVal *o = k10_mk_f64v(n->n_kids); if (!o) return 0;
for (I i = 0; i < n->n_kids; i++)
o->fvec[i] = vs[i]->kind == K_VAL_FLOAT ? vs[i]->f : vs[i]->l;
return o;
}
KVal *o = kmini_val_new(K_VAL_LIST); if (!o) return 0;
o->n = n->n_kids; o->list = vs; return o;
}
static KVal *k10_eval_v(KAst *n) {
if (k10_is_adv(n, '/')) {
KAst l = {0}, o = {0}; l.kind = K_AST_VERB;
l.op = n->op; o.kind = K_AST_OVER;
o.a = &l; o.b = n->b->b; return k10_eval(&o);
}
KVal *b = k10_eval(n->b);
if (k10_is_err(b)) return b;
if (!n->a) return k10_monad(n->op, b);
KVal *a = k10_eval(n->a);
if (k10_is_err(a)) return a;
if (n->op != ',' && n->op != '@' && n->op != '#' &&
k10_val_len(a) > 1 && k10_val_len(b) > 1 &&
k10_val_len(a) != k10_val_len(b))
return k10_mk_err("length");
return k10_dyad(n->op, a, b);
}
static KVal *k10_eval_each(KAst *n) {
KVal *v = k10_eval(n->b); if (k10_is_err(v)) return v;
if (!n->a) return v;
I ln = k10_val_len(v), flt = k10_is_f64(v);
KVal *o = flt ? k10_mk_f64v(ln) : k10_mk_i64v(ln);
if (!o) return 0;
for (I i = 0; i < ln; i++) {
KVal *x = k10_lift(v, i, flt);
KVal *one = k10_apply(n->a, x, 0);
if (k10_is_err(one)) return one;
if (!one) continue;
if (flt) o->fvec[i] = k10_to_f64(one, 0);
else o->lvec[i] = k10_to_i64(one, 0);
}
return o;
}
static KVal *k10_eval_over(KAst *n) {
KVal *v = k10_eval(n->b); if (k10_is_err(v)) return v;
I ln = k10_val_len(v); if (ln == 0) return k10_mk_i64(0);
I flt = k10_is_f64(v); KVal *acc = k10_lift(v, 0, flt);
for (I i = 1; i < ln && acc; i++) {
acc = k10_apply(n->a, acc, k10_lift(v, i, flt));
if (k10_is_err(acc)) return acc;
}
return acc;
}
static KVal *k10_eval(KAst *n) {
if (!n) return k10_mk_i64(0);
if (n->kind == K_AST_LONG) return k10_mk_i64(n->l);
if (n->kind == K_AST_FLOAT) return k10_mk_f64(n->f);
if (n->kind == K_AST_NIL) return k10_mk_i64(0);
if (n->kind == K_AST_PAREN) return k10_eval(n->a);
if (n->kind == K_AST_SYM) {
KVal *v = kmini_val_new(K_VAL_SYM);
if (v) { strncpy(v->sym, n->name, 31); v->sym[31] = 0; }
return v;
}
if (n->kind == K_AST_NAME) {
KMiniBinding *s = kmini_bind_lookup(n->name);
return (s && s->value) ? s->value : k10_mk_err("value");
}
if (n->kind == K_AST_BIND) {
KVal *r = k10_eval(n->b);
if (r && !k10_is_err(r)) kmini_bind_store(n->name, r);
return r;
}
if (n->kind == K_AST_LIST) {
size_t sz = (size_t)n->n_kids * sizeof(KVal *);
KVal **vs = (KVal **)kmini_alloc(sz);
return vs ? k10_eval_ln(n, vs) : 0;
}
if (n->kind == K_AST_VERB) return k10_eval_v(n);
if (n->kind == K_AST_INDEX) {
KVal *s = k10_eval(n->a); if (k10_is_err(s)) return s;
KVal *i = k10_eval(n->b); if (k10_is_err(i)) return i;
return k10_dyad('@', s, i);
}
if (n->kind == K_AST_EACH) return k10_eval_each(n);
if (n->kind == K_AST_OVER) return k10_eval_over(n);
return k10_mk_i64(0);
}
static I k10_fmt_sym(const KVal *v, char *o, I c) {
I w = 0;
if (v->sym[0] == '\'') {
for (I i = 0; v->sym[i] && w < c - 1; i++)
o[w++] = v->sym[i];
} else {
if (w < c - 1) o[w++] = '`';
for (I i = 0; v->sym[i] && w < c - 1; i++)
o[w++] = v->sym[i];
}
return w;
}
static I k10_fmt_iv(const KVal *v, char *o, I c) {
if (v->n == 0) return snprintf(o, (size_t)c, "!0");
I w = 0;
for (I i = 0; i < v->n && w < c - 1; i++) {
if (i > 0 && w < c - 1) o[w++] = ' ';
w += snprintf(o + w, (size_t)(c - w), "%lld",
(long long)v->lvec[i]);
}
return w;
}
static I k10_fmt_fv(const KVal *v, char *o, I c) {
if (v->n == 0) return snprintf(o, (size_t)c, "!0");
I w = 0;
for (I i = 0; i < v->n && w + 1 < c; i++) {
if (i > 0) o[w++] = ' ';
w += snprintf(o + w, (size_t)(c - w), "%g", v->fvec[i]);
}
return w;
}
static I k10_fmt_ls(const KVal *v, char *o, I c) {
I w = 0;
if (w < c - 1) o[w++] = '(';
for (I i = 0; i < v->n; i++) {
if (i > 0 && w < c - 1) o[w++] = ';';
w += k10_fmt(v->list[i], o + w, c - w);
}
if (w < c - 1) o[w++] = ')';
return w;
}
static I k10_fmt(const KVal *v, char *o, I c) {
if (!v || c <= 0) return 0;
I w = 0;
if (v->kind == K_VAL_LONG)
w = snprintf(o, (size_t)c, "%lld", (long long)v->l);
else if (v->kind == K_VAL_FLOAT)
w = snprintf(o, (size_t)c, "%g", v->f);
else if (v->kind == K_VAL_SYM)
w = k10_fmt_sym(v, o, c);
else if (v->kind == K_VAL_LONG_VEC)
w = k10_fmt_iv(v, o, c);
else if (v->kind == K_VAL_FLOAT_VEC)
w = k10_fmt_fv(v, o, c);
else if (v->kind == K_VAL_CHAR_VEC) {
if (w < c - 1) o[w++] = '"';
for (I i = 0; i < v->n && w < c - 1; i++)
o[w++] = v->cvec[i];
if (w < c - 1) o[w++] = '"';
} else if (v->kind == K_VAL_LIST)
w = k10_fmt_ls(v, o, c);
else w = snprintf(o, (size_t)c, "0");
if (w < c) o[w] = 0; return w;
}
static I k10_ok_line(const char *l) {
I s = 0;
for (const char *p = l; *p && *p != '\n'; p++) {
if (s) {
if (*p == '"' && p[-1] != '\\') s = 0;
continue;
}
if (*p == '"') { s = 1; continue; }
if (*p == '{' || *p == '}' || *p == '\\') return 0;
if (*p == ':' && p[1] == '[') return 0;
if (*p == '/' && p > l) {
char v = p[-1];
if (v != ' ' && v != '\t' && v != '(' && v != ';')
return 0;
}
}
return 1;
}
static J *k10_eval_line_fast(const char *l) {
if (!l) return 0;
while (*l == ' ' || *l == '\t') l++;
if (*l == 0 || *l == '\n' || *l == '/') return 0;
if (!k10_ok_line(l)) return 0;
kmini_arena_reset(); KLex L; L.src = l; L.err = 0;
klex_advance(&L); KVal *last = 0; I n = 0;
for (;;) {
if (L.cur.kind == KTOK_END) break;
KAst *e = k10_parse_expr(&L);
if (L.err || !e) return 0;
last = k10_eval(e); n++;
if (L.cur.kind == KTOK_SEMI) {
klex_advance(&L); continue; }
break;
}
if (n == 0 || !last) return 0;
char b[4096]; I m = k10_fmt(last, b, 4094);
if (m > 0 && m < 4095) {
b[m++] = '\n'; write(1, b, (size_t)m);
}
return (J *)1;
}
J *eval_source_or_dispatch(char *line, J a2, I a3) {
G f = (G)line[0];
if (f == 0 || f == '/') return 0;
if (f == '\\') return slash_command_dispatch(line + 1, a2, a3);
{
J *fast = k10_eval_line_fast(line);
if (fast) return fast;
}
S v = cstr_to_charvec_trim(line);
J *p = parse_source_to_ast((__int128 *)v);
if (K_IS_ERR_RETURN(p)) return p;
J *r = sort_or_grade_inner(p, 0, 0);
release_object(p); return r;
}
static J *k10_help(void) {
static S h = "*ffi:\"./a.so\"5:`a!\"fiFI\"\n"
"python: from k import k;k('+',2,3)\n"
"nodejs: k=require('k').k;k('+',2,3)\n\n"
"$k [-p 1024] a.k\n\n"
"verb adverb noun \\l a.k\n"
": x y f' each char \" ab\" \\t:n x\n"
"+ flip plus [x]f/ over c/ join \\u:n x\n"
"- minus minus [x]f\\ scan c\\ splt \\v\n"
"* first times [y]f':eachprior \\w\n"
"% divide f/:eachright g/:over .z.d\n"
"& where min/and f\\:eachleft g\\:scan .z.t\n"
"| reverse max/or \n"
"< asc less i/o (*enterprise) class\n"
"> desc more 0: r/w line list (2;3.4;`c)\n"
"= group equal 1: r/w char dict [n:`b;i:2]\n"
"~ not match *2: r/w data func {[a;b]a+b}\n"
"! key key *3: k-ipc set expr :a+b\n"
", enlist cat *4: https get \n"
"^ sort [f]cut *5: ffi:`f!\"ifsIF\"\n"
"# count [f]take \n"
"_ floor [f]drop\n"
"$ string parse $[b;t;f] cond\n"
"? unique find limit {[p8]l8;g32;c128}\n"
"@ type [f]at @[x;i;f[;y]] amend \n"
". value [f]dot .[x;i;f[;y]] dmend \n\n"
"sqrt sqr exp log sin cos div mod bar in\n"
"select A by B from T where C; update A; ..\n"
"count first last min max sum dot avg var\n\n"
"/comment \\trace [:return 'signal if do while]\n";
S v = cstr_to_charvec_trim(h);
return split_charvec_into_lines(v);
}
static J *k10_time_cmd(I reps, S expr, J *pa) {
J t0 = now_ns_fast();
for (I i = 0; i < reps; i++) {
J *s = pa ? sort_or_grade_inner(pa, 0, 0) :
k10_slash(expr + 1, 0, 0);
if (K_IS_ERR(s)) return s;
release_object((V **)s);
}
J t1 = now_ns_fast();
J bud = t0 + (J)((uI)(reps * 24));
J act = (t1 - bud) >= 0 ? (t1 - bud) : 0;
J *res = (J *)(0xd00000000000000ULL |
(uJ)(uI)(act * 1e-6));
release_object((V **)pa); return res;
}
static J *k10_sl_spec(G f, I a3) {
const G *t = stmt_terminator_set;
for (I i = -2; i < 0; i++)
if (t[i] == f) return special_variable_get(f, 0, a3);
return (J *)9;
}
static S k10_sl_next(S c) {
S p = c; while (*p && *p != ' ') p++;
return p;
}
J *k10_slash(S cmd, J a2, I a3) {
G f = (G)*cmd;
if (f == '\\') flush_log_and_exit(0);
if (!f) return k10_help();
if (!cmd[1]) return k10_sl_spec(f, a3);
S p = k10_sl_next(cmd); I n = (I)(p - cmd), r = 1;
if (f != 't' && f != 'u')
return run_subprocess_or_builtin(n, cmd);
if (n != 1) {
if (cmd[1] != ':') return run_subprocess_or_builtin(1, cmd);
cmd[n] = 0; r = (I)(J)eval_source_or_dispatch(cmd+2, 0, 0);
}
S ex = cmd + n + 1; J *pa = 0;
if (*ex != '\\') {
S v = cstr_to_charvec_trim(ex);
pa = k10_parse_src((uJ *)v);
}
if (*ex == '\\' || !K_IS_ERR(pa))
return k10_time_cmd(r, ex, pa);
return pa;
}
static J k10_strip_comm(J *toks) {
I n = XN(toks); S s = (S)toks;
for (I i = 0; i < n - 1; i++) {
if (s[i] == ' ' && s[i+1] == '/') {
*(I *)(s - 4) = i;
return i;
}
}
return n;
}
static I k10_match_br(G c) {
if (c == '(') R ')';
if (c == '[') R ']';
if (c == '{') R '}';
R 0;
}
static S k10_skip_str(S s) {
G c;
while ((c = *++s) && c != '"') {
if (c == '\\') s++;
}
R s;
}
static I k10_check_bal(S s) {
G stk[99], c; I top = 0;
while ((c = *s)) {
I m = k10_match_br(c);
if (m) {
if (top == 99) R 0;
stk[top++] = m;
} else if (c == ')' || c == ']' || c == '}') {
if (!top || stk[--top] != c) R 0;
} else if (c == '"') s = k10_skip_str(s);
if (*s) s++;
}
R top == 0;
}
static J *k10_parse_err(J *toks) {
I col = (I)((S)parse_cursor - (S)toks);
if (col < 0) col = 0;
J *src = retain_object(toks);
if (!K_IS_ERR(src)) println_object(src);
if (col >= 0 && col < 4096) {
J *pd = allocate_typed_vector(K_TYPE_CHAR, col + 1);
if (!K_IS_ERR(pd)) {
memset(pd, ' ', col);
((S)pd)[col] = '^'; println_object(pd);
}
}
J *err = symbol_from_index(K_ERR_PARSE);
if (!K_IS_ERR(err)) println_object(err);
R (J *)1;
}
J *k10_parse_src(uJ *src) {
J *t = (J *)cast_table_dispatch(0x920, src);
k10_strip_comm(t);
if (!cast_to_decimal_inner(t, 0)) R k10_parse_err(t);
if (!* (G *)t) R k10_build_fn((J)t, 0, 0);
if (!k10_check_bal((S)t)) R k10_parse_err(t);
parse_cursor = (J)t; parse_token_start = (J)t;
J *ast = k10_build_fn((J)t, 0, 0);
if (K_IS_ERR(ast)) R k10_parse_err(t);
R ast;
}
static S k10_trim_line(S line) {
I n = XN(line); I i = 0;
for (; i < n - 1; i++) {
if (line[i] == ' ' && line[i+1] == '/') break;
}
*(I *)(line - 4) = i; R line;
}
static J *k10_flush_acc(S acc) {
if (!acc) R 0;
R k10_flush_buf((V **)acc);
}
J *k10_parse_lines(V **lines) {
I n = XN(lines); S acc = 0; I d = 0;
for (I i = 0; i < n; i++) {
S s = k10_trim_line((S)lines[i]); I len = XN(s);
if (!len) continue;
if (*s == '/') { d += (len == 1); continue; }
if (len == 1 && *s == '\\') {
if (d-- < 1) break; continue;
}
if (d) continue;
if (*s == ' ') {
S r = (S)retain_object(s);
acc = acc ? (S)compare_aux_a(';', acc, r) : r;
} else {
J *f = k10_flush_acc(acc);
if (K_IS_ERR(f)) R f;
acc = (S)retain_object(s);
}
}
J *res = k10_flush_acc(acc);
release_object((V **)lines); R res;
}
J *k10_flush_buf(V **buf) {
if (!buf) R 0;
V **t = (V **)append_byte_to_charvec(buf, 0);
*(I *)((S)t - 4) -= 1;
J *ast = eval_line_or_dispatch((S)t, 0, 0);
release_object((V **)t); R ast;
}
static J *k10_make_fn_formals(J a2, J a3) {
if (a3) R make_pair_J(a2, a3);
if (!a2) R retain_object((V *)runtime_builtin_sym_table);
R make_singleton_J(a2);
}
J *k10_build_fn(J src, J a2, J a3) {
J *b = make_triple_J(0, 0, src);
J *g = make_pair_J(retain_object((V *)runtime_builtin_sym_table),
retain_object((V *)runtime_long_vector_25mb));
J *f = k10_make_fn_formals(a2, a3);
parse_function_locals = (J)k10_cat3((V **)b, (S)g, (V **)f);
J *fn = allocate_typed_vector(K_TYPE_LIST, 3);
if (K_IS_ERR(fn)) {
release_object((V **)b); release_object((V **)g); release_object((V **)f); R fn;
}
fn[0] = (J)b; fn[1] = (J)g; fn[2] = (J)f;
*((G *)fn - 5) = K_TYPE_LITERAL_FUNC; R fn;
}
V **k10_cat3(V **a, S b, V **c) {
if (K_IS_ERR(a)) R a;
if (K_IS_ERR(b)) R (V **)b;
V **ab = (V **)concat_charvecs((J)a, (J)b);
if (K_IS_ERR(ab)) R ab;
if (K_IS_ERR(c)) R c;
R (V **)concat_charvecs((J)ab, (J)c);
}
J k10_emit_imm(J v, J a2, I a3) {
if (K_TOP_TAG(v)) R (J)k10_push_local((J *)v, a2, a3);
R v;
}
static I k10_is_lit(S s) {
if (K_TOP_TAG(s)) R 0;
I n = XN(s);
I v = *(I *)(s + ((n - 1) << 2));
R (v - 0x1a) < 6;
}
S k10_build_args(I idx, V *toks) {
S f = (S)retain_object(((J **)toks)[idx]);
I n = XN(toks);
if (idx + 1 == n) {
if (K_TOP_TAG(f)) R (S)k10_push_local((J *)f, 0, 0);
R f;
}
V *s = (V *)((J **)toks)[idx + 1];
I la = k10_is_lit(f); I lb = 0;
if (!K_TOP_TAG(s))
lb = (*(I *)((S)s + ((XN(s)-1)<<2)) - 0x1a) < 6;
if (la >= lb) {
S r = k10_build_args(idx + 1, toks);
R (S)k10_emit_call((J *)f, r, 0);
}
J *rs = retain_object(s); S t = k10_build_args(idx + 2, toks);
R k10_emit_cat(rs, f, t, 0);
}
I k10_at_term(void) {
J cur = parse_cursor; G c;
while ((c = *(G *)cur) == ' ') parse_cursor = ++cur;
if (!c) R 1;
const G *t = keyword_table_select;
for (I i = -4; i < 0; i++) if (t[i] == c) R 1;
if (k10_match_kw(0x41feba, cur)) R 1;
if (parse_in_dyadic_context != 1) R 0;
if (c == ',') R 1;
if (k10_match_kw(0x41fec0, cur)) R 1;
R k10_match_kw(0x41fec3, cur);
}
static I k10_get_cls(G c) {
if (!c) R ';';
R bracket_pair_class[c - 32];
}
I k10_match_kw(J kw, J cur) {
I len = strlen((S)kw);
if (memcmp((V *)kw, (V *)cur, len)) R 0;
G a = *(G *)(cur + len);
I cls = k10_get_cls(a);
const G *t = keyword_table_aggregate;
I k = 0;
for (I i = -2; i < 0; i++) if (t[i] == cls) k = 1;
R !k && a != '.';
}
I k10_is_term(I b) {
I cls = k10_get_cls(b);
const G *t = keyword_table_aggregate;
I k = 0;
for (I i = -2; i < 0; i++) if (t[i] == cls) k = 1;
R k || b == '.';
}
J *k10_push_local(J *v, J a2, I a3) {
if (K_IS_ERR(v)) R v;
V **t = *(V ***)(parse_function_locals + 24);
if (XN(t) == 128) { parse_cursor--; R (J *)2; }
V **g = (V **)append_value_to_list(t, v, a3);
*(V ***)(parse_function_locals + 24) = g;
R make_int_atom(XN(g) + 127);
}
static J k10_parse_expl(J gs) {
V **acc = (V **)retain_object((V *)runtime_long_vector_25mb);
S s;
do {
J end = k10_scan();
J nm = extract_first_word_for_print(end -
parse_cursor, (J *)parse_cursor);
parse_cursor = end;
V **tk = (V **)box_immediate_to_heap(box_atom(2, nm));
acc = (V **)multi_strategy_concat((J)acc, (V ***)tk, 0, 0);
parse_cursor = (J)(s = (S)parse_cursor) + 1;
} while (*s == ';');
if (*s != ']' || XN(acc) < 9) R K_ERR_PARSE;
R (J)k10_build_fn(0, gs, (J)acc);
}
J k10_parse_args(I mode) {
J st = parse_token_start, lx = parse_cursor, fr = parse_function_locals;
parse_token_start = lx;
J gs = (J)retain_object((V *)runtime_long_vector_25mb);
J res;
if (!mode) res = (J)k10_build_fn(0, gs, 0);
else if (mode == 1) {
parse_cursor = lx + 1;
V *f = retain_object((V *)runtime_xyz_sym_vector);
res = (J)k10_build_fn(0, gs, (J)f);
} else {
parse_cursor = lx + 2;
res = k10_parse_expl(gs);
}
parse_token_start = st; parse_function_locals = fr; R res;
}
J k10_cons_kw(J kw) {
J at = parse_cursor;
if (!k10_match_kw(kw, at)) R 0;
parse_cursor = at + strlen((S)kw);
R parse_cursor;
}
static V *k10_sel_name(J end) {
if (*(S)end != ':') R 0;
J st = parse_cursor;
R (V *)box_atom(2, extract_first_word_for_print(end-st, (J *)st));
}
static V *k10_def_name(V **body) {
J *args = ((J **)body)[4]; I n = XN(args);
if (!n) R (V *)sym_intern_cstr((J *)"n");
J v = index_typed_vector((J)args, n - 1);
V **l = (V **)promote_to_symbol_list(
split_charvec_with_terminator(0x2e, symbol_to_charvec(v)));
R (V *)keyed_last_value(l);
}
V **k10_parse_sel(V **ex) {
if (k10_at_term()) { parse_cursor--; R (V **)2; }
V **ns = (V **)retain_object((V *)runtime_builtin_sym_table);
for (;;) {
if (!ex) {
J r = k10_parse_args(0);
if (K_IS_ERR(r)) R (V **)r;
ns = (V **)append_value_to_list(ns, (V *)r, 0);
} else {
J end = k10_scan(); V *cn = k10_sel_name(end);
parse_cursor = cn ? end + 1 : parse_cursor;
V **bd = (V **)k10_parse_args(0);
if (K_IS_ERR(bd)) R bd;
if (!cn) cn = k10_def_name(bd);
V **as = (V **)box_immediate_to_heap((J *)cn);
ex = (V **)multi_strategy_concat((J)ex, (V ***)as, 0, 0);
ns = (V **)append_value_to_list(ns, bd, 0);
}
S at = (S)parse_cursor++;
if (*at == ',') continue;
parse_cursor = (J)at;
if (ex) R (V **)pair_cell_make(K_TYPE_KEYED_PAIR, ex, ns);
R ns;
}
}
static I k10_is_sh(S right) {
if (K_TOP_TAG(right)) R 0;
R (*(I *)(right + ((XN(right) - 1) << 2)) - 0x1a) <= 5;
}
S k10_emit_ass(J *left, S right, I a3) {
if (K_IS_ERR(right)) R right;
I n = XN(right);
if (n < 3 && n != 2) {
S f = keyed_first_value(right);
I hp = !K_TOP_TAG(f);
if (!hp || left || (hp && k10_is_sh(f))) {
J *t = left ? left : (J *)0x20;
R (S)k10_emit_call(t, f, 0);
}
}
if (n == 2 || (n >= 3 && (!K_TOP_TAG(left) || (uI)left != '0')))
R (S)k10_emit_verb(left, (J *)right, a3);
if (n >= 3 && K_TOP_TAG(left) && (uI)left == '0') {
if (n & 1) R (S)k10_emit_mod((V **)right);
parse_cursor--; R (S)2;
}
R right;
}
J k10_emit_call(J *v, S body, I a3) {
G t = K_TOP_TAG(v); J *vp = v;
if (t) {
uJ i = (uJ)v;
if (i <= 0x3f) R (J)append_int_word((J)body, i);
vp = k10_push_local((J *)i, i, a3);
}
R (J)k10_emit_cat((J *)K_PRINT_TAB_INDEX, (S)vp, body, t);
}
V **k10_emit_verb(J *left, J *verb, I a3) {
J *vp = left; I n = XN(verb);
V **t = (V **)parse_dyadic_args_into_table((J)verb,
(J)verb, a3);
J *b = list_concat_or_canonicalize(t, 0, 0);
if (K_TOP_TAG(left)) vp = k10_push_local((J *)(uJ)left, 0, 0);
I suf[2] = {5, n};
V **so = (V **)allocate_typed_vector_init(
K_TYPE_INT, 2, suf);
R k10_cat3((V **)b, (S)vp, (V **)so);
}
S k10_emit_cat(J *v, S l, S r, I a4) {
if (K_IS_ERR(l)) R l;
if (K_IS_ERR(r)) R r;
if (K_TOP_TAG(v)) {
uJ t = (uJ)v;
if (t <= 0x3f) {
J c = concat_charvecs((J)r, (J)l);
R (S)append_int_word(c, t + 0x20);
}
}
J *p = make_pair_J((J)l, (J)r);
R (S)k10_emit_verb(v, p, 0);
}
static I k10_is_num(G c) {
R (uI)(c - '0') <= 9;
}
I k10_look(void) {
J cur = parse_cursor; G b0 = *(G *)cur;
if ((uI)(b0 - '0') <= 5)
if (*(S)(cur + 1) == ':') R '+';
if (!b0) R 0;
if (b0 == '-') {
I o = *(S)(cur + 1) == '.';
G b1 = *(G *)(cur + o + 1);
if (!b1 || !k10_is_num(b1)) R k10_get_cls(b0);
if (parse_token_start == cur) R '0';
I pc = k10_get_cls(*(G *)(cur - 1));
const G *t = keyword_table_temporal;
for (I i = -4; i < 0; i++) if (t[i] == pc) R '0';
}
R k10_get_cls(b0);
}
static S k10_dict_fin(J *ns, V **ex, I op) {
if (XN(ns) <= 1) ns = (J *)keyed_first_value((S)ns);
S nseg = (S)k10_push_local(ns, 0, 0);
S eseg = k10_emit_ass(0, (S)ex, 0);
S res = k10_emit_cat((J *)K_VERB_GROUP_PRIME, nseg, eseg, 0);
R op ? (S)append_int_word((J)res, 0x21) : res;
}
S k10_parse_dict(I op) {
if (k10_at_term()) { parse_cursor--; R (S)2; }
J *ns = (J *)retain_object((V *)runtime_long_vector_25mb);
V **ex = (V **)retain_object((V *)runtime_builtin_sym_table);
for (;;) {
J end = k10_scan(); V *cn = k10_sel_name(end);
parse_cursor = cn ? end + 1 : parse_cursor;
S body = (S)concat_three_charvecs_alt();
if (K_IS_ERR(body)) R body;
if (!cn) cn = retain_object((V *)runtime_empty_atom_list_sentinel);
V **as = (V **)box_immediate_to_heap((J *)cn);
ns = (J *)multi_strategy_concat((J)ns, (V ***)as, 0, 0);
ex = (V **)append_value_to_list(ex, body, 0);
S at = (S)parse_cursor++;
if (*at == ';') continue;
parse_cursor = (J)at; R k10_dict_fin(ns, ex, op);
}
}
static I k10_add_local(I slot, V *name) {
I cap = slot == 4 ? 32 : 8;
V **f = *(V ***)(parse_function_locals + (slot << 3));
if (cap == XN(f)) R 0;
J *r = (J *)box_immediate_to_heap(retain_object(name));
V **g = (V **)multi_strategy_concat((J)f, (V ***)r, 0, 0);
*(V ***)(parse_function_locals + (slot << 3)) = g;
R hash_table_lookup_index((J)g, name, 0);
}
uJ k10_resolve(I add, I slot, V *name) {
J f = *(J *)(parse_function_locals + (slot << 3));
I rc = hash_table_lookup_index(f, name, 0);
if (!rc && add) rc = k10_add_local(slot, name);
if (!rc && !add) R 0;
I bs = slot == 4 ? 0x5f : (slot == 5 ? 0x11 : 9);
R (uJ)(bs + rc);
}
J k10_scan(void) {
J cur = parse_cursor; G c = *(G *)cur;
if (c == ' ') {
while (*(G *)++cur == ' ');
parse_cursor = cur; c = *(G *)cur;
}
while (!k10_is_term(c)) c = *(G *)++cur;
R cur;
}
static V **k10_mod_val(V **n) {
if (XN(n) < 4) R (V **)retain_object(n[2]);
R k10_emit_mod((V **)pair_chain_walk_recurse(2,
retain_object(n)));
}
V **k10_emit_mod(V **n) {
V **v = k10_mod_val(n); V **k = (V **)retain_object(n[1]);
V **b = (V **)retain_object((V *)*n); release_object((V **)n);
I h[2] = {3, XN(v) + 1};
V **vo = (V **)allocate_typed_vector_init(
K_TYPE_INT, 2, h);
S vw = (S)concat_charvecs((J)k, (J)vo);
h[0] = 4; h[1] = XN(vw) + 1;
V **bo = (V **)allocate_typed_vector_init(
K_TYPE_INT, 2, h);
V **bc = (V **)concat_charvecs((J)b, (J)bo);
R k10_cat3(bc, vw, v);
}
V **k10_parse_seq(void) {
V **acc = (V **)retain_object((V *)runtime_builtin_sym_table);
for (;;) {
V **ex = (V **)concat_three_charvecs_alt();
if (K_IS_ERR(ex)) R ex;
acc = (V **)append_value_to_list(acc, ex, 0);
if (K_IS_ERR(acc)) R acc;
S at = (S)parse_cursor++;
if (*at != ';') { parse_cursor = (J)at; break; }
}
R acc;
}
J *k10_to_hex(I n, J src) {
J *out = allocate_typed_vector(K_TYPE_PAIR_CHAIN, n + n);
I len = XN(out); S s = (S)out;
for (I i = 0; i < len; i++) {
G b = *(G *)(src + (i >> 1));
G nib = (i & 1) ? (b & K_NIBBLE_MAX) : (b >> 4);
s[i] = nib + (nib > 9 ? 'W' : '0');
}
R out;
}
J k10_wrap_str(S q, V **p) {
G op = q ? q[0] : '"';
if (!*(G *)((S)p - 5)) {
J *e = join_charvecs_with_separator((J)q, p);
p = (V **)e; *(I *)((S)p - 4) -= 1;
}
G cl = q ? q[1] : '"';
R make_charvec_concat_byte(op,
append_byte_to_charvec(p, cl));
}
J *k10_fin_str(G q, V **p) {
J *e = join_charvecs_with_separator((J)q, p);
*(I *)((S)e - 4) -= 1; R e;
}
static S k10_fmt_sub3(J *n, G sub) {
J *f = retain_object((V *)*n); release_object((V **)n);
V **l = (V **)k10_fmt_val(f, 0, 0);
S s = (S)char_or_token_to_K((V *)(uJ)(sub + 23));
R (S)concat_charvecs((J)l, (J)s);
}
static S k10_fmt_sub0(J *n) {
S b = (S)retain_object((V *)n[2]); release_object((V **)n);
if (b[0] != '{') R (S)make_charvec_concat_byte(':', b);
R b;
}
static S k10_fmt_rest(J *n, G sub) {
if (!K_IS_ERR(n)) {
V **d = (V **)clone_or_recycle_header(n);
*((S)d - 5) = 0; n = (J *)d;
}
J *c = apply_unary_each((K_unary_fn)
render_node_passthrough, n);
if (sub != 1) R (S)list_concat_or_canonicalize(
(V **)c, 0, 0);
V **r = (V **)retain_object((V *)*c);
S s = (S)k10_wrap_str((S)&verb_class_classifier[K_PRINT_TAB_INDEX],
(V **)pair_chain_walk_recurse(1, c));
R (S)concat_charvecs((J)r, (J)s);
}
S k10_fmt_node(J *n) {
G sub = *(G *)((S)n - 6);
if (sub >= 3) R k10_fmt_sub3(n, sub);
if (!sub) R k10_fmt_sub0(n);
R k10_fmt_rest(n, sub);
}
static J k10_fmt_fe(J *v) {
if (*(S)(*v - 5) == 2) R eval_block_chain(v);
J *r = retain_object((V *)v[1]), *l = retain_object((V *)*v); release_object((V **)v);
G lt = *(G *)((S)l - 5);
if (lt == K_TYPE_PAIR_CELL && *(S)((S)r - 5) == K_TYPE_PAIR_CELL)
R eval_special_dispatch(l, r);
V **ls; J *rn;
if (lt > 0x3f || XN(l) != 1) {
ls = (V **)k10_fmt_val(l, 0, 0); rn = r;
} else {
ls = (V **)k10_fmt_val(keyed_first_value((S)l), 0, 0);
rn = (J *)keyed_first_value((S)r);
}
R compare_aux_a('!', ls, k10_fmt_val(rn, 0, 0));
}
static J k10_fmt_inr(J *v, G in) {
I n = XN(v); V **w; S p;
if (in >= 2 && !n) {
w = (V **)k10_fmt_val(keyed_first_value((S)v), 0, 0);
p = "0#,";
} else if (n == 1) {
w = (V **)k10_fmt_val(keyed_first_value((S)v), 0, 0);
p = ",";
} else if (!in) R k10_wrap_str((S)&list_format_template,
(V **)apply_unary_each((K_unary_fn)
render_node_passthrough, v));
else R eval_jump_dispatch(box_immediate_to_heap(v));
R (J)concat_charvecs((J)cstr_to_charvec_trim((J)p),
(J)w);
}
static J k10_fmt_nan(J tag, J *v) {
F f = (tag != K_TYPE_F64_VEC) ? *(F *)K_PAYLOAD_PTR(v) : (F)(J)v;
if (__builtin_isunordered(f, f))
R (J)cstr_to_charvec_trim((J)"0n");
R 0;
}
J k10_fmt_val_atom(J *v) {
G t = K_TOP_TAG(v); I hp = (uJ)v >= K_HEAP_LOW_ADDR;
if (hp && !t) {
G in = *(G *)((S)v - 5);
if (in == K_TYPE_PAIR_CELL) R eval_special_dispatch(
retain_object((V *)runtime_combined_pair_chain), v);
if (in == K_TYPE_KEYED_PAIR) R k10_fmt_fe(v);
if (in != K_TYPE_LITERAL_FUNC) R k10_fmt_inr(v, in);
}
if ((t & K_BYTE_HIGH_BIT_MASK) == K_TYPE_F64_VEC) {
J r = k10_fmt_nan(t, v); if (r) R r;
}
if ((t - 8) > 6) { if (!t) R eval_lookup_or_apply(v); }
else if (!TEST_BITQ(K_TAGCLASS_SCALAR_IMMED, hp + t)
&& *(J *)K_PAYLOAD_PTR(v) == INT64_MIN)
R (J)cstr_to_charvec_trim((J)"ON");
R eval_jump_dispatch(box_immediate_to_heap(v));
}
J k10_pad_l(I w, J *v) {
if (K_TOP_TAG(v)) R (J)digits_or_truncate(w, (J)v);
I p = w - XN(v); J *c = vector_first_atom(v);
V **pd = (V **)group_or_take_dispatch(p, c, 0);
R multi_strategy_concat((J)pd, (V ***)v, 0, 0);
}
J k10_pad_r(I w, J *v) {
if (K_TOP_TAG(v)) R (J)digits_or_truncate(w, (J)v);
I p = w - XN(v); J *c = vector_first_atom(v);
V ***pd = (V ***)group_or_take_dispatch(p, c, 0);
R multi_strategy_concat((J)v, pd, 0, 0);
}
static J *k10_fit_rv(I b, J *r, G lt) {
J *m = (J *)retain_object((V *)runtime_long_vector_16mb);
if (XT(r) == K_TYPE_PAIR_CELL) R k10_fit_cols(b, r);
R (J *)eval_arglist_apply(b, lt != K_TYPE_PAIR_CELL ? 0 : m, r);
}
static J *k10_fit_lv(I b, J *l, J *r) {
J *m = (J *)retain_object((V *)runtime_long_vector_16mb);
if (XT(l) == K_TYPE_PAIR_CELL) R k10_fit_cols(b, l);
R (J *)eval_arglist_apply(b, XT(r) != K_TYPE_PAIR_CELL ? 0 : m, l);
}
static J *k10_fit_p(I cols, J *v) {
J *r = (J *)retain_object((V *)v[1]), *l = (J *)retain_object((V *)*v);
release_object((V **)v); I b = cols - 3;
J *lb = k10_fit_lv(b, l, r);
I rb = b + (!XN(lb));
J *rbk = k10_fit_rv(rb, r, XT(l));
R (J *)wrap_pair_with_separator('|', (V **)lb, (V **)rbk);
}
static J *k10_fit_ls(I cols, J *v) {
V **vs = (V **)retain_object((V *)v[1]);
J *ns = (J *)retain_object((V *)*v); release_object((V **)v);
J *a = (J *)retain_object((V *)runtime_builtin_sym_table);
I c = 0; V **lr = 0;
if (XN(vs)) {
for (I i = 0; i < XN(vs); i++) {
c = XN(a); if (c + 2 >= cols) break;
J *in = ns ? symbol_to_charvec(
index_typed_vector((J)ns, i)) : 0;
J *ce = (J *)eval_arglist_apply((!c) + cols, in,
retain_object(vs[i]));
lr = (V **)wrap_pair_with_separator(' ', (V **)a,
(V **)ce);
a = (J *)lr;
}
}
if (!XN(vs) || (c + 2) >= cols) lr = (V **)a;
release_object((V **)vs); release_object((V **)ns); R (J *)lr;
}
J *k10_fit_cols(I cols, J *v) {
G t = XT(v);
if (t == K_TYPE_KEYED_PAIR) R k10_fit_p(cols, v);
if (t != K_TYPE_PAIR_CELL) R (J *)eval_arglist_apply(cols, 0, v);
R k10_fit_ls(cols, v);
}
J k10_render(I pack, J *v) {
uI rows = (uI)pack >> 8; G t = XT(v); I used = 0;
if (t == K_TYPE_PAIR_CELL || (t == K_TYPE_KEYED_PAIR && *(G *)(*v - 5) == K_TYPE_PAIR_CELL)
|| (t == K_TYPE_KEYED_PAIR && *(G *)(v[1] - 5) == K_TYPE_PAIR_CELL)) used = 2;
I avail = (I)(rows - used); uI cols = (uI)pack & K_BYTE_MAX;
if (avail > pair_chain_length(v))
R (J)k10_fit_cols(cols, v);
J *b = k10_fit_cols(cols,
reshape_take_recursive(avail - 2, v));
R (J)append_value_to_list((V **)b, k10_trim((J)".."), 0);
}
J *k10_trim(J s) {
size_t l = strlen((S)s) + 1;
J *o = k10_alloc_init(1, (I)l, (V *)s);
uI n = XN(o); XN(o) = n - 1;
if (n != 1) {
uJ i = n - 1;
while (i) {
i--; if (*((S)o + i) != ' ') break;
XN(o) = (I)i; *((S)o + i) = 0; i = (uJ)XN(o);
}
}
R o;
}
J k10_trunc(I pack, J *v, J a3, I a4) {
uI c = (uI)pack >> 8;
if (c && !K_TOP_TAG(v) && XT(v) != K_TYPE_LITERAL_FUNC) {
J *r = (J *)k10_fmt_val(v, 0, 0);
R (J)elide_at_cols(c * (uI)pack, r);
}
R k10_fmt_val(v, 0, 0);
}
J *elide_at_cols(I c, J *v) {
if (XN(v) <= c) R v;
R (J *)concat_charvecs(
reshape_take_recursive(c - 2, v), k10_trim((J)".."));
}
uJ k10_is_csv(V *p) {
static S ok[] = {"k","q","csv","json","lz4","zstd",
"l2","sqr","sqrt","tsv","txt","y",0};
if (!p) R 0; I n = XN(p); S s = (S)p;
if (n <= 0) R 0; I d = -1;
for (I i = n - 1; i >= 0; i--) {
if (s[i] == '.') { d = i; break; }
if (s[i] == '/') break;
}
if (d < 0) R 0; S e = s + d + 1; I el = n - d - 1;
if (el <= 0 || el > 8) R 0;
for (I i = 0; ok[i]; i++) {
I l = (I)strlen(ok[i]);
if (l == el && !memcmp(e, ok[i], l)) R 1;
}
R 0;
}
J k10_ext_look(J n, J a2, I a3) {
J t = extension_keyword_table;
if (!t) t = eval_misc_helper(0x420654);
R hash_table_lookup_index(extension_keyword_table = t, n, a3);
}
J k10_ldr_look(J n, J a2, I a3) {
J t = loader_keyword_table;
if (!t) t = eval_misc_helper(0x42065a);
R hash_table_lookup_index(loader_keyword_table = t, n, a3);
}
J k10_wr_err(V **v) {
if ((((uJ)v >> K_TAG_SHIFT) - 2) <= 5)
v = (V **)k10_sym_to_vec(retain_object(v));
println_object(v); R 4;
}
J k10_write(V *vb, V **v, I a3) {
I i = (I)k10_ldr_look((J)vb, (J)v, a3);
if (!i) { write_cstr_stderr("rank?\n"); R 5; }
if (K_TOP_TAG(v) || XT(v) != 1) R k10_wr_err(v);
if (i == 1) R decode_one_value_and_release(v);
if (i == 2) R diagnostic_type_mismatch(v);
I m = i - 3;
if (m <= 3) R (J)ipc_send_to_client(2*m+1, vb, v, 8);
R k10_wr_err(v);
}
J *k10_sym_to_vec(V **s) {
uJ n = *(uJ *)((uJ)s & K_PTR_MASK);
release_object((V **)s); I b = 1;
if (n) {
I m = (I)_bit_scan_reverse(n);
b = (((m ^ 0xffffffc0) + 0x48) >> 3) + 1;
}
J *o = k10_alloc(1, b); *o = n;
uI len = XN(o) - 1;
XN(o) = len; *((S)o + len) = 0;
R o;
}
static J k10_dyadic_keyword_lookup(J n) {
J t = dyadic_keyword_table;
if (!t) t = eval_misc_helper(0x42069b);
R dyadic_keyword_table = t;
}
J k10_dispatch_dyadic(J *v, uJ val) {
I idx = (I)hash_table_lookup_index(
k10_dyadic_keyword_lookup(0), (J)v, 0);
if (idx < 1) R apply_dot_or_dispatch(v, val, 0);
I b = idx - 1;
if (b > 1) R 3;
if (b == 1) R cast_to_temporal_inner(val, 1);
R cast_to_long_inner(val, 0);
}
static V ***k10_named_dyadic_err(uJ *n) {
if ((((uJ)n >> K_TAG_SHIFT) - 2) <= 5)
n = (uJ *)k10_sym_to_vec((V **)n);
println_object((V **)n); R (V ***)4;
}
V ***k10_dispatch_named_dyadic(uJ *n, V **a, V ***r) {
I idx = (I)hash_table_lookup_index(
k10_dyadic_keyword_lookup(0), (J)n, 0);
if (idx < 1) R k10_named_dyadic_err(n);
I s = idx - 1;
if (s >= 3) {
J fp = verb_dispatch_primary[(uJ)s];
R ((V *** (*)(V **, V ***))fp)(a, r);
}
if (((uJ)r >> K_TAG_SHIFT)) {
V ***w = k10_dispatch_named_dyadic(n, a,
(V ***)k10_box_imm((V **)r));
R K_IS_ERR(w) ? w : (V ***)keyed_first_value((S)w);
}
uI t = (uI)((uJ)a >> K_TAG_SHIFT);
if ((t - 8) > 6) R (V ***)8;
uJ m = ((uJ)a < K_HEAP_LOW_ADDR) + t;
J v = TEST_BITQ(0x100000000ULL, m) ? (J)a :
*(J *)((uJ)a & K_PTR_MASK);
k10_release(a);
if (v == INT64_MIN) v = 0;
if (v < 0) R (V ***)9;
G rt = *(G *)((S)r - 5);
if ((rt & K_BYTE_HIGH_BIT_MASK) != K_TYPE_F64_VEC && (I)(rt - 8) <= K_LOG2_BITS_INDEX_MASK) {
if (v == 0) R r;
J fp = verb_dispatch_primary[(uJ)s];
if (TEST_BITQ(0x3ff00001ffaULL, rt))
r = (V ***)cast_to_tag(14, r);
R (V ***)((J (*)(J, V ***, J))fp)(v, r, fp);
}
R (V ***)8;
}
J *k10_box_imm(V **v) {
uJ t = (uJ)v >> K_TAG_SHIFT;
J *b = k10_alloc(t, 1);
uJ p = (uJ)v & K_PTR_MASK;
if (TEST_BITQ(0x448000000000000ULL, t)) {
if (p >= K_MMAP_HIGH_BUDGET_LO) *(__int128 *)b = *(__int128 *)p;
else *(__int128 *)b = (__int128)(J)p;
} else {
J pay;
if (TEST_BITQ(0x100000000ULL, t) || p < K_MMAP_HIGH_BUDGET_LO)
pay = (J)v & 0x00ffffffffffffffULL;
else pay = *(J *)p;
*b = pay;
}
k10_release(v); R b;
}
J k10_csv_fmt(V *v) {
J f = csv_format_lambda;
if (!f) f = (J)eval_source_or_dispatch(
"{(*/x)#/:&'x#'|*\\-1_1,|x}", 0, 0);
csv_format_lambda = f;
R (J)apply_functor_atomic((V *)f, v, 0, 0);
}
J k10_prime_ext(void) {
csv_loader_lookup(runtime_empty_atom_list_sentinel, 0, 0);
csv_extension_lookup(runtime_empty_atom_list_sentinel, 0, 0);
k10_dyadic_keyword_lookup(0);
R k10_csv_fmt(k10_alloc(13, 0));
}
static J *k10_split_byte(I s, J len, I (*src)[4]) {
if (!len) R (J *)k10_retain((V *)runtime_builtin_sym_table);
I (*cur)[4] = src;
if ((uI)*(G *)((len + (J)src) - 1) != (uI)s) R (J *)9;
J *o = k10_alloc(0, symbol_subtree_intern(s, len, cur));
for (J i = 0; i < XN(o); i++) {
I n = (I)((S)memchr(cur, s, -1) - (S)cur);
o[i] = (J)k10_alloc_init(1, n, cur);
cur = (I (*)[4])((S)cur + n + 1);
}
R o;
}
J *k10_split_ln(V **v) {
J *o = k10_split_byte('\n', (uJ)XN(v), (I (*)[4])v);
k10_release(v); R o;
}
J k10_join_ln(V **l) {
R (J)k10_join_sep('\n', l);
}
J *k10_join_sep(G s, V **l) {
uJ n = XN(l), t = 0;
for (uJ i = 0; i < n; i++) t += (uJ)XN(l[i]);
t += n;
if ((t >> 32)) R (J *)11;
J *o = k10_alloc(1, t); S c = (S)o;
for (uJ i = 0; i < n; i++) {
V *p = l[i]; uI ln = XN(p);
memcpy(c, p, ln); c += ln + 1; c[-1] = s;
}
k10_release(l); R o;
}
J *k10_split_term(I s, V **v) {
uJ n = 0;
if (XN(v)) {
v = (V **)append_byte_to_charvec(v, s);
n = (uJ)XN(v);
}
J *o = k10_split_byte(s, n, (I (*)[4])v);
k10_release(v); R o;
}
static J *k10_split_dot(I (*d)[4]) {
if (((uJ)d >> K_TAG_SHIFT) - 2 < 6)
d = (I (*)[4])symbol_to_charvec((V **)d);
else if (((uJ)d >> K_TAG_SHIFT) != 0 || *(S)((S)d - 5) != 1)
R (J *)8;
R promote_to_symbol_list(k10_split_term('.', (V **)d));
}
J *split_or_dispatch(V **a1, I (*d)[4], J a3, I a4) {
if (!a1 && ((I)((uJ)d >> K_TAG_SHIFT)) == (a4 - a4) &&
*(S)((S)d - 5) == 1) {
J *o = k10_split_byte('\n', (uJ)XN(d), d);
k10_release(d); R o;
}
uI t = (uI)((uJ)a1 >> K_TAG_SHIFT);
I b = t - 2; J p = 0x4190ac;
if (t == 1) p = 0x40600c;
J fp = (b >= 6) ? p : 0x405fc2;
if (fp == 0x4190ac) R apply_along_axis(a1, d, p, b);
if (fp == 0x405fc2) R k10_split_dot(d);
if (((I)((uJ)d >> K_TAG_SHIFT)) == (a4 - a4) &&
*(S)((S)d - 5) == 1)
R k10_split_term((uI)(uintptr_t)a1, (V **)d);
R (J *)8;
}
static J *k10_enc_payload(J h, J *r, J *v, I f) {
if (!h) serialize_value_compact(r, (V **)v);
else serialize_object_payload((S)(h - (J)r), r, (V **)v, f);
k10_release(v); R r;
}
J *k10_encode(J h, V **v, J aux, I f) {
V **e = canonicalize_for_send(v, v, aux, f);
J s = estimate_encoded_size(h, (J **)e, aux);
if ((s >> 32)) R (J *)10;
J *r = k10_alloc(1, s + 0xf); XN(r) -= 0xf;
R k10_enc_payload(h, r, (J *)e, f);
}
static __thread struct TlsHeap tls_heap;
volatile I g_multithread_active = 0;
volatile J g_global_freelist[K_CLASS_MAX + 1];
static V k10_drain(void);
J runtime_heap_size_bytes;
J runtime_heap_base;
J runtime_root_symbol_tree;
J runtime_root_value_tree;
J runtime_empty_atom_list_sentinel;
J runtime_long_vector_25mb;
J runtime_long_vector_16mb;
J runtime_builtin_sym_table;
J runtime_combined_pair_chain;
J runtime_aggregate_keyword_vector;
J runtime_generic_keyword_vector;
J runtime_xyz_sym_vector;
J runtime_root_namespace_anchor;
V **runtime_namespace_skeleton;
V **runtime_namespace_skeleton_end;
static I k10_is_comp(G t) { R t == 0 || t >= K_TYPE_PAIR_IMMEDIATE_LO; }
static J k10_owner(V *b) { (void)b; R (J)&tls_heap; }
static V k10_rem_free(struct TlsHeap *o, V *b) {
for (;;) {
J h = o->remote_free_head;
*(J *)b = h;
if (__sync_val_compare_and_swap(
&o->remote_free_head, h, (J)b) == h) break;
}
}
static V k10_drain_ch(J ch) {
while (ch) {
V *b = (V *)ch;
J nx = *(J *)b;
uJ c = (uJ)*(G *)((S)b - 0x10);
if (c < K_CLASS_MAX) {
*(J *)b = tls_heap.freelist[c];
tls_heap.freelist[c] = (J)b;
}
ch = nx;
}
}
static V k10_drain(void) {
J ch;
do {
ch = tls_heap.remote_free_head;
if (!ch) R;
} while (__sync_val_compare_and_swap(
&tls_heap.remote_free_head, ch, 0) != ch);
tls_heap.remote_drain_count++;
k10_drain_ch(ch);
}
static V k10_split_cas(uJ c, J th, J te) {
for (;;) {
J gh = g_global_freelist[c];
*(J *)te = gh;
if (__sync_val_compare_and_swap(
&g_global_freelist[c], gh, th) == gh) break;
}
}
static V k10_split(uJ c) {
J h = tls_heap.freelist[c];
if (!h) R;
I n = 0;
for (J p = h; p && n < 0x800; p = *(J *)p) n++;
if (n < 0x800) R;
J *cut = (J *)&tls_heap.freelist[c];
for (I i = 0; i < (n >> 1); i++) cut = (J *)*cut;
J th = *cut;
if (!th) R;
J te = th;
while (*(J *)te) te = *(J *)te;
k10_split_cas(c, th, te);
*cut = 0;
}
static V k10_slab_free(V *b, uJ c) {
if (g_multithread_active) {
struct TlsHeap *o = (struct TlsHeap *)k10_owner(b);
if (o != &tls_heap) { k10_rem_free(o, b); R; }
}
tls_heap.bytes_alloc -= (1LL << c);
*(J *)b = tls_heap.freelist[c];
tls_heap.freelist[c] = (J)b;
if (g_multithread_active) k10_split(c);
}
static J *k10_alloc_glb(uJ c) {
J gh = g_global_freelist[c];
while (gh) {
J nx = *(J *)gh;
if (__sync_val_compare_and_swap(
&g_global_freelist[c], gh, nx) == gh) {
tls_heap.bytes_alloc += (1LL << c);
R (J *)gh;
}
gh = g_global_freelist[c];
}
R 0;
}
static J *k10_alloc_mt(uJ c) {
if (tls_heap.remote_free_head) k10_drain();
J *h = (J *)tls_heap.freelist[c];
if (h) {
tls_heap.bytes_alloc += (1LL << c);
tls_heap.freelist[c] = *h;
R h;
}
R k10_alloc_glb(c);
}
static V k10_chop(J *b, uJ c, uI n) {
J d = -(1LL << c), s = (8LL << c);
J *t = (J *)tls_heap.freelist[c];
I r = (I)(n - 1);
do {
tls_heap.bytes_alloc += d;
*b = (J)t;
tls_heap.freelist[c] = (J)b;
t = b;
b = (J *)((S)b + s);
} while (--r > 0);
}
static J *k10_alloc_mmap(uJ c) {
size_t n = (size_t)1 << (c + 3);
V *r = mmap(0, n + 0x10, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (r == MAP_FAILED) exit(1);
*(J *)r = (J)c;
tls_heap.bytes_alloc += (1LL << c);
R (J *)((S)r + 0x10);
}
static J *k10_alloc_split(uJ c) {
J *p = k10_alloc_slot(c + 1);
p[-2] = c;
J s = (8LL << c);
tls_heap.bytes_alloc += -(1LL << c);
*p = tls_heap.freelist[c];
tls_heap.freelist[c] = (J)p;
*(J *)((S)p + s - 0x10) = (J)c;
R (J *)((S)p + s);
}
static J *k10_alloc_large(uJ c) {
if (c >= 0x29) exit(1);
I empty = 1;
for (uI k = c + 1; k < 0x29; k++)
if (tls_heap.freelist[k]) { empty = 0; break; }
if (empty) R k10_alloc_mmap(c);
R k10_alloc_split(c);
}
static J *k10_alloc_small(uJ c) {
J *b = (J *)((S)k10_alloc_slot(3) - 0x20);
uI n = (8u >> c);
if (n != 1) k10_chop(b, c, n);
J *h = (J *)tls_heap.freelist[c];
tls_heap.bytes_alloc += (1LL << c);
tls_heap.freelist[c] = *h;
R h;
}
J *k10_alloc_slot(I cls) {
uJ c = (uJ)cls;
J *h = (J *)tls_heap.freelist[c];
if (h) {
tls_heap.bytes_alloc += (1LL << c);
tls_heap.freelist[c] = *h;
R h;
}
if (g_multithread_active && (h = k10_alloc_mt(c))) R h;
if (c <= 2) R k10_alloc_small(c);
R k10_alloc_large(c);
}
static V k10_rel_kids(V **o, G t) {
I n = XN(o);
if (t >= K_TYPE_PAIR_IMMEDIATE_LO && n > 2) n = 2;
for (I i = 0; i < n; i++) {
V **c = (V **)((J *)o)[i];
if (c != o) k10_release(c);
}
}
J k10_rls_comp(V *o, G t) {
if (k10_is_comp(t)) k10_rel_kids(o, t);
uJ c = (uJ)XC(o);
if (c < K_CLASS_MAX) k10_slab_free(o, c);
R c;
}
J k10_rls_heap(V *o) {
uJ off = (uJ)((uJ)o - (uJ)runtime_heap_base);
if (off >= (uJ)runtime_heap_size_bytes)
R 0;
I rc = g_multithread_active ?
__sync_fetch_and_sub(&XR(o), 1) : XR(o)--;
if (rc != 0) R (uJ)(rc - 1);
R k10_rls_comp(o, XT(o));
}
uJ k10_release(V *o) {
if (!o) R 0;
uJ t = (uJ)o >> K_TAG_SHIFT;
if (t == 0) R k10_rls_heap(o);
if (TEST_BITQ(K_TAGCLASS_HEAP_BOXED, t)) {
uJ c = (uJ)k_type_log2_bits_table[t] -
K_LOG2_BITS_TO_CLASS_BIAS;
slab_free((V *)((uJ)o & K_PTR_MASK), c);
R c;
}
R t;
}
static V *k10_rtn_heap(uJ v) {
if (v < K_MIN_VALID_HEAP_ADDR) R (V *)v;
uJ off = v - (uJ)runtime_heap_base;
if (off >= K_HEADER_BYTES &&
off < (uJ)runtime_heap_size_bytes) {
if (g_multithread_active)
__sync_fetch_and_add(&XR(v), 1);
else XR(v) += 1;
}
R (V *)v;
}
V *k10_retain(V *v) {
uJ x = (uJ)v, t = x >> K_TAG_SHIFT;
if (t == 0) R k10_rtn_heap(x);
if (TEST_BITQ(K_TAGCLASS_SCALAR_IMMED, t))
R v;
uJ pa = x & K_PTR_MASK;
if (pa < K_SYM_INDEX_CUTOFF) R v;
I c = TEST_BITQ(K_TAGCLASS_ATOMIC_BOX, t) ? 0 : 1;
V *s = kalloc_slot(c);
if (c) *(__int128 *)s = *(__int128 *)pa;
else *(J *)s = *(J *)pa;
R (V *)((x & K_TAG_MASK) | (uJ)s);
}
J *k10_alloc(I t, I n) {
uJ b = K_VEC_BYTES((uJ)n, t);
I c = K_BSR_TO_CLASS(b);
J *p = kalloc_slot(c);
p[-1] = ((uJ)n << 32) | ((uJ)t << 24);
R p;
}
J k10_box_a(I t, J v) {
J *s = kalloc_slot(0);
*s = v;
R (J)s | ((uJ)t << K_TAG_SHIFT);
}
J k10_box_p(I t, __int128 v) {
J *s = kalloc_slot(1);
*(__int128 *)s = v;
R (J)s | ((uJ)t << K_TAG_SHIFT);
}
J *k10_alloc_init(I t, I n, const V *s) {
J *p = k10_alloc(t, n);
G l = k_type_log2_bits_table[XT(p)];
uJ b = (((uJ)XN(p) << l) + 7) >> 3;
memcpy(p, s, b);
R p;
}
J *k10_clone(V *o) {
uJ off = (uJ)o - (uJ)runtime_heap_base;
if (off < (uJ)runtime_heap_size_bytes &&
XR(o) == 0) {
XA(o) = 0; *(I16 *)((S)o - 8) = 0;
R (J *)k10_retain(o);
}
J *p = k10_alloc(XT(o), XN(o));
R p;
}
uJ k10_len(V *o) {
for (;;) {
G t = XT(o);
if (t < 0xfa) R (uJ)XN(o);
if (t != K_TYPE_PAIR_CELL)
R pair_immediate_last_int(o);
o = *(V **)((S)o + 8);
}
}
J *k10_widen(I n, V **s) {
G t = XT(s);
J *p = k10_alloc(t, n);
if ((I)(t - 1) < 0x3f) {
uJ b = K_VEC_BYTES((uJ)XN(s), t);
memcpy(p, s, b);
} else {
I m = XN(s);
for (I i = 0; i < m; i++)
p[i] = (J)k10_retain(s[i]);
}
XA(p) = 0; k10_release(s); R p;
}
V **k10_ensure(I a, V **o) {
I n = a + XN(o);
if (!has_growth_capacity(n, o))
R (V **)k10_widen(n, o);
XN(o) = n; XA(o) = 0; R o;
}
V **k10_app_b(V **v, char b) {
if (!v || K_IS_ERR(v)) {
J *f = k10_alloc(K_TYPE_PAIR_CHAIN, 1);
((S)f)[0] = b; R (V **)f;
}
V **o = k10_ensure(1, v);
((S)o)[XN(o) - 1] = b; R o;
}
V **k10_app_i(V **v, I w) {
if (K_IS_ERR(v)) R v;
V **o = k10_ensure(1, v);
((I *)o)[XN(o) - 1] = w; R o;
}
V **k10_app_v(V **v, J *x, I f) {
if (!v) R ensure_singleton_or_box(x, (J)x, f);
V **o = k10_ensure(1, v);
o[XN(o) - 1] = (V *)x; R o;
}
V *k10_cat_s(V **a, S b) {
if (!a || (uJ)a < K_HEAP_LOW_ADDR) R b;
if (!b || (uJ)b < K_HEAP_LOW_ADDR) R a;
I an = XN(a), bn = XN(b);
V **d = a;
if (bn) d = k10_ensure(bn, d);
V *o = copy_into_offset(an, d, b);
k10_release(b); R o;
}
V *k10_copy(I o, V *d, S s) {
if ((uI)XT(d) - 1 > 0x3e) {
uJ n = (uJ)XN(s);
if (n) {
J *t = (J *)((S)d + ((uJ)o << 3));
for (uJ i = 0; i < n; i++)
t[i] = (J)k10_retain(((V **)s)[i]);
}
R d;
}
G l = k_type_log2_bits_table[XT(s)];
uJ ob = (uJ)o << l, bytes = (uJ)XN(s) << l;
S dp = (ob >> 3) + (S)d; uJ bo = ob & 7;
if (!bo) memcpy(dp, s, (bytes + 7) >> 3);
else bit_copy_misaligned(dp, s, bo, bytes);
R d;
}
J *k10_chr_p(char a, char b) {
J *p = k10_alloc(K_TYPE_CHAR, 2);
((S)p)[0] = a; ((S)p)[1] = b; R p;
}
J k10_cat_b(char b, S r) {
J *p = k10_alloc(K_TYPE_CHAR, 1);
*(S)p = b; R (J)k10_cat_s((V **)p, r);
}
J *k10_int_a(I v) {
J *p = k10_alloc(K_TYPE_INT, 1);
*(I *)p = v; R p;
}
J *k10_zero(I t, I n) {
J *p = k10_alloc(t, n);
G l = k_type_log2_bits_table[XT(p)];
uJ b = (((uJ)XN(p) << l) + 7) >> 3;
memset(p, 0, b < 32 ? 32 : b);
R p;
}
J *k10_sng_j(J v) {
J *p = k10_alloc(K_TYPE_LIST, 1);
*p = v; R p;
}
J *k10_pair_j(J a, J b) {
J *p = k10_alloc(K_TYPE_LIST, 2);
p[0] = a; p[1] = b; R p;
}
J *k10_tri_j(J a, J b, J c) {
J *p = k10_alloc(K_TYPE_LIST, 3);
p[0] = a; p[1] = b; p[2] = c; R p;
}
J k10_quad(J a, J b, J c, J *d) {
J *p = k10_tri_j(a, b, c);
R (J)k10_app_v((V **)p, d, 0);
}
uJ k10_pchn_l(V **o) {
G t = XT(o);
if (t == K_TYPE_KEYED_PAIR) { o = *(V ***)o; t = XT(o); }
for (;;) {
if (t < 0xfa) R (uJ)XN(o);
if (t != K_TYPE_PAIR_CELL) R pair_immediate_last_int(o);
o = *(V ***)((S)o + 8); t = XT(o);
}
}
J k10_intern(J c) {
V *v = cstr_to_charvec_trim((S)c);
J *s = split_charvec_with_terminator('.', (V **)v);
R promote_to_symbol_list((V **)s);
}
J mmap_at_high_address(uJ mem_class) {
uJ bytes = 1ULL << mem_class;
V *p = mmap(NULL, bytes, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
return (p == MAP_FAILED) ? 0 : (J)p;
}
J *make_singleton_alias(J arg) {
J *out = allocate_typed_vector(K_TYPE_LIST, 1);
if (out) out[0] = arg;
return out;
}
J prime_default_extension_tables(J a, J b, I c) {
(void)a; (void)b; (void)c;
if (!extension_keyword_table)
extension_keyword_table = (J)allocate_typed_vector(K_TYPE_LIST, 0);
if (!loader_keyword_table)
loader_keyword_table = (J)allocate_typed_vector(K_TYPE_LIST, 0);
if (!dyadic_keyword_table)
dyadic_keyword_table = (J)allocate_typed_vector(K_TYPE_LIST, 0);
return 0;
}
static V ns_skeleton_init(void)
{
size_t bytes = ((size_t)K_NAMESPACE_SLOTS + 1) * sizeof(V *);
V *region = mmap(NULL, bytes, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (region == MAP_FAILED) return;
V **base = (V **)region + 1;
V **end = base + K_NAMESPACE_SLOTS;
for (V **p = base; p != end; p++) *(p - 1) = (V *)p;
runtime_namespace_skeleton = base;
runtime_namespace_skeleton_end = end;
}
J init_runtime_memory_(J mem_class, J ram_bytes)
{
runtime_heap_size_bytes = ram_bytes;
runtime_heap_base = mmap_at_high_address((uJ)ram_bytes);
ns_skeleton_init();
V *base = (V *)(runtime_heap_base + 0x20);
uJ cls;
if (ram_bytes == 1) {
cls = 0xfffffffd;
} else {
I msb = 63 - __builtin_clzll((uJ)(ram_bytes - 1));
cls = (uJ)(msb - 2);
}
*(J *)((char *)base - 0x10) = (J)cls;
tls_heap.freelist[cls] = (J)base;
J *r = kalloc_slot(0);
*r = 0;
runtime_empty_atom_list_sentinel = ((J)r) | (((uJ)2) << K_TAG_SHIFT);
J *r5 = kalloc_slot(3);
r5[-1] = 0x2000000;
runtime_long_vector_25mb = (J)r5;
J *r6 = kalloc_slot(3);
r6[-1] = 0x1000000;
runtime_long_vector_16mb = (J)r6;
runtime_builtin_sym_table = (J)make_singleton_J((J)r6);
runtime_combined_pair_chain = pair_cell_make(K_TYPE_KEYED_PAIR, r5, (J *)runtime_builtin_sym_table);
*(I *)((char *)runtime_builtin_sym_table - 4) = 0;
J z = intern_dotted_path((J)".z");
J *pair = (J *)make_pair_J((J)refcount_up((V *)runtime_combined_pair_chain),
(J)refcount_up((V *)runtime_combined_pair_chain));
runtime_root_symbol_tree = pair_cell_make(K_TYPE_KEYED_PAIR, (J *)z, pair);
runtime_aggregate_keyword_vector = intern_dotted_path(
(J)"count.first.last.min.max.sum.dot.avg.var.dev");
runtime_generic_keyword_vector = intern_dotted_path(
(J)".parse.rank.value.nyi.class.length.type.domain.stack.limit.EE.AA");
J xyz = intern_dotted_path((J)"x.y.z");
runtime_xyz_sym_vector = xyz;
runtime_root_value_tree = index_typed_vector(xyz, 2);
static const char BOOTSTRAP_K[] =
"import:{.(:;x;5:x)};"
"sqrt:`sqrt;sqr:`sqr;sin:`sin;cos:`cos;exp:`exp;log:`log;"
"div:`div';mod:`mod';bar:`bar';in:`in';bin:`bin';within:</</;"
"deltas:-':;differ:~~':;frq:`frq;fra:{x%+/x:`frq x};"
"meta:{$[`A~@x;@'*x;(@'*)'. x]};"
"grp:{(x_y)@=y x};"
"ungrp:{,/(+x!!y),''. y};";
J script = eval_source_or_dispatch((char *)BOOTSTRAP_K, 0, 0);
runtime_root_namespace_anchor = *(J *)dictionary_insert_or_get((J *)runtime_root_symbol_tree,
(V *)runtime_root_value_tree,
(I)script);
runtime_root_value_tree = (J)refcount_up((V *)runtime_empty_atom_list_sentinel);
return runtime_root_value_tree;
}
J initialize_runtime(long mem_class, long ram_bytes)
{
return init_runtime_memory_(mem_class, ram_bytes);
}
V init_runtime_memory(void) { }
V **promote_to_target_type(I target_type, V **vec) {
if (!vec) return 0;
if (XT(vec) == (G)target_type) return vec;
I n = XN(vec);
J *out = allocate_typed_vector(target_type, n);
if (!out) return vec;
for (I i = 0; i < n; i++)
out[i] = (J)((J *)vec)[i];
return (V **)out;
}
V *cast_to_char_or_bool(I target_tag, V **vec) {
return promote_to_target_type(target_tag, vec);
}
static uJ detect_temporal_code(uJ nn)
{
uI code2 = (uI)((0xaaaaaaabULL * nn) >> 0x21);
return (uJ)((code2 < 5 ? code2 : 5) + 0x12);
}
static I detect_numeric_suffix_match(char *buf, uJ n, char first)
{
uJ i = 0;
char c = first;
while (i < n) {
for (J s = -3; s != 0; s++)
if (numeric_suffix_letters[s] == c) return 1;
i++;
if (i != n) c = buf[i];
}
return 0;
}
static uJ detect_plain_atom_type(char *buf, uJ n, I dots)
{
char first = (n != 0) ? buf[0] : 0;
if (first == '0' && n >= 6 && dots == 0) return detect_temporal_code(n);
uI code = K_VERB_GROUP_PRIME;
if (dots != 0) return (uJ)code;
if (n != 0 && detect_numeric_suffix_match(buf, n, first)) return (uJ)code;
code = 0xe;
if (n == 0) return (uJ)code;
if (first != '-' && (n > 9 || buf[n-1] != 'N')) {
code = 0xd;
if (n == 9) code = (uI)((first > '1') + 0xd);
}
return (uJ)code;
}
uJ detect_atom_type(char *buf)
{
uJ n = (uJ)*(I *)(buf - 4);
I colons = 0, dots = 0;
if (n != 0) {
for (uJ i = 0; i < n; i++) colons += (buf[i] == ':');
for (uJ i = 0; i < n; i++) dots += (buf[i] == '.');
}
if (n == 0 || (dots != 2 && colons == 0))
return detect_plain_atom_type(buf, n, dots);
return n != 0 ? detect_temporal_code((dots != 2 && colons != 0) ? n - 2 : n)
: K_VERB_GROUP_PRIME;
}
uJ detect_atom_type_from_text(char *buf) { return detect_atom_type(buf); }
uJ parse_build_date(const char *date_literal)
{
const char *table = (const char *)month_letter_signature_table;
unsigned key = ((unsigned)(G)date_literal[1] +
(unsigned)(G)date_literal[2]) & K_BYTECODE_LOCAL_LIMIT;
const char *m = (char *)memchr(table, (key + 0x5e), (size_t)-1);
I month_idx = (I)(m - table);
I year_lo = ((G)date_literal[9]) & K_NIBBLE_MAX;
I year_hi = ((G)date_literal[10]) & K_NIBBLE_MAX;
I year_off = year_lo * 10 + year_hi;
I day_hi = ((G)date_literal[4]) & K_NIBBLE_MAX;
I day_lo = ((G)date_literal[5]) & K_NIBBLE_MAX;
I day = day_hi * 10 + day_lo - 1;
I days = (I)rata_die_to_julian((month_idx - 0xc) +
(year_off * 0xc));
return (uJ)(day + days);
}
uJ parse_build_date_alias(const char *date_literal)
{
return parse_build_date(date_literal);
}
J *temporal_unit_lookup(I letter)
{
intptr_t s = -2;
while (s != 0) {
if ((G)temporal_suffix_letters_a[s] == (uI)letter) {
J boxed[2];
boxed[0] = 7;
*(I *)((char *)&boxed[1] + 4) = (I)0;
return allocate_typed_vector_init(K_TYPE_INT, 2, boxed);
}
s++;
}
return (J *)2;
}
J ensure_singleton(J *value, J aux, I flags)
{
if (is_keyed_pairlist(value, aux, flags) != 0) {
J *a = (J *)refcount_up((V *)value[1]);
V *b = refcount_up((V *)*value);
I rc = (I)release_object((V **)value);
return pair_cell_make(K_TYPE_PAIR_CELL, b, apply_unary_or_singleton(a, (J)b, rc));
}
if (((J)value >> K_TAG_SHIFT) == 0) {
return (J)make_singleton_J((J)value);
}
return (J)box_immediate_to_heap((V **)value);
}
J ensure_singleton_alias(J *value, J aux, I flags)
{
return ensure_singleton(value, aux, flags);
}
I is_canonical_promote_target(J *vec, I flags) {
(void)flags;
if (!vec) return 0;
G t = XT(vec);
return t == K_TYPE_LIST || t == K_TYPE_PAIR_CELL;
}
V **canonicalize_to_typed_vector(J *vec, I a2, J a3, I a4) {
(void)a2; (void)a3; (void)a4;
return (V **)vec;
}
J emit_pad_for_print_rhs(I pad_total, J *value) {
(void)value;
if (pad_total <= 0) return 0;
char buf[256]; if (pad_total > 256) pad_total = 256;
memset(buf, ' ', (size_t)pad_total);
write(1, buf, (size_t)pad_total);
return pad_total;
}
static V column_rectify_copy_payload16(J *col, J *vec, J src_col)
{
uJ cnt = (uJ)XN(col);
for (uJ k = 0; k < cnt; k++) {
J row = vec[k];
*(__int128 *)((char *)col + (k << 4)) =
*(__int128 *)((char *)row + ((uJ)src_col << 4));
}
}
static V column_rectify_copy_scalar(J *col, J *vec,
J src_col, uJ cls)
{
uJ cnt = (uJ)XN(col);
switch (cls) {
case 0:
for (uJ k = 0; k < cnt; k++) ((char *)col)[k] = *((char *)vec[k] + src_col);
break;
case 1:
for (uJ k = 0; k < cnt; k++) ((I16 *)col)[k] = *(I16 *)((char *)vec[k] + ((uJ)src_col << 1));
break;
case 2:
for (uJ k = 0; k < cnt; k++) ((I *)col)[k] = *(I *)((char *)vec[k] + ((uJ)src_col << 2));
break;
case 3:
for (uJ k = 0; k < cnt; k++) col[k] = *(J *)((char *)vec[k] + ((uJ)src_col << 3));
break;
}
}
static J *column_rectify_one(J *vec, uI tag, J src_col)
{
I n_rows = XN(vec);
if (tag == 0) {
J *col = kalloc(0, n_rows);
for (J i = 0; i < (J)XN(col); i++)
col[i] = (J)index_typed_vector(vec[i], (uJ)src_col);
return (J *)canonicalize_homogeneous_list(col, 0, 0);
}
if (XN((V *)vec[0]) == 0) return make_zero_filled((I)tag, n_rows);
J *col = kalloc((I)tag, n_rows);
uJ cls = (uJ)k_type_column_class_table[(uJ)XT(col)] - 3;
if (cls > 3) column_rectify_copy_payload16(col, vec, src_col);
else column_rectify_copy_scalar(col, vec, src_col, cls);
return col;
}
J is_keyed_pairlist(J *arg1, J arg2_unused, I flags_unused)
{
(void)arg2_unused; (void)flags_unused;
if (((J)arg1 >> K_TAG_SHIFT) != 0) return 0;
if ((uintptr_t)arg1 < K_SYM_INDEX_CUTOFF) return 0;
if (*(G *)((char *)arg1 - 5) != K_TYPE_KEYED_PAIR) return 0;
J key_raw = *(J *)arg1;
if (((J)key_raw >> K_TAG_SHIFT) != 0) return 0;
if ((uintptr_t)key_raw < K_SYM_INDEX_CUTOFF) return 0;
if (*(G *)(key_raw - 5) != 2) return 0;
V **values = (V **)arg1[1];
if ((uintptr_t)values < K_SYM_INDEX_CUTOFF) return 0;
if ((uI)*(G *)((char *)values - 5) - 1 < 0x3f) return 1;
J i = 0, n = (J)*(I *)((char *)values - 4);
if (n < 0 || n > K_MAX_VECTOR_LEN) return 0;
while (i < n) {
V *e = (V *)((J *)values)[i];
if (((J)e >> K_TAG_SHIFT) == 0) {
if ((J)e < K_HEAP_LOW_ADDR) return 0;
if ((uI)*(G *)((char *)e - 5) - 1 > 0x3e) return 0;
}
i++;
}
return 1;
}
J *column_rectify(J *vec, I flags)
{
uI elem_type = 0;
if (is_canonical_promote_target(vec, flags) != 0) {
elem_type = (uI)XT((V *)*vec);
if (elem_type == K_TYPE_BOOL) {
return (J *)reshape_to_target_tag(K_TYPE_BOOL,
(J *)column_rectify(
(J *)reshape_to_target_tag(0xb, vec), flags));
}
}
if (XN(vec) <= 0) return kalloc(K_TYPE_LIST, 0);
J *out = kalloc(K_TYPE_LIST, XN((V *)*vec));
if (elem_type == K_TYPE_PAIR_CELL) elem_type = 0;
J i = 0;
do {
out[i] = (J)column_rectify_one(vec, elem_type, i);
i++;
} while (i < (J)XN(out));
release_object((V **)vec);
return out;
}
J *refresh_keyed_pairs(J *vec, J arg2, I arg3)
{
J *first = (J *)*vec;
J i = 0;
while (1) {
J *cell = (J *)vec[i];
J ok = is_keyed_pairlist(cell, arg2, arg3);
if (ok != 0) {
I eq = deep_equal(*first, *cell, arg3, (I)ok);
if (eq != 0) {
i++;
if (i >= (J)*(I *)((char *)vec - 4)) break;
continue;
}
}
return vec;
}
V *keys = refcount_up((V *)*first);
J j = 0;
J *vals = kalloc(K_TYPE_LIST, *(I *)((char *)vec - 4));
do {
uJ cell = index_typed_vector((J)vec, (uJ)j);
V *vv = refcount_up((V *)*(J *)(cell + 8));
release_object((V **)cell);
vals[j] = (J)vv;
j++;
} while (j < (J)*(I *)((char *)vals - 4));
return (J *)pair_cell_make(K_TYPE_PAIR_CELL, keys,
column_rectify(vals, (I)release_object((V **)vec)));
}
J *refresh_keyed_pairlist(J *vec, J a2, I a3) { return refresh_keyed_pairs(vec, a2, a3); }
static I canonicalize_every_keyed(V **arg1, J aux, J aux2)
{
J n = XN(arg1);
if (n <= 0) return 0;
for (J i = 0; i < n; i++)
if (!is_keyed_pairlist((J *)arg1[i], aux, (I)aux2)) return 0;
return 1;
}
static V **canonicalize_expand_pair_immediates(J *rect)
{
J n = XN(rect);
for (J k = 0; k < n; k++) {
if (*(G *)(rect[k] - 5) != K_TYPE_PAIR_IMMEDIATE) continue;
V **out = (V **)kalloc(0, (I)n);
for (J bb = 0; bb < n; bb++) {
uJ e = index_typed_vector((J)rect, (uJ)bb);
if (*(G *)(e - 5) == K_TYPE_PAIR_IMMEDIATE) e = (uJ)expand_pair_immediate(e);
((J *)out)[bb] = (J)e;
}
release_object((V **)rect);
return out;
}
return (V **)rect;
}
static V **canonicalize_plain_list(V **arg1, J aux,
J aux2, I flags)
{
if (canonicalize_every_keyed(arg1, aux, aux2)) {
V **a6 = refcount_up(arg1);
J n = XN(a6);
J *a7 = kalloc(K_TYPE_LIST, (I)n);
for (J bb = 0; bb < n; bb++) {
uJ e8 = index_typed_vector((J)a6, (uJ)bb);
V *e9 = refcount_up((V *)*(J *)e8);
release_object((V **)e8);
a7[bb] = (J)e9;
}
I rd = (I)release_object(a6);
J *a11 = (J *)list_concat_or_canonicalize(a7, 0, rd);
V **a12 = canonicalize_to_typed_vector(a11, 0, 0, 0);
J *a14 = (J *)ranged_pair_or_each(K_PRINT_TAB_INDEX, (J *)a6,
(V **)refcount_up(a12));
return (V **)pair_cell_make(0xfe, a12, column_rectify(a14, 0));
}
J *rect = (J *)rectify_or_pad_rows((J *)arg1, aux, aux2, flags);
if (K_IS_ERR_RETURN(rect)) return (V **)rect;
return (V **)column_rectify((J *)canonicalize_expand_pair_immediates(rect), 0);
}
static V **canonicalize_keyed_pair_case(V **arg1, J aux, J aux2)
{
V *inner = (V *)*(J *)arg1;
if (*(G *)((char *)inner - 5) != 2) return (V **)3;
V **k = (V **)refcount_up(inner);
J *v = (J *)refcount_up((V *)arg1[1]);
I rc = (I)release_object(arg1);
if (*(G *)((char *)v - 5) != K_TYPE_PAIR_CELL)
return (V **)pair_cell_make(0xfd, k, (J *)rectify_or_pad_rows(v, aux, aux2, rc));
J *vk = (J *)refcount_up((V *)v[1]);
V **vv = (V **)refcount_up((V *)*v);
J *cell = (J *)pair_cell_make(K_TYPE_PAIR_CELL, k,
column_rectify(vk, (I)release_object((V **)v)));
return (V **)pair_cell_make(0xfe, vv, cell);
}
static V **canonicalize_pair_chain_header(V **arg1)
{
if (K_IS_ERR_RETURN(arg1)) return arg1;
V **dup = clone_or_recycle_header((J *)arg1);
*(G *)((char *)dup - 5) = 0xfe;
return dup;
}
static J k10_can_pln(J x, J a, J b, I f) {
return (J)canonicalize_plain_list((V**)x, a, b, f);
}
static J k10_can_key(J x, J a, J b) {
return (J)canonicalize_keyed_pair_case((V**)x, a, b);
}
static J k10_can_chn(J x) {
return (J)canonicalize_pair_chain_header((V**)x);
}
J k10_canon_list(J x, J a, J b, I f) {
P(!K_IS_HEAP(x), 3);
G t = XT(x);
if (t == 0) return k10_can_pln(x, a, b, f);
if (t == K_TYPE_KEYED_PAIR) return k10_can_key(x, a, b);
if (t == K_TYPE_PAIR_CELL) return k10_can_chn(x);
return 3;
}
J k10_canon_display(J x, J a, J b, I f) {
return k10_canon_list(x, a, b, f);
}
static I k10_rec_chk(J x, J* v, J n) {
J i = 1;
while (i < n) {
if (K_TOP_TAG(v[i]) != 0) return 0;
if (kind_or_length_walk((V*)x) !=
kind_or_length_walk((V*)v[i])) return 0;
i++;
}
return 1;
}
static I k10_is_rect(J* x, J n) {
if (K_TOP_TAG(*x) != 0) return 0;
return k10_rec_chk(*x, x, n);
}
static I k10_max_w(J* x, J n) {
I w = 0;
for (J i = 0; i < n; i++) {
I c = K_IS_HEAP(x[i]) ? XN(x[i]) : 0;
if (c > w) w = c;
}
return w;
}
J* k10_rectify(J* x, J a, J b, I f) {
if (XT(x) != 0) return (J*)3;
J n = XN(x);
if (k10_is_rect(x, n)) return x;
I w = k10_max_w(x, n);
J* r = (J*)kalloc(0, (I)n);
for (J i = 0; i < n; i++)
r[i] = emit_pad_for_print_rhs(w, (J*)k10_at(x, i));
release_object((V **)x);
return r;
}
J* k10_rectify_rows(J* x, J a, J b, I f) {
return k10_rectify(x, a, b, f);
}
J* k10_list_head(J x) {
J n = XN(x);
J* r = (J*)kalloc(0xb, (I)n);
for (J i = 0; i < n; i++) {
S row = (S)((J*)x)[i];
((G*)r)[i] = (XN(row) == 0) ? ' ' : *row;
}
release_object((V **)x);
return r;
}
J* k10_list_len(J x) {
J n = XN(x);
J* r = (J*)kalloc(0xd, (I)n);
for (J i = 0; i < n; i++) ((I*)r)[i] = XN(((J*)x)[i]);
release_object((V **)x);
return r;
}
J* k10_list_counts(J x) { return k10_list_len(x); }
J k10_parse_int(I n, S s) {
P(n == 0 || s[n-1] == 'N', INT64_MIN);
I i = (s[0] == '-');
J r = i ? 0 : s[0] - '0';
for (I k = 1; k < (i ? n - 1 : n); k++)
r = r * 10 + (s[k + i] - '0');
return i ? -r : r;
}
J k10_parse_integer(I n, S s) { return k10_parse_int(n, s); }
V k10_parse_f64_into(I n, S s) {
P(n == 0, );
G last = s[n-1], first = s[0];
P(last == 'n' || last == 'w', );
I off = (first == '-');
strtod_at_offset(n - off, s + off);
}
V k10_parse_f64_buf(I n, S s) { k10_parse_f64_into(n, s); }
static J k10_can_prm(J x, J a, I f) {
J bb = (J)narrow_long_if_fits_int((V*)x);
I tag = XT(bb);
I shrink = cached_max_element((V*)bb, a, f);
if (tag == 1) return (J)canonicalize_universal((V*)bb, a, f);
if ((tag - 8) <= 5 && shrink <= 0xffff) {
I tgt = (shrink > K_BYTE_MAX) ? 0xc : ((shrink > 1) ? 0xb : 8);
J redo = (J)cast_to_tag(tgt, (V*)bb);
XN(redo) = shrink;
bb = redo;
}
return (J)canonicalize_universal((V*)bb, a, f);
}
static J k10_can_at(J x) {
if (K_TOP_TAG(x) == K_TYPE_LONG) {
J v = *(J*)UNMASK(x);
if ((v >> 32) == 0) {
release_object((V **)x);
return v | K_TAG(0xd);
}
}
return x;
}
static J k10_can_p(J x, J a, J b, I f) {
J r = (J)retain_object(((V**)x)[1]), l = (J)retain_object(*(J*)x);
G t = XT(x); release_object((V **)x);
J cr = k10_canon_send(r, a, b, f);
return (J)k10_pair_make(t, l, (J*)cr);
}
J k10_canon_send(J x, J a, J b, I f) {
if (K_TOP_TAG(x) != 0) return k10_can_at(x);
G t = XT(x);
if ((G)(t + 3) < 2) return k10_can_p(x, a, b, f);
if (t == K_TYPE_PAIR_IMMEDIATE) x = (J)expand_pair_immediate((J*)x);
t = XT(x);
if (t != K_TYPE_LITERAL_FUNC && (G)(t - 1) <= 0x3e)
return k10_can_prm(x, a, f);
return (J)canonicalize_generic_send((V**)x, a, b, f);
}
uJ k10_obj_len(V* x) {
for (;;) {
G t = XT(x);
if (t < 0xfa) return (uJ)XN(x);
if (t != K_TYPE_PAIR_CELL) return (uJ)pair_immediate_last_int(x);
x = *(V**)((S)x + 8);
}
}
uJ k10_obj_len_walk(V* x) { return k10_obj_len(x); }
uJ k10_obj_len_alt(V* x) { return k10_obj_len(x); }
J k10_promote_atom(J* src, J v) {
if ((uJ)(v - 1) < 0xf) return v;
J out = (J)apply_functor_atomic(NULL, NULL, 0, 0);
release_object((V **)src);
return out;
}
J k10_atom_to_list(J* src, J v) { return k10_promote_atom(src, v); }
static uJ k10_at_fa_v(V* p, uJ i) {
G t = XT(p);
if (t == 8) return (((J*)p)[i >> 6] >> (i & 63)) & 1;
if ((K_TAGCLASS_INT32_LANE >> t) & 1) return ((uI*)p)[i];
if (t == K_TYPE_SHORT) return (uJ)((I16*)p)[i];
return (uJ)((G*)p)[i];
}
static J k10_at_fa(J* v, uJ i) {
J* base = (J*)*v;
if (*(S)(base - 6) == 5) return k10_at((J*)v[1], i);
V* p = (V*)v[1];
uJ idx = i;
if (*(S)(v - 6) >= 2) idx = pair_immediate_inner_index(p, i);
else idx = k10_at_fa_v(p, i);
return k10_at(base, idx);
}
static J k10_at_p(J* v, uJ i, G t) {
if (t == K_TYPE_SHORT) return (J)((I16*)v)[i];
if (t == 0xb || t == 1) return (J)((G*)v)[i];
if (t == 8) return (J)((v[i >> 6] >> (i & 63)) & 1);
return (J)((I*)v)[i];
}
static J k10_at_chn(J* v, uJ i) {
V* h = retain_object((V*)*v);
J r = (J)ranged_pair_or_each(K_PRINT_TAB_INDEX,
retain_object((V*)v[1]), K_TAG(0xd) | i);
return (J)k10_pair_make(0xfe, (J)h, (J*)r);
}
J k10_at(J* v, uJ i) {
if (v == NULL || (uJ)v < K_HEAP_LOW_ADDR) return (J)v;
G t = XT(v);
if (t == K_TYPE_PAIR_IMMEDIATE) return k10_at_fa(v, i);
if (t == 0) return (J)retain_object((V*)v[i]);
if (t == K_TYPE_PAIR_CELL) return k10_at_chn(v, i);
if ((K_TAGCLASS_PAIR_PAYLOAD >> t) & 1)
return (J)make_pair_box(t, ((__int128*)v)[i]);
if ((K_TAGCLASS_ATOMIC_BOX >> t) & 1)
return (J)make_atom_box(t, v[i]);
return (J)((uJ)t << K_TAG_SHIFT) | k10_at_p(v, i, t);
}
J k10_at_typed(J* v, uJ i) { return k10_at(v, i); }
J k10_first(J* v) {
J v0 = k10_at_typed(v, 0);
return (J)unwrap_pair_chain((V**)v0, 0, 0, 0);
}
J k10_first_atom(J* v) { return k10_first(v); }
J k10_at_safe(J* v, I i) {
if (k10_obj_len(v) <= (uJ)i) return k10_first(v);
return k10_at(v, (uJ)i);
}
J k10_at_safe_atom(J* v, I i) { return k10_at_safe(v, i); }
static J k10_key_wlk(V** x) {
V** b = x;
while (XT(b) == K_TYPE_KEYED_PAIR) {
V** n = (V**)retain_object(b[1]);
release_object((V **)b);
b = n;
}
return (J)b;
}
J k10_keyed_first(V** x) {
J r = k10_key_wlk(x);
J v = k10_at_safe((J*)r, 0);
release_object((V **)r);
return v;
}
J k10_keyed_val_first(V** x) { return k10_keyed_first(x); }
J k10_keyed_last(V** x) {
J r = k10_key_wlk(x);
J v = k10_at_safe((J*)r, (I)k10_obj_len((V*)r) - 1);
release_object((V **)r);
return v;
}
J k10_keyed_val_last(V** x) {
return k10_keyed_last(x);
}
static F k10_parse_w(I n, S s) {
J r = 0;
if (n > 0) r = s[0] - '0';
for (I i = 1; i < n; i++)
r = r * 10 + s[i] - '0';
return (F)r;
}
static F k10_parse_f(I n, S s) {
if (n < 2) return 0.0;
if (n >= 3) {
F v = (F)((s[1]& K_NIBBLE_MAX) + (s[0]& K_NIBBLE_MAX)*10);
return v / 100.0;
}
return (F)(s[0]& K_NIBBLE_MAX) / 10.0;
}
static I k10_find_dot(I m, S r) {
for (I i = 0; i < m && i < 16; i++)
if (r[i] == '.') return i;
return m;
}
static F k10_parse_f64_val(I n, S s) {
I dot = k10_find_dot(n, s);
return k10_parse_w(dot, s) + k10_parse_f(n - dot, s + dot + 1);
}
F k10_parse_f64_frac(I n, S s, F *f) {
if (n == 0) return 0.0;
G last = s[n-1], first = s[0];
if (last == 'n') return 0.0/0.0;
if (last == 'w')
return (first == '-') ? -1.0/0.0 : 1.0/0.0;
I sign = (first == '-');
F v = k10_parse_f64_val(n - sign, s + sign);
return sign ? -v : v;
}
V k10_parse_f64_f(I n, S s, F *z) {
k10_parse_f64_frac(n, s, z);
}
J k10_parse_dt_s(I k, I a, V *b) {
G *p = (G*)b;
return (J)((p[0] & K_NIBBLE_MAX) * 10 + (p[1] & K_NIBBLE_MAX));
}
J k10_parse_dt_f(I k, I a, V *b) {
return k10_parse_dt_s(k, a, b);
}
uJ k10_parse_dt(I k, I n, V *b) {
if (k <= 7) return (uJ)k10_parse_dt_s(k, n, b);
G *p = (G*)b;
I y = p[4] - '0', c = (y > 9) ? 1 : 0;
I m = (I)(p[2] & K_NIBBLE_MAX);
I d = (I)(p[4 + c] & K_NIBBLE_MAX);
I l = (I)((p[3] & K_NIBBLE_MAX) + (m * 10));
return (uJ)((d + l) - 1);
}
J* k10_expand_pair(V** x, J a, J b, I f) {
if (K_TOP_TAG(x)) return (J*)x;
G t = XT(x);
if (t != K_TYPE_KEYED_PAIR && t != K_TYPE_PAIR_CELL) return (J*)x;
V* ks = retain_object(*(J*)x);
V** vs = (V**)retain_object(((J*)x)[1]);
release_object((V **)x);
J* pj = (J*)project_keyed_columns((J)vs,
(J)ks, f);
return (J*)k10_pair_make(0xfe, (J)ks, pj);
}
J* k10_keyed_to_list(V** x, J a, J b, I f) {
return k10_expand_pair(x, a, b, f);
}
J* k10_pair_make(I t, J a, J* b) {
if (K_IS_ERR_RETURN(b)) return b;
J* r = (J*)kalloc(t, 2);
r[0] = a; r[1] = (J)b;
return r;
}
static V** k10_unw_p(V** x, J a, J b, I f) {
V* r = retain_object(x[1]), *l = retain_object(*(J*)x);
G h = XT(x); release_object((V **)x);
V** i = k10_unwrap_chain((V**)r, a, b, f);
if (K_IS_ERR_RETURN(i)) return i;
J* c = (J*)kalloc(h, 2);
c[0] = (J)l; c[1] = (J)i;
return (V**)c;
}
V** k10_unwrap_chain(V** x, J a, J b, I f) {
if (K_TOP_TAG(x))
return (V**)normalize_atom_or_list(x);
G h = XT(x);
if ((S)(h + 3) < (S)2)
return k10_unw_p(x, a, b, f);
if (h == K_TYPE_PAIR_IMMEDIATE)
x = (V**)expand_pair_immediate((J*)x);
h = XT(x);
if (h == K_TYPE_PAIR_IMMEDIATE || h != K_TYPE_LITERAL_FUNC)
return (V**)k10_unw_gen(x, a, b, f);
return (V**)normalize_atom_or_list(x);
}
uJ k10_rd_to_jd(I m) {
uJ r = (uJ)(m + 10);
uI a = (uI)((0xaaaaaaabULL * r) >> 35);
uJ v = (r - (uJ)((a << 2) * 3)) * 0x3d32f6ULL;
uJ res = (((v + 0xffff) >> 17) + ((a * 0x5b5) >> 2));
return res - 0x132;
}
uJ k10_jd_to_rd(J j) {
uJ r = (uJ)((I)((j << 2) + 0x4cb));
uJ c = (r * 0x166db073ULL) >> 39;
uJ r_c = (r - (c * 0x5b5)) >> 2;
uJ v = (uI)(((I16)(r_c * 5)) + 2);
return (((v * 0x358b) >> 21) + (uI)((c * 3) << 2)) - 10;
}
static J k10_cst_im(V* t, J v) {
uJ tt = (uintptr_t)t, st = (uJ)v >> K_TAG_SHIFT;
if (!st) return 6;
if (st == tt) return v;
if (K_TAG_INT_FAMILY(tt) && K_TAG_INT_FAMILY(st))
return (tt << K_TAG_SHIFT) | (v & K_PAYLOAD_MASK);
V** b = k10_prom_t((I)tt,
(__int128*)singleton_coerce_atom(v));
return (J)b;
}
V** k10_prom_t(I t, __int128* v) {
return promote_vector_to_tag(t, v);
}
J k10_reshp_a(I t, V** v) {
return (J)generic_cast_worker((J)k10_cst_im,
(J)k10_prom_t, (uJ)t, v);
}
J k10_reshp(I t, V** v) {
return k10_reshp_a(t, v);
}
V* k10_p_last(V* x) {
V* p = (V*)((J*)x)[1];
if (*(S)(x - 6) < 2) return (V*)(J)XN(p);
return (V*)(J)((I*)p)[XN(p) - 1];
}
V* k10_p_last_i(V* x) { return k10_p_last(x); }
static J* k10_p_exp_t(J* t) {
if (*(S)(t - 6) < 2) return t;
I l = ((I*)t)[XN(t) - 1];
if (!l) return t;
V** v = (V**)t;
return (J*)bigint_grow_to_target_lo(l,
bigint_normalize_in_place(v));
}
J* k10_p_exp(J* x) {
J* h = (J*)retain_object((V*)*x);
J* t = (J*)retain_object((V*)x[1]);
release_object((V **)x);
t = k10_p_exp_t(t);
J* r = shape_with_int_dimensions(h, (__int128*)t);
release_object((V **)h);
return r;
}
V** k10_recycl(V** x) {
uJ o = (uJ)((S)x - (S)runtime_heap_base);
if (o < runtime_heap_size_bytes && XR(x) == 0) {
*(S)(x - 6) = 0;
*((J*)x - 1) = 0;
return x;
}
return (V**)promote_widen(XN(x), x);
}
V** k10_recycl_h(V** x) { return k10_recycl(x); }
I k10_h_cap(I w, V* x) {
uJ o = (uJ)((S)x - (S)runtime_heap_base);
if (o < runtime_heap_size_bytes && XR(x) == 0) {
uI av = (uI)XC(x);
uJ nb = K_VEC_BYTES(w, XT(x));
return K_BSR_TO_CLASS(nb) <= (I)av;
}
return 0;
}
I k10_h_grow(I w, V** x) {
return k10_h_cap(w, x);
}
static uJ k10_eq_s(V** r, V** l, uJ n, G t) {
if (t == 8) return (uJ)compare_bool_vectors(r, l);
if ((I)(t - 1) <= 0x3e) {
G l2 = k_type_log2_bits_compare_table[t];
uJ nb = ((n << l2) + 7) >> 3;
return (uJ)(bcmp(r, l, nb) == 0);
}
for (uJ i = 0; i < n; i++) {
V** r_i = (V**)((J*)r)[i];
V** l_i = (V**)((J*)l)[i];
if (!k10_equal(r_i, l_i, 0, 0)) return 0;
}
return 1;
}
static uJ k10_equal_tagged(uJ r, uJ l, uJ lt) {
if (r == l) return 1;
uJ rt = l >> K_TAG_SHIFT;
if (!rt) return 0;
if (lt == rt || (lt - 8 <= K_LOG2_BITS_INDEX_MASK && rt - 8 <= K_LOG2_BITS_INDEX_MASK))
return (uJ)(tagged_atom_equal(r, l) != 0);
return 0;
}
static uJ k10_equal_types(V** r, V** l, G lty, G rty) {
uJ n = (uJ)XN(r);
if (n != (uJ)XN(l)) return 0;
if (lty == rty) return k10_eq_s(r, l, n, lty);
if (lty - 8 > 6 || rty - 8 > 6) return 0;
V** p = (V**)cast_to_tag_alias(lty, retain_object(l));
uJ res = k10_equal(r, p, 0, 0);
release_object((V **)p);
return res;
}
static uJ k10_equal_step(V*** pl, V*** pr) {
V** l = *pl, **r = *pr;
V** t = r; r = l; l = t;
uJ lt = (uJ)r >> K_TAG_SHIFT;
if (lt)
return k10_equal_tagged((uJ)r, (uJ)l, lt) ? 1 : 2;
G lty = XT(r), rty = XT(l);
if (lty == K_TYPE_PAIR_IMMEDIATE) return k10_eq_fa(r, l) ? 1 : 2;
if (lty < rty || rty == K_TYPE_PAIR_IMMEDIATE) {
*pl = r; *pr = t; return 0;
}
return k10_equal_types(r, l, lty, rty) ? 1 : 2;
}
uJ k10_equal(V** a, V** b, I a3, uJ a4) {
V** l = a, **r = b;
for (;;) {
uJ res = k10_equal_step(&l, &r);
if (res) return res == 1;
}
}
J k10_dict_get_retry(J* r, V* k, I f) {
for (I i = 0; ; i++) {
if (i >= XN(r)) {
J p = (J)hash_table_lookup_index(*r, (uJ)k, f);
if (p) return p;
i = 0;
}
V** s = (V**)((J*)r)[i];
V*** rs = (V***)(i == 0 ? retain_object(k) : NULL);
V** u = multi_strategy_concat(s, rs, f, f);
((J*)r)[i] = (J)u;
}
}
J k10_dict_get(J* r, V* k, I f) {
J p = (J)hash_table_lookup_index(*r, (uJ)k, f);
if (!p) p = k10_dict_get_retry(r, k, f);
return (J)(((p - 1) << 3) + ((J*)r)[1]);
}
J k10_dict_get_a(J* r, V* k, I f) {
return k10_dict_get(r, k, f);
}
V **canonicalize_list(V **a, J b,
J c, I d) {
return (V**)k10_canon_list((J)a, b, c, d);
}
V **canonicalize_list_for_display(V **a, J b,
J c, I d) {
return (V**)k10_canon_display((J)a, b, c, d);
}
J *rectify_or_pad(J *a, J b,
J c, I d) {
return (J*)k10_rectify(a, b, c, d);
}
J *rectify_or_pad_rows(J *a, J b,
J c, I d) {
return (J*)k10_rectify_rows(a, b, c, d);
}
J *list_first_bytes(V **a) {
return (J*)k10_list_head((J)a);
}
J *list_lengths(V **a) {
return (J*)k10_list_counts((J)a);
}
J *list_element_lengths(V **a) {
return (J*)k10_list_len((J)a);
}
J parse_signed_int(I a, char *b) {
return k10_parse_int(a, b);
}
J parse_signed_integer(I a, char *b) {
return k10_parse_integer(a, b);
}
V parse_double_into(I a, char *b) {
k10_parse_f64_into(a, b);
}
V parse_double_into_buffer(I a, char *b) {
k10_parse_f64_buf(a, b);
}
V **canonicalize_for_send(V **a, J b,
J c, I d) {
return (V**)k10_canon_send((J)a, b, c, d);
}
uJ kind_or_length(V *a) {
return k10_obj_len(a);
}
uJ kind_or_length_walk(V *a) {
return k10_obj_len_walk(a);
}
uJ kind_or_length_alternate(V *a) {
return k10_obj_len_alt(a);
}
V **promote_singleton(V **a, J b) {
return (V**)k10_promote_atom((J*)a, b);
}
V **promote_atom_to_singleton(V **a,
J b) {
return (V**)k10_atom_to_list((J*)a, b);
}
uJ index_vector(J *a, uJ b) {
return (uJ)k10_at(a, b);
}
uJ index_typed_vector(J *a,
uJ b) {
return (uJ)k10_at_typed(a, b);
}
J vector_first(J *a) {
return k10_first(a);
}
J vector_first_atom(J *a) {
return k10_first_atom(a);
}
J vector_at_or_first(J *a,
I b) {
return k10_at_safe(a, b);
}
J vector_at_or_first_atom(J *a,
I b) {
return k10_at_safe_atom(a, b);
}
J keyed_first(V **a) {
return k10_keyed_first((V**)a);
}
J keyed_first_value(V **a) {
return k10_keyed_val_first((V**)a);
}
J keyed_last(V **a) {
return k10_keyed_last((V**)a);
}
J keyed_last_value(V **a) {
return k10_keyed_val_last((V**)a);
}
F parse_double_with_frac(I a, char *b,
F *c) {
return k10_parse_f64_frac(a, b, c);
}
V parse_double_with_fraction(I a,
char *b, F *c) {
k10_parse_f64_f(a, b, c);
}
J parse_temporal_short(I a, I b,
V *c) {
return k10_parse_dt_s(a, b, c);
}
J parse_temporal_short_field(I a,
I b, V *c) {
return k10_parse_dt_f(a, b, c);
}
uJ parse_temporal_dispatch(I a,
I b, V *c) {
return k10_parse_dt(a, b, c);
}
J *expand_pair(V **a, J b,
J c, I d) {
return (J*)k10_expand_pair((V**)a, b, c, d);
}
J *expand_keyed_pair_to_list(V **a,
J b, J c, I d) {
return (J*)k10_keyed_to_list((V**)a, b, c, d);
}
J *pair_cell_make(I a, J b,
J *c) {
return (J*)k10_pair_make(a, b, c);
}
V **unwrap_pair_chain(V **a, J b,
J c, I d) {
return (V**)k10_unwrap_chain((V**)a, b, c, d);
}
uJ rata_die_to_julian(I a) {
return k10_rd_to_jd(a);
}
uJ julian_to_rata_die(J a) {
return k10_jd_to_rd(a);
}
J reshape_to_target_tag(I a, V **b) {
return k10_reshp(a, b);
}
V *pair_immediate_last(V *a) {
return k10_p_last(a);
}
V *pair_immediate_last_int(V *a) {
return k10_p_last_i(a);
}
J *expand_pair_immediate(J *a) {
return (J*)k10_p_exp(a);
}
V **clone_or_recycle_real(V **a) {
return (V**)k10_recycl((V**)a);
}
V **clone_or_recycle_header(V **a) {
return (V**)k10_recycl_h((V**)a);
}
I has_capacity(I a, V *b) {
return k10_h_cap(a, b);
}
I has_growth_capacity(I a, V **b) {
return k10_h_grow(a, (V**)b);
}
uJ deep_equal(V **a, V **b,
I c, uJ d) {
return k10_equal((V**)a, (V**)b, c, d);
}
J dict_insert_or_get(J *a, V *b,
I c) {
return k10_dict_get(a, b, c);
}
J dictionary_insert_or_get(J *a,
V *b, I c) {
return k10_dict_get_a(a, b, c);
}
G k10_type_bits[0x40] = {
6, 3, 6, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7,
5, 5, 5, 5, 5, 6, 6, 6, 5, 5, 5, 5, 5, 6, 6, 6,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 6, 7, 0,
43, 0, 0, 0, 14, 0, 0, 0,
2, 0, 0, 0, 25, 0, 0, 0
};
G k10_type_bits_cmp[0x40] = {
6, 3, 6, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7,
5, 5, 5, 5, 5, 6, 6, 6, 5, 5, 5, 5, 5, 6, 6, 6,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 6, 7, 0,
43, 0, 0, 0, 14, 0, 0, 0,
2, 0, 0, 0, 25, 0, 0, 0
};
G k10_type_col_class[0x40] = {
3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 1, 2, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
G k10_cast_grad[0x40] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 6, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6, 0, 0, 0, 5, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
static const G k10_punct_storage[216] = {
' ', '+', '0', 'a', '`', 0, ' ', '+', '`', '+',
'+', '+', '+', '+', '(', ')', '+', '+', '+', '+',
'+', '+', '0', '0', '0', '0', '0', '0', '0', '0',
'0', '0', '+', ';', '+', '+', '+', '+', '+', 'a',
'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
'a', 'a', 'a', 'a', '(', '+', ')', '+', '+', '`',
'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
'a', 'a', 'a', 'a', '(', '+', ')', '+', 0, '\'',
'/', '\\', 0, ':', '+', '-', '*', '%', '&', '|',
'<', '>', '=', '~', '!', ',', '^', '#', '_', '$',
'?', '@', '.', 0, '(', '[', '{', 0, '}', ']', ')',
0, '0', '1', '2', '1', '1', 0, ';', ')', ']', '}',
0, 'w', 'h', 'e', 'r', 'e', 0, 'b', 'y', 0, 'f',
'r', 'o', 'm', 0, '0', 'a', 0, 's', 'e', 'l', 'e',
'c', 't', 0, 'u', 'p', 'd', 'a', 't', 'e', 0, 'd',
'e', 'l', 'e', 't', 'e', 0, 's', 'd', 'u', 0, '.',
'z', '.', 0, '(', ';', '+', ' ', 0, '3', '3', '3',
'2', '2', '2', '2', '2', 0, 'v', 'w', 0, 't', 'u',
0, '*', 'f', 'f', 'i'
};
const G *const k10_punct = k10_punct_storage + 5;
static G numeric_suffix_letters_storage[16] = {
'i', 'h', 'j', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
G *numeric_suffix_letters = numeric_suffix_letters_storage + 3;
G month_letter_signature_table[12] = {
'm','e','q','`','x','a','_','z','s','u','c','f'
};
static G temporal_suffix_letters_a_storage[16] = {
'm','d','h','r','s','t','u','v', 0,0,0,0,0,0,0,0
};
G *temporal_suffix_letters_a = temporal_suffix_letters_a_storage + 2;
static G temporal_suffix_letters_b_storage[16] = {
'm','d','h','r','s','t','u','v', 0,0,0,0,0,0,0,0
};
G *temporal_suffix_letters_b = temporal_suffix_letters_b_storage + 2;
G date_field_letters_a[24] = {
'*','c','n','4','5','6','7','8','b','*','*','g',
'h','i','j','*','*','*','e','f','x','.','.','.'
};
G date_field_letters_b[24] = {
'c','n','4','5','6','7','8','b','*','*','g','h',
'i','j','*','*','*','e','f','x','.','.','.','.'
};
__attribute__((aligned(16)))
G k10_ieee_sign[16] = {
0,0,0,0,0,0,0,0x80, 0,0,0,0,0,0,0,0x80
};
const char k10_csv_letters[16] =
"fisdtcFISDTC aA";
J k10_render_pair(V *p) {
V *h = retain_object(*(V **)p);
V *t = retain_object(*((V **)p + 1));
release_object((V **)p);
h = (V *)k10_render_node((J)h);
t = (V *)k10_render_node((J)t);
R (J)pair_cell_make(0xfd, h, t);
}
J k10_render_node(J val) {
if (TAG(val) || val < K_MIN_VALID_HEAP_ADDR)
R val;
V *p = (V *)val;
G t = XT(p);
if (t == K_TYPE_PAIR_CELL) R k10_render_pair(p);
if (t == K_TYPE_PAIR_IMMEDIATE) {
V *e = expand_pair_immediate(p);
R k10_render_node((J)e);
}
R val;
}
static J k10_expand_keyed_inner(V *p, J h) {
V *hk = retain_object((V *)h);
V *tk = retain_object(*((V **)p + 1));
release_object((V **)p);
R (J)pair_cell_make(0xfd, hk, tk);
}
J k10_expand_keyed(J val) {
V *p = (V *)val;
if (TAG(p) || (uJ)p < K_MIN_VALID_HEAP_ADDR)
R val;
J h = *(J *)p;
if (XT(p) == K_TYPE_KEYED_PAIR && XT(h) == 2)
return k10_expand_keyed_inner(p, h);
R val;
}
J k10_apply_unary_or_single(V *arg, J aux, I flg) {
if (!arg || (uJ)arg < K_MIN_VALID_HEAP_ADDR)
R (J)arg;
if (TAG(arg)) R (J)arg;
if (XT(arg) >= 1 && XT(arg) <= 0x3f && XN(arg)) {
V **b = (V **)ensure_singleton(arg, aux, flg);
R (J)canonicalize_list(b, aux, 0, flg);
}
R (J)k10_apply_unary_each(k10_expand_keyed, arg);
}
J *k10_apply_unary_keyed(K_unary_fn f, V *v) {
V *k = retain_object(*(V **)v);
V *val = retain_object(*((V **)v + 1));
release_object((V **)v);
V *res = (V *)k10_apply_unary_each(f, val);
R (J *)pair_cell_make(0xfe, k, res);
}
static J *k10_apply_unary_loop_fill(K_unary_fn f,
V *v, J *o,
I n) {
for (I i = 0; i < n; i++) {
J *r = f(vector_at_or_first(v, i));
o[i] = (J)r;
if (K_IS_ERR_RETURN(r)) return r;
}
return NULL;
}
J *k10_apply_unary_loop(K_unary_fn f, V *v,
J *o, I n) {
J *err = k10_apply_unary_loop_fill(f, v, o, n);
if (err) R err;
if (!n)
o[0] = (J)unwrap_pair_chain((V **)*o, 0, 0, 0);
J *r = (J *)
canonicalize_homogeneous_list(o, 0, 0);
release_object((V **)v);
R r;
}
J *k10_apply_unary_each(K_unary_fn f, V *v) {
if (XT(v) == K_TYPE_KEYED_PAIR)
R k10_apply_unary_keyed(f, v);
I n = (I)kind_or_length(v);
R k10_apply_unary_loop(f, v, kalloc(0, n), n);
}
J *k10_apply_dyadic_left_keyed(K_dyadic_left_fn f,
J l, V *v) {
V *k = retain_object(*(V **)v);
V *val = retain_object(*((V **)v + 1));
release_object((V **)v);
V *res = (V *)k10_apply_dyadic_left(f, l, val);
R (J *)pair_cell_make(0xfe, k, res);
}
static J *k10_apply_dyadic_left_loop_f(K_dyadic_left_fn f,
J l, V *v,
J *o, I n) {
for (I i = 0; i < n; i++) {
J *r = f(l, (J)index_vector(v, (uJ)i));
o[i] = (J)r;
if (K_IS_ERR_RETURN(r)) return r;
}
return NULL;
}
J *k10_apply_dyadic_left_loop(K_dyadic_left_fn f,
J l, V *v, J *o, I n) {
J *err = k10_apply_dyadic_left_loop_f(f, l, v, o, n);
if (err) R err;
if (!n)
o[0] = (J)unwrap_pair_chain((V **)*o, 0, 0, 0);
J *r = (J *)
canonicalize_homogeneous_list(o, 0, 0);
release_object((V **)v);
R r;
}
J *k10_apply_dyadic_left(K_dyadic_left_fn f,
J l, V *v) {
if (XT(v) == K_TYPE_KEYED_PAIR)
R k10_apply_dyadic_left_keyed(f, l, v);
I n = (I)vec_total_length(v);
R k10_apply_dyadic_left_loop(f, l, v,
kalloc(0, n), n);
}
J *k10_apply_dyadic_left_each(J fn, J l, V *v) {
return k10_apply_dyadic_left((K_dyadic_left_fn)fn,
l, v);
}
V **k10_cast_temporal(I tgt, V *src) {
R (V **)fold_temporal_class(tgt, src);
}
V **k10_cast_narrow(I tgt, V *src) {
G c = XT(src);
if ((c - 8) > K_LOG2_BITS_INDEX_MASK) R (V **)8;
I n = k10_cast_grad[tgt & K_TYPE_TAG_MASK] + 8;
V **r = k10_cast((V *)(uintptr_t)n, src);
if (K_IS_ERR_RETURN(r)) R r;
V **d = clone_or_recycle_real(r);
XT(d) = (G)tgt;
R d;
}
static V* k10_cast_typed_inner(I tgt, V* src,
G c, char* buf) {
if (tgt == 8)
return (V *)cast_to_bool_packed(src, buf);
if (c != 8)
return (V *)cast_to_typed_inner((V *)(uintptr_t)tgt,
src);
return (V *)cast_to_int_typed(tgt, src);
}
V **k10_cast_typed(I tgt, V *src) {
G c = XT(src), cls = *(G *)((char *)src - 6);
G b3 = (G)((c < tgt) << 2);
if (b3 >= cls) b3 = cls;
char buf[16];
V *nxt = k10_cast_typed_inner(tgt, src, c, buf);
if (!K_IS_ERR_RETURN(nxt)) *(G *)((char *)nxt - 6) = b3;
R (V **)nxt;
}
V **k10_cast(V *tgt_tag, V *src) {
I tgt = (I)(uintptr_t)tgt_tag;
G cur = XT(src);
if (cur == tgt) R (V **)src;
I tw = tgt & ~0xf, cw = cur & ~0xf;
if (tw == 0x10 && cw == 0x10)
R k10_cast_temporal(tgt, src);
if (tgt == 1 || tw == 0x10)
R k10_cast_narrow(tgt, src);
if (cur != 1 && cw != 0x10)
R k10_cast_typed(tgt, src);
R (V **)8;
}
V **k10_cast_tag_alias(I tgt, V *v) {
R k10_cast((V *)(uintptr_t)tgt, v);
}
static V k10_prom_dbl(J *o, V **v) {
uJ n = (uJ)XN(o);
for (uJ i = 0; i < n; i++) {
S s = (S)v[i];
parse_double_into_buffer(XN(s), s);
((F *)o)[i] = strtod_at_offset(XN(s), s);
}
}
static V k10_prom_flt(J *o, V **v) {
uJ n = (uJ)XN(o);
F f;
for (uJ i = 0; i < n; i++) {
S s = (S)v[i];
float f2 = (float)parse_double_with_frac(XN(s),
s, &f);
((float *)o)[i] = f2;
}
}
static V k10_prom_si(J *o, V **v) {
uJ n = (uJ)XN(o);
for (uJ i = 0; i < n; i++) {
S s = (S)v[i];
I r = 0, l = XN(s);
for (I j = 0; j < l; j++) {
r = r * 5;
r = (I)((G)s[j] + (r << 1) - '0');
}
((I *)o)[i] = r;
}
}
static V k10_prom_long(J *o, V **v) {
uJ n = (uJ)XN(o);
for (uJ i = 0; i < n; i++) {
S s = (S)v[i];
o[i] = parse_signed_int(XN(s), s);
}
}
static J k10_prom_sym_one(J *r) {
uJ rn = (uJ)XN(r);
if (!rn) return 0;
uJ s = (rn >= 8) ? 8 : rn;
s = (uJ)(-(J)(s << 3));
return (J)((*r << s) >> s);
}
static V k10_prom_sym(J *o, V **v) {
uJ n = (uJ)XN(o);
for (uJ i = 0; i < n; i++)
o[i] = k10_prom_sym_one((J *)v[i]);
}
static V k10_prom_num(I tgt, uI h,
J *o, V **v) {
if (tgt >= 0x12 && (tgt & 0xfffffff0u) == 0x10)
R;
if (h == K_VERB_GROUP_PRIME) k10_prom_dbl(o, v);
else if (h == K_TYPE_F64_VEC) k10_prom_flt(o, v);
else if ((h > 0x29 && h != K_TYPE_F64_VEC && h != K_VERB_GROUP_PRIME) ||
(h <= 0x29 && h != 2 && h != 0xe))
k10_prom_si(o, v);
else if (h == K_TYPE_LONG) k10_prom_long(o, v);
else if (h == 2) k10_prom_sym(o, v);
}
static V k10_prom_temp_fill(I f, G p, uJ n,
J *o, V **v) {
for (uJ i = 0; i < n; i++) {
V *r = v[i];
uJ v2 = parse_temporal_dispatch(f, XN(r), r);
if (p & 1) ((I *)o)[i] = (I)v2;
else o[i] = (J)v2;
}
}
static V k10_prom_temp(I tgt, J *o, V **v) {
if (tgt < 0x12 || (tgt & 0xfffffff0u) != 0x10)
R;
uJ n = (uJ)XN(v);
if (!n) R;
I f = tgt & K_NIBBLE_MAX;
G p = (G)((K_TAGCLASS_INT32_LANE >> tgt) & K_BYTE_MAX);
k10_prom_temp_fill(f, p, n, o, v);
}
static V** k10_promote_atom_list(I tgt, V** vec) {
V *fb = list_first_bytes(vec);
if (tgt == 1) return (V **)fb;
return (V **)cast_to_char_or_bool_alias(0x31, fb);
}
V **k10_promote(I tgt, V **vec) {
if (!tgt) R (V **)8;
if (tgt == 8 || tgt == 1)
return k10_promote_atom_list(tgt, vec);
J *out = kalloc(tgt, XN(vec));
k10_prom_num(tgt, (uI)XT(out), out, vec);
k10_prom_temp(tgt, out, vec);
V **c = canonicalize_for_send((V **)out, 0, 0, 0);
release_object((V **)vec);
R c;
}
V **k10_promote_target(I tgt, V **v) {
R k10_promote(tgt, v);
}
J k10_promote_sym_list(V **v) {
R (J)k10_promote(2, v);
}
J *k10_ranged_pair_keyed(V *verb, V *v, J *val) {
J *r = (J *)retain_object(*((V **)v + 1));
V *l = retain_object(*(V **)v);
release_object((V **)v);
V *res = (V *)k10_ranged_pair(verb, r, val);
R (J *)pair_cell_make(0xfe, l, res);
}
J *k10_ranged_pair_list(V *v, I n) {
V ***r = (V ***)kalloc(0, n);
for (I i = 0; i < n; i++) {
r[i] = (V **)vector_at_or_first(v, i);
}
R (J *)r;
}
static J *k10_ranged_pair_verb(V *verb, J *v,
J *val) {
if (is_homogeneous_list(v, v, 0, XT(v))) {
V *g = (V *)group_or_take_dispatch(XN(v), val, 0);
return (J *)rebalance_concat_left(v, g);
}
return NULL;
}
J *k10_ranged_pair(V *verb, J *v, J *val) {
if (TAG(v) || XT(v) == K_TYPE_LITERAL_FUNC) R (J *)3;
G t = XT(v);
if (t == K_TYPE_KEYED_PAIR)
return k10_ranged_pair_keyed(verb, (V *)v, val);
if ((uJ)verb == 0x2c) {
J *r = k10_ranged_pair_verb(verb, v, val);
if (r) return r;
}
I n = (I)kind_or_length(v);
if (!n && pair_chain_terminal_length(verb, v, 0)) {
release_object((V **)val); R v;
}
return (J *)k10_ranged_pair_list((V *)v, n);
}
J *k10_ranged_pair_alias(V **verb, J *v,
J *val) {
R k10_ranged_pair((V *)verb, v, val);
}
V ***k10_axis_tagged(V **a1, V *a2, J aux, I flg) {
V *box = (V *)box_immediate_to_heap((J)a2);
V ***r = k10_apply_along_axis(a1, box, aux, flg);
if (!K_IS_ERR_RETURN(r))
R (V ***)k10_apply_unary_each(keyed_first,
(V *)r);
R r;
}
V ***k10_axis_split(V **out, V **src, I n) {
for (I i = n - 1; i > 0; i--) {
V **p = (V **)partition_by_index(
*(I *)((S)src - 4 + (i<<2)), (V **)src);
V *right = retain_object(p[1]);
src = (V **)retain_object(*p);
release_object((V **)p);
out[i] = (V **)right;
}
*out = (V **)src;
R out;
}
static V*** k10_axis_apply_n(V** src, I n) {
if (n <= 1) {
release_object((V **)src);
V *a = (V *)list_append_value(src, NULL, 0);
return (V ***)k10_apply_unary_each(
ensure_singleton_or_box, a);
}
V ***out = (V ***)kalloc(0, n);
return k10_axis_split(out, src, n);
}
V ***k10_apply_along_axis(V **a1, V *a2, J aux, I flg) {
if (TAG(a2)) return k10_axis_tagged(a1, a2, aux, flg);
if ((uJ)a2 < K_MIN_VALID_HEAP_ADDR) R (V ***)6;
if ((XT(a2) - 1) > 0x3e) R (V ***)6;
V **src = k10_cast((V *)0xd, a2);
if (K_IS_ERR_RETURN(src)) R (V ***)src;
return k10_axis_apply_n(src, XN(src));
}
J k10_is_wide_sorted(J *v, J aux, uJ flg) {
while (XT(v) == K_TYPE_PAIR_CELL)
v = *(J **)(((J *)v)[1]);
if (XT(v) == K_TYPE_PAIR_IMMEDIATE) R 0;
if (XN(v) < 2) R 1;
V *u = canonicalize_universal_alias(v, aux, (uI)flg);
R *(int8_t *)((S)u - 6) > 3;
}
static J *k10_is_unq_sorted_list(J *v, J aux,
uJ flg) {
V *u = canonicalize_universal_alias(v, aux, (uI)flg);
return (J *)(J)(*(int8_t *)((S)u - 6) > 1);
}
J *k10_is_unique_sorted(J *v, J aux, uJ flg) {
G t = XT(v);
if (t == K_TYPE_PAIR_CELL) {
if (XN(*(J *)v) != 1) return NULL;
V *nxt = *(V **)((J *)v + 1);
return (J *)(J)(k10_is_unique_sorted(nxt, aux,
flg) != 0);
}
if (t == K_TYPE_PAIR_IMMEDIATE)
return (J *)(J)(*(int8_t *)((S)v - 6) > 1);
if (XN(v) >= 2)
return k10_is_unq_sorted_list(v, aux, flg);
return (J *)1;
}
J k10_same_kind(J *v, I a2, I a3) {
(void)a2; (void)a3;
if (!v || (uJ)v < K_MMAP_HIGH_BUDGET_LO) R 0;
V *h = (V *)v[0], *t = (V *)v[1];
if (TAG(h) || (uJ)h < K_MMAP_HIGH_BUDGET_LO) R 0;
if (TAG(t) || (uJ)t < K_MMAP_HIGH_BUDGET_LO) R 0;
R (J)(XT(h) == XT(t));
}
J k10_same_outer_kind(J *v, I a2, I a3) {
R k10_same_kind(v, a2, a3);
}
J *k10_concat_loop(V **a, J *o, I n) {
uJ off = 0;
for (I k = 0; k < n; k++) {
copy_into_slot((I)off, o, a[k]);
off += XN(a[k]);
}
release_object((V **)a); R o;
}
J *k10_concat_o(V **a, I n) {
uJ tot = 0;
for (I k = 0; k < n; k++) tot += XN(a[k]);
if (tot >> 32) R (J *)0xb;
J *o = kalloc(XT(a[0]), (I)tot);
R k10_concat_loop(a, o, n);
}
static J *k10_concat_non_typed(V **a, I n,
uI flg) {
for (I i = 0; i < n; i++) {
if (TAG(a[i]) || XT(a[i]) == K_TYPE_LITERAL_FUNC) continue;
if (!is_canonical_promote_target((J *)a, flg))
return iterate_verb_into_list(0x2c, 0, a);
return k10_concat_o(a, n);
}
return NULL;
}
J *k10_list_concat_or_canon(V **a, uJ aux,
uI flg) {
if (!a || (uJ)a < K_MIN_VALID_HEAP_ADDR)
R (J *)a;
G t = XT(a);
if (t == K_TYPE_KEYED_PAIR) {
V **r = (V **)retain_object((V *)((J *)a)[1]);
release_object((V **)a); a = r; t = XT(a);
}
if (!t) {
J *r = k10_concat_non_typed(a, XN(a), flg);
if (r) return r;
}
return (J *)canonicalize_homogeneous_list(
(J *)a, aux, flg);
}
J *k10_list_concat_alias(V **a, uJ b, uI c) {
R k10_list_concat_or_canon(a, b, c);
}
V **k10_canon_typed_final(V **r) {
if (XN(r) >= 2) *(int8_t *)((S)r - 6) = 4;
R r;
}
V **k10_canon_typed_body(J *v) {
uJ hd = (uJ)XT(v);
V *(*fp)(V **);
if (hd != K_TYPE_PAIR_CELL) {
if ((0x3ff00001ffaULL >> hd) & 1)
fp = (V *(*)(V **))canonicalize_temporal_typed;
else if ((K_TAGCLASS_INT32_LANE >> hd) & 1)
fp = (V *(*)(V **))canonicalize_int_typed;
else fp = (V *(*)(V **))canonicalize_other_typed;
} else fp = (V *(*)(V **))canonicalize_pair_chain_typed;
R k10_canon_typed_final(fp((V **)v));
}
V **k10_canonicalize_typed(J *v, I f, J a3, I flg) {
(void)a3; (void)flg;
if (TAG(v)) R (V **)6;
G t = XT(v);
if (t == K_TYPE_LITERAL_FUNC) R (V **)6;
if (t == K_TYPE_KEYED_PAIR) {
V *right = retain_object((V *)v[1]);
J *left = (J *)retain_object((V *)*v);
release_object((V **)v);
R (V **)pair_cell_make(0xfe, right, left);
}
V **r = (V **)canonicalize_to_typed_inner(v, f);
if (K_IS_ERR_RETURN(r)) R r;
if (k10_is_wide_sorted((J *)r, 0, 0)) R r;
if (XT(r) == K_TYPE_PAIR_IMMEDIATE)
R (V **)pair_immediate_canonicalize(r);
if (k10_is_unique_sorted((J *)r, 0, 0)) {
V *b = bitwise_complement_vector((J)promote_to_unique_bool(r));
J *x = shape_with_int_dimensions((J *)r,
(__int128 *)cast_graph_int_tail((J)b));
release_object((V **)r); R (V **)x;
}
R k10_canon_typed_body((J *)r);
}
V **k10_canon_typed_vec(J *v, I f, J a3, I a4) {
R k10_canonicalize_typed(v, f, a3, a4);
}
uJ max_long_vector(V *vec, J a2, J a3, uJ hdr) {
(void)a2; (void)a3; (void)hdr;
if (!vec) return 0;
J *p = (J *)vec; I n = XN(vec);
J m = p[0];
for (I i = 1; i < n; i++) if (p[i] > m) m = p[i];
return (uJ)m;
}
uJ max_int_vector(V *vec, J a2, J a3, uJ hdr) {
(void)a2; (void)a3; (void)hdr;
if (!vec) return 0;
I *p = (I *)vec; I n = XN(vec);
I m = p[0];
for (I i = 1; i < n; i++) if (p[i] > m) m = p[i];
return (uJ)(uI)m;
}
uJ max_short_vector(V *vec, J a2, J a3, uJ hdr) {
(void)a2; (void)a3; (void)hdr;
if (!vec) return 0;
I16 *p = (I16 *)vec; I n = XN(vec);
I16 m = p[0];
for (I i = 1; i < n; i++) if (p[i] > m) m = p[i];
return (uJ)(uI16)m;
}
uJ k10_cached_max(V *v, J a2, J a3) {
if (!v || (uJ)v < K_MIN_VALID_HEAP_ADDR) R 0;
uJ c = (uJ)*(I16 *)((S)v - 8);
if (c) R c;
if (!XN(v)) R 0;
G h = XT(v); uJ val = 0;
if (h == 8) val = 1;
else if (h == 1 || h == 0xb )
val = max_long_vector(v, a2, a3, h);
else if (h == K_TYPE_SHORT)
val = max_short_vector(v, a2, a3, h);
else val = max_int_vector(v, a2, a3, h);
*(I16 *)((S)v - 8) = (I16)((val <= 0xffff) ? val : 0);
R val;
}
uJ cached_max_element(V *vec, J a, J b) { return cached_max(vec, a, b); }
J partition_by_index(J shift, V **arg2)
{
V *dup = refcount_up(arg2);
V *gather = reciprocal_with_cap(shift, (__int128 *)dup, 0);
return (J)make_pair_J((J)gather,
pair_or_collapse_dyadic(2, arg2,
(V *)(intptr_t)((0xeULL << K_TAG_SHIFT) | (uJ)shift)));
}
J cast_or_box(V *target_tag, J arg2)
{
uJ arg2_tag = (uJ)arg2 >> K_TAG_SHIFT;
if (arg2_tag == 0) return 6;
J r = arg2;
if (arg2_tag == (uintptr_t)target_tag) return r;
if (((intptr_t)target_tag - 8) > 5 ||
(((intptr_t)target_tag - 8) <= 5 && (arg2_tag - 8) > 5)) {
V **boxed = cast_to_tag_alias((I)(intptr_t)target_tag,
box_immediate_to_heap(r));
if ((((uintptr_t)boxed) - 1) >= 0xf) {
return keyed_first(boxed);
}
r = (J)boxed;
}
if (((intptr_t)target_tag - 8) <= 5 && (arg2_tag - 8) <= 5) {
r = (((uintptr_t)target_tag) << K_TAG_SHIFT) | (uJ)r;
}
return r;
}
J cast_to_target_or_box(V *target, J value) { return cast_or_box(target, value); }
J *generic_cast_worker(J alloc_helper, J promote,
J target, V **vec)
{
if (((J)vec >> K_TAG_SHIFT) == 0) {
G t = *(G *)((char *)vec - 5);
I pair = (I)((G)(t + 3) < 2);
if (pair) {
V *right = refcount_up((V *)((J *)vec)[1]);
V *left = refcount_up((V *)*(J *)vec);
release_object(vec);
J *inner = generic_cast_worker(alloc_helper, promote, target,
(V **)right);
if (!K_IS_ERR_RETURN(inner)) {
J *cell = kalloc(t, 2);
cell[0] = (J)left; cell[1] = (J)inner;
return cell;
}
return inner;
}
return (J *)((K_promote_fn)promote)((V *)target, vec);
}
return (J *)((K_alloc_into_fn)alloc_helper)((V *)target, (J)vec);
}
J dict_lookup(J *root, uJ *key, I flags)
{
uJ *err_key = key;
I slot = (I)hash_table_lookup_index(*root, (uJ)key, flags);
if (slot != 0) {
return *(J *)(root[1] + (((uJ)(slot - 1)) << 3));
}
if (((uintptr_t)((J)key >> K_TAG_SHIFT) - 2) <= 5) {
err_key = symbol_to_charvec(refcount_up(key));
}
println_object((V **)err_key);
return 4;
}
J dictionary_lookup(J *root, uJ *key, I flags)
{
return dict_lookup(root, key, flags);
}
V **split_engine(V *arg1, __int128 *arg2, J a3, I flags)
{
uI lt = (uI)((J)arg1 >> K_TAG_SHIFT);
uI shift = (lt == 0) ? (uI)*(G *)((char *)arg1 - 5) : lt;
shift -= 8;
V **err = (V **)(uintptr_t)K_TYPE_BOOL;
if (shift > 5) return err;
return (V **)apply_along_axis((V **)arg1, arg2, a3, flags);
}
V *bigint_load_or_init(V *vec) {
if (vec) return vec;
J *out = allocate_typed_vector(K_TYPE_LONG, 1);
if (out) out[0] = 0;
return out;
}
V *bigint_normalize_inner_helper(V **vec) {
if (!vec || !*vec) return 0;
J *p = (J *)*vec; I n = XN(*vec);
while (n > 1 && p[n - 1] == 0) n--;
XN(*vec) = n;
return *vec;
}
V *bigint_normalize_in_place(V **vec)
{
if (vec == NULL || (uintptr_t)vec < K_MIN_VALID_HEAP_ADDR) return vec;
I n = *(I *)((char *)vec - 4);
if (n <= 0) return vec;
J *limbs = (J *)vec;
while (n > 1 && limbs[n - 1] == 0) n--;
*(I *)((char *)vec - 4) = n;
return vec;
}
J *bigint_grow_to(I target_lo, V **vec)
{
V **g = ensure_capacity(target_lo - *(I *)((char *)vec - 4), vec);
return (J *)g;
}
J *bigint_grow_to_target_lo(I target_lo, V **vec) { return bigint_grow_to(target_lo, vec); }
I leaf_int_value(V *vec) {
if (!vec) return 0;
return *(I *)vec;
}
J *reshape_or_take_full(I arg1, J *vec) {
if (!vec) return 0;
I n = XN(vec);
if (arg1 == n) return vec;
J *out = allocate_typed_vector(XT(vec), arg1);
if (!out) return vec;
for (I i = 0; i < arg1; i++) out[i] = vec[i % n];
return out;
}
J *sort_with_key(J key_seed, J *vec)
{
J pin = key_seed;
J *out = sort_or_grade_inner(vec, NULL, &pin);
release_object((V **)vec);
return out;
}
J *sort_with_key_seed(J key_seed, J *vec) { return sort_with_key(key_seed, vec); }
J is_count_call(J *arg1, J a2, J a3, I flags)
{
(void)a2; (void)a3;
if (((J)arg1 >> K_TAG_SHIFT) != 0) {
arg1 = *(J **)((char *)arg1 + 8);
} else if (*(G *)((char *)arg1 - 5) == K_TYPE_LITERAL_FUNC &&
*(G *)((char *)arg1 - 6) == 0 &&
*(I *)((char *)arg1 - 4) < 7) {
} else {
arg1 = *(J **)((char *)arg1 + 8);
}
I *body = (I *)arg1[2];
if (((((uI)body[1]) ^ 0x74) | (0x6e756f63u ^ (uI)body[0])) == 0) {
return 1;
}
V *vbody = (V *)*arg1;
return (uI)((G)((char *)vbody)[*(I *)((char *)vbody - 4) - 1] - 0x34) < 0xc;
}
J is_count_call_lambda(J *a, J b, J c, I d) { return is_count_call(a, b, c, d); }
V *sort_then_canonicalize(V *arg1, J *arg2)
{
V *pin = arg1;
I hint = leaf_int_value(arg1);
J *sorted = sort_or_grade_inner(arg2, NULL, &pin);
I rd = (I)release_object((V **)arg2);
return size_match_or_clone(hint, sorted, rd);
}
J k10_check_short_e(V *e) {
if (TAG(e)) R 0;
if (XT(e) != K_TYPE_LITERAL_FUNC) R 0;
if (XA(e)) R 0;
R XN(e) <= 6;
}
J k10_is_short_funcs(V *arg, I a2, I a3) {
(void)a2; (void)a3;
if (TAG(arg) || XT(arg)) R 0;
uJ i = 0;
uJ n = (uJ)XN(arg);
while (i < n) {
V *e = *(V **)((char *)arg + (i << 3));
if (!k10_check_short_e(e)) R 0;
i++;
}
R 1;
}
J k10_is_short_func_table(V *a, I b, I c) {
R k10_is_short_funcs(a, b, c);
}
J k10_group_or_take(I cnt, J *vec, I flg) {
V **b = (V **)ensure_singleton_or_box(vec,
(J)vec,
flg);
if (cnt < 2)
R (J)reshape_take_recursive(cnt, b);
R (J)reshape_or_take_full(cnt, b);
}
J k10_group_dispatch(I c, J *v, I f) {
R k10_group_or_take(c, v, f);
}
J *k10_digits_take(I cnt, V **vec) {
if (cnt <= 1) {
V *b = box_immediate_to_heap((J)vec);
R (J *)reshape_take_recursive(cnt,
(V **)b);
}
J *out;
if (((I)TAG(vec)) != 8) {
V *b = box_immediate_to_heap((J)vec);
out = (J *)reshape_or_take_full(cnt,
(V **)b);
} else {
out = make_zero_filled(8, cnt);
if (vec)
out = (J *)bitwise_complement_vector((J)out);
}
XA(out) = 2;
R out;
}
V *k10_digits_alias(I cnt, J val) {
R (V *)k10_digits_take(cnt,
(V **)(uintptr_t)val);
}
J k10_is_homo(V *arg, J a2, J a3, I flg) {
(void)a2; (void)a3; (void)flg;
if (!arg || (uJ)arg < K_HEAP_LOW_ADDR) R 0;
if (XT(arg)) R 0;
uJ n = (uJ)XN(arg);
if (!n) R 0;
for (uJ i = 0; i < n; i++) {
V *e = *(V **)((char *)arg + (i << 3));
if (TAG(e)) R 0;
G t = XT(e);
if (t && (t - 1) > 0x3e) R 0;
}
R 1;
}
J k10_is_homo_alias(V *a, J b, J c, I d) {
R k10_is_homo(a, b, c, d);
}
uJ k10_pchain_len(V **arg, J a2, I flg) {
(void)a2; (void)flg;
uI t = (uI)TAG(arg);
uJ r = 0;
while (!t) {
if (XT(arg) != K_TYPE_LITERAL_FUNC) break;
if (!XA(arg)) {
r = (uJ)XN(arg[3]);
break;
}
arg = (V **)*arg;
t = (uI)TAG(arg);
}
R r;
}
V **k10_apply_verb(J *fn, V *arg) {
R (V **)verb_apply_alias(fn, 1,
(J *)&arg);
}
V **k10_apply_list(J *fn, V **arg, I flg) {
if (!same_kind((J *)arg, 0, flg))
R (V **)sym_lookup_apply_alias(fn,
arg, flg);
V *raw = retain_object(fn);
if (!TAG(raw) && XT(raw) == K_TYPE_PAIR_CELL)
R (V **)sort_then_canonicalize(raw,
(J *)arg);
R (V **)raw;
}
V **k10_apply_v(J *fn, V *arg, J a3, uJ flg) {
(void)a3;
if ((uJ)fn <= K_BYTE_MAX)
R k10_apply_verb(fn, arg);
if (!TAG(fn)) {
G t = XT(fn);
if (t == K_TYPE_LITERAL_FUNC) R k10_apply_verb(fn, arg);
} else if (TAG(fn) > K_VERB_GROUP_PRIME) {
R k10_apply_verb(fn, arg);
}
R k10_apply_list(fn, (V **)arg, (I)flg);
}
V **k10_apply_atomic(J *fn, V *v, J a3, uJ f) {
R k10_apply_v(fn, v, a3, f);
}
J k10_rebalance_left(V **arg1, V ***arg2) {
if (XT(arg1) != K_TYPE_PAIR_CELL) {
V *v = unwrap_pair_or_self(arg2);
V **out = pair_cell_concat_value(arg1, v);
R (J)k10_canon_homo_list((J *)out, 0, 0);
}
V **dup = clone_or_recycle_real(arg1);
R (J)pair_cell_insert(dup, arg2, 0);
}
J k10_rebalance_alias(V **a, V ***b) {
R k10_rebalance_left(a, b);
}
uJ k10_merge_rhs_tag(V ***right) {
R K_RUNTIME_HEADER_OK(right) ?
(uJ)XT(right) : 0xffu;
}
V **k10_merge_promote(V **anc, V **right) {
V **dup = pair_promote_uniform_alias((V ***)&anc,
right);
if (K_IS_ERR_RETURN(dup)) R dup;
R (V **)charvec_concat(anc, (char *)dup);
}
V **k10_merge_mismatch(V **anc, V **l, V **r,
uI lt, uI rt) {
if (K_TAG_NUMERIC_MIX(lt) && K_TAG_NUMERIC_MIX(rt))
R k10_merge_promote(anc, r);
if (K_TAG_INT_FAMILY(lt) && K_TAG_INT_FAMILY(rt))
R k10_merge_promote(anc, r);
V *lv = unwrap_pair_or_self(l);
V *rv = unwrap_pair_or_self(r);
R (V **)charvec_concat((V **)lv, (char *)rv);
}
V **k10_merge_check_r(V ***r, V ***arg2, I arg3) {
uJ rt = !TAG(r) ? k10_merge_rhs_tag(r) : 0xffu;
if (TAG(r) || rt == K_TYPE_LITERAL_FUNC) {
r = (V ***)ensure_singleton_or_box((J *)r,
(J)arg2,
arg3);
}
R (V **)r;
}
V **k10_merge_dispatch(V **l, V ***r, V **arg1) {
uI lt = (uI)XT(l);
uI rt = (uI)XT(r);
if (lt == K_TYPE_PAIR_IMMEDIATE || rt == K_TYPE_PAIR_IMMEDIATE) R l;
if (lt == K_TYPE_KEYED_PAIR)
R (V **)charvec_concat(l, "cat");
if (lt != rt)
R k10_merge_mismatch(arg1, l, (V **)r,
lt, rt);
if (lt == K_TYPE_PAIR_CELL)
R (V **)concat_pair_chains((char *)l,
(V **)r);
R (V **)charvec_concat(l, (char *)r);
}
V **k10_merge_concat(V **arg1, V ***arg2, I a3, I a4) {
(void)a4;
if (TAG(arg1))
arg1 = (V **)box_immediate_to_heap(arg1);
V **l = arg1;
V ***r = k10_merge_check_r(arg2, arg2, a3);
uJ rt = XT(r);
if (rt == K_TYPE_KEYED_PAIR || !kind_or_length(r)) R l;
if (!kind_or_length(l)) {
release_object((V **)l);
R (V **)r;
}
R k10_merge_dispatch(l, r, arg1);
}
V **k10_multi_concat(V **a, V ***b, I c, I d) {
R k10_merge_concat(a, b, c, d);
}
V **k10_ins_match(J *arg1, J *arg2) {
R insert_with_callback(arg1, arg2, NULL, 0);
}
V **k10_ins_match_cb(J *a, J *b) {
R k10_ins_match(a, b);
}
V *k10_pimm_canon(J *arg) {
R expand_pair_immediate(arg);
}
V *k10_pimm_canon_alias(J *arg) {
R k10_pimm_canon(arg);
}
V **k10_prom_bool_cls(I val, V **vec) {
if (val > 0xffff) R vec;
I cls = (val > 1) ? ((1 * 3) | 8) : 8;
I tgt = (val <= K_BYTE_MAX) ? cls : 0xc;
V **out = cast_to_tag_alias(tgt, vec);
*((I *)out - 1) = (I)(I16)val;
R out;
}
V **k10_shrink_int(I v, V **vec) {
R k10_prom_bool_cls(v, vec);
}
V **k10_canon_typed_unq(V **vec, J a2, I flg) {
I len = XN(vec);
V *bc = bitwise_complement_vector(
(J)promote_to_unique_bool(vec));
J *tail = cast_graph_int_tail((J)bc);
J *shape = shape_with_int_dimensions(vec,
(__int128 *)retain_object(tail));
release_object((V **)vec);
V **payload = (V **)intvec_append_word(
(V **)apply_unary_each((K_unary_fn)retain_object, tail),
len);
XA(payload) = 3;
R (V **)pair_cell_make(K_TYPE_PAIR_IMMEDIATE, shape,
(J *)payload);
}
V **k10_canon_typed_widely(V **a17, I flg, J a3) {
I bp3 = XN(a17) - 1;
V **a14 = (V **)kalloc(0xd, bp3);
if (bp3 <= 0xffff) {
I tgt = (bp3 > K_BYTE_MAX) ? 0xc : (((bp3 > 1) * 3) | 8);
a14 = cast_to_tag_alias(tgt, a14);
*((I *)a14 - 1) = bp3;
}
if (XN(a17) >= 0x10000) R (V **)5;
G align_in = XA(a14);
G align_out = align_in ? align_in : 1;
J *out = (J *)pair_cell_make(K_TYPE_PAIR_IMMEDIATE,
a17, (J *)a14);
XA(out) = align_out;
R (V **)out;
}
V **k10_canon_for_typed(V **arg, J a2,
J a3, I flg) {
if (XT(arg) == K_TYPE_PAIR_IMMEDIATE) R arg;
V **canon = canonicalize_for_send(arg, a2, a3, flg);
if (!is_canonical_promote_target((J *)canon, flg))
R (V **)9;
if ((uI)*((I *)canon - 1) - 1 >= 0x3e7) R canon;
if (is_widely_typed_sorted((J *)canon, a2,
(uI)flg)) R canon;
if (is_unique_sorted((J *)canon, a2, (uI)flg))
R k10_canon_typed_unq(canon, a2, flg);
V **a16 = (V **)retain_object((V *)canon);
V **a17 = (V **)canonicalize_to_typed_vector(
(J *)a16, flg, a3, flg);
R k10_canon_typed_widely(a17, flg, a3);
}
V **k10_canon_typed_pair(V **a, J b, J c, I d) {
R k10_canon_for_typed(a, b, c, d);
}
I k10_nz(G st, __int128 *vec, I i) {
if (st == 8)
R (((G *)vec)[i >> 3] >> (i & 7)) & 1;
if (st == K_TYPE_PAIR_CELL || st == K_TYPE_CHAR)
R ((char *)vec)[i] != 0;
if (st == K_TYPE_SHORT) R ((I16 *)vec)[i] != 0;
if (st == K_TYPE_INT) R ((I *)vec)[i] != 0;
if (st == 0x20) R ((J *)vec)[i] != 0;
if (st == K_TYPE_FLOAT)
R ((F *)vec)[i] != 0.0;
R ((char *)vec)[i] != 0;
}
J *k10_cast_bool_packed(__int128 *vec, char *m) {
if (!vec || (uJ)vec < K_HEAP_LOW_ADDR) R (J *)vec;
G st = XT(vec);
I n = XN(vec);
if (n < 0 || n > 0x3fffffff) R (J *)vec;
J *out = allocate_typed_vector(8, n);
if (K_IS_ERR_RETURN(out)) R out;
G *b = (G *)out;
memset(b, 0, (n + 7) >> 3);
for (I i = 0; i < n; i++) {
I nz = k10_nz(st, vec, i);
if (nz) b[i >> 3] |= (G)(1u << (i & 7));
if (m) m[i] = (char)nz;
}
R out;
}
J *k10_cast_int_typed(I tgt, __int128 *vec) {
if ((tgt & 0xfffffffe) == K_TYPE_F64_VEC) {
V *c = k10_cast_int_typed(0xd, vec);
R (J *)cast_to_tag((V *)(uintptr_t)tgt,
(__int128 *)c);
}
J *out = kalloc(tgt, XN(vec));
(void)k_type_cast_gradient_table[XT(out)];
R cast_to_typed_inner_helper(tgt, vec);
}
J *k10_canon_homo_build(J *v, uI in, uJ n) {
uI wide = in;
for (uJ i = 1; i < n; i++) {
uI t = (uI)TAG(v[i]);
if (wide < t) wide = t;
}
J *out = allocate_typed_vector((I)wide, (I)n);
for (uJ i = 0; i < n; i++) {
element_store_into_typed(out, (J)i,
retain_object((V *)v[i]));
}
release_object((V **)v);
R out;
}
J k10_homo_k(J *vec, uJ n, uI inner) {
J k = 1;
while (k < (J)n && (uI)TAG(vec[k]) == inner)
k++;
R k;
}
J k10_homo_k_num(J *vec, uJ n) {
J k = 1;
while (k < (J)n && (TAG(vec[k]) - 8) < 7)
k++;
R k;
}
J *k10_canon_homo_list(J *vec, uJ a, uI f) {
if (!vec || (uJ)vec < K_HEAP_LOW_ADDR) R vec;
if (XT(vec)) R vec;
uI in = (uI)TAG(*vec);
uJ n = (uJ)XN(vec);
if (in) {
if (k10_homo_k(vec, n, in) >= (J)n)
R k10_canon_homo_build(vec, in, n);
}
if ((in - 8) > 6)
R refresh_keyed_pairlist(vec, (J)a, (I)f);
if (k10_homo_k_num(vec, n) < (J)n)
R refresh_keyed_pairlist(vec, (J)a, (I)f);
R k10_canon_homo_build(vec, in, n);
}
V **k10_ensure_box(J *v, J a, I f) {
R (V **)ensure_singleton(v, a, f);
}
I k10_cmp_bool(V *a, V *b) { R (I)bitvec_eq(a, b); }
I k10_atom_eq(J a, J b) { R a == b; }
V *k10_size_match(I want, V *vec, I flg) {
(void)flg;
if (!vec || (uJ)vec < K_HEAP_LOW_ADDR) R vec;
I cur = XN(vec);
if (cur == want) R vec;
if (cur < want) R (V *)promote_widen(want,
(V **)vec);
V **dup = clone_or_recycle_header(vec);
if (dup) XN(dup) = want;
R (V *)dup;
}
V *k10_unwrap(J *arg) { R unwrap_or_self(arg); }
J k10_norm_atom_list(V *vec) {
if (K_IS_ERR_RETURN(vec)) R (J)vec;
R (J)k10_canon_homo_list((J *)vec, 0, 0);
}
J *k10_bit_not(J arg) {
R bitwise_not_vec((__int128 *)arg);
}
uJ k10_max_i(V *v, J a2, J a3, uJ h) {
(void)h; (void)a2; (void)a3;
if (!v || (uJ)v < K_HEAP_LOW_ADDR) R 0;
I *p = (I *)v;
uJ n = (uJ)XN(v);
I m = n ? p[0] : 0;
for (uJ i = 1; i < n; i++)
if (p[i] > m) m = p[i];
R (uJ)(uI)m;
}
uJ k10_max_j(V *v, J a2, J a3, uJ h) {
(void)h; (void)a2; (void)a3;
if (!v || (uJ)v < K_HEAP_LOW_ADDR) R 0;
J *p = (J *)v;
uJ n = (uJ)XN(v);
J m = n ? p[0] : 0;
for (uJ i = 1; i < n; i++)
if (p[i] > m) m = p[i];
R (uJ)m;
}
uJ k10_max_s(V *v, J a2, J a3, uJ h) {
(void)h; (void)a2; (void)a3;
if (!v || (uJ)v < K_HEAP_LOW_ADDR) R 0;
I16 *p = (I16 *)v;
uJ n = (uJ)XN(v);
I16 m = n ? p[0] : 0;
for (uJ i = 1; i < n; i++)
if (p[i] > m) m = p[i];
R (uJ)(uint16_t)m;
}
V *k10_canon_pchain(V **vec) {
if (XT(vec) != K_TYPE_CHAR && XT(vec) != K_TYPE_PAIR_CELL)
R vec;
I d = 0; V *p = vec;
while (d <= 6 && XT(p) == K_TYPE_PAIR_CELL) {
p = *(V **)((char *)p + 8);
d++;
}
if (d <= 6) XA(vec) = 4;
R vec;
}
V *k10_canon_temp(V **vec) {
if (XA(vec) >= 3) XA(vec) = 4;
R vec;
}
V *k10_canon_int(V **vec) {
if (XT(vec) == 0x20) {
J *p = (J *)vec;
uJ n = (uJ)XN(vec);
I f = 1;
for (uJ i = 0; i < n; i++)
if (p[i] < -2147483648LL ||
p[i] > 2147483647LL) {
f = 0; break;
}
if (f) XA(vec) = 4;
} else XA(vec) = 4;
R vec;
}
V *k10_canon_other(V **vec) {
if (!XT(vec)) {
uJ n = (uJ)XN(vec);
I f = 1;
for (uJ i = 0; i < n; i++) {
V *c = ((V **)vec)[i];
if (!TAG(c) && XA(c) < 4) { f = 0; break; }
}
if (f) XA(vec) = 4;
} else XA(vec) = 4;
R vec;
}
V *k10_canon_to_typed(V **vec, I flg) {
G h = XT(vec);
if (h == K_TYPE_PAIR_CELL || h == K_TYPE_KEYED_PAIR)
R k10_canon_pchain(vec);
if ((h & 0xf0u) == 0x10)
R k10_canon_temp(vec);
if (((0x1fc00u >> h) & 1) || h == 0x20)
R k10_canon_int(vec);
(void)flg;
R k10_canon_other(vec);
}
I k10_is_canon_prom(J *v, I f) {
(void)f;
if (TAG(v)) R 0;
if (XN(v) < 1) R 0;
if (XT(v) == K_TYPE_LITERAL_FUNC) R 0;
R XA(v) < 4;
}
V *k10_canon_u(V *v, J a, uI f) {
R k10_canon_homo_list((J *)v, a, f);
}
V *k10_canon_u_alias(V *v, J a, uI f) {
R k10_canon_u(v, a, f);
}
J *k10_reshape(I w, J *v) {
R reshape_or_take(w, v);
}
I k10_leaf_int(V *v) { R (I)leaf_int(v); }
J k10_pimm_idx(V *p, uJ idx) {
if (!p || (uJ)p < K_HEAP_LOW_ADDR) R 0;
uJ pt = (uJ)XT(p);
if (pt == 8)
R (((J *)p)[idx >> 6] >> (idx & 63)) & 1;
if ((0x1fc00u >> pt) & 1) R ((I *)p)[idx];
if (pt == K_TYPE_SHORT) R ((I16 *)p)[idx];
R (J)((G *)p)[idx];
}
V **k10_pair_cat(V **a1, V *a2) {
R pair_cell_concat(a1, a2);
}
V **k10_pair_ins(V **a1, V ***a2, I f) {
(void)f; R pair_cell_concat(a1, a2);
}
V **k10_cat_pchains(char *l, V *r) {
R (V **)concat_pairchain(l, (V **)r);
}
V **k10_ins_cb(V *cb, V *base, V **slot, I f) {
R insert_with_callback(cb, base, slot, f);
}
J k10_fold_temp(I tgt, V *vec) {
G h = XT(vec);
if (h == (G)tgt) R (J)vec;
if ((h & 0xf0u) != 0x10 ||
((uI)tgt & 0xf0u) != 0x10)
R (J)cast_to_tag((V *)(uintptr_t)tgt,
(__int128 *)vec);
V **out = clone_or_recycle_header((V **)vec);
XT(out) = (G)tgt;
R (J)out;
}
J k10_cast_i_tail(J arg) {
if (TAG(arg) || (uJ)arg < K_HEAP_LOW_ADDR) R arg;
if (XT(arg) == 0x20) {
J *p = (J *)arg;
uJ n = (uJ)XN(p);
for (uJ i = 0; i < n; i++)
if (p[i] < -2147483648LL ||
p[i] > 2147483647LL) R arg;
R (J)cast_to_tag((V *)0xd, (__int128 *)arg);
}
R arg;
}
J k10_get_v(I sw, __int128 *vec, I i) {
if (sw == 0)
R (((G *)vec)[i >> 3] >>
(i & 7)) & 1;
if (sw == 3) R ((char *)vec)[i];
if (sw == 4) R ((I16 *)vec)[i];
if (sw == 5) R ((I *)vec)[i];
if (sw == 6) R ((J *)vec)[i];
R 0;
}
V k10_put_v(I dw, J *out, I i, J v) {
if (dw == 0) {
if (v) ((uJ *)out)[i >> 6] |= (1ULL << (i & 63));
else ((uJ *)out)[i >> 6] &= ~(1ULL << (i & 63));
} else if (dw == 3) ((char *)out)[i] = (char)v;
else if (dw == 4) ((I16 *)out)[i] = (I16)v;
else if (dw == 5) ((I *)out)[i] = (I)v;
else if (dw == 6) ((J *)out)[i] = (J)v;
}
V *k10_cast_typed_inner_v(I tgt, __int128 *vec) {
if (!vec || (uJ)vec < K_HEAP_LOW_ADDR) R vec;
G st = XT(vec);
if ((uI)st == (uI)tgt) R vec;
I n = XN(vec);
if (n < 0 || n > 0x3fffffff) R vec;
J *out = allocate_typed_vector(tgt, n);
if (K_IS_ERR_RETURN(out)) R out;
I sw = k_type_log2_bits_table_alias[st & K_BYTE_MAX];
I dw = k_type_log2_bits_table_alias[tgt & K_BYTE_MAX];
for (I i = 0; i < n; i++) {
J v = k10_get_v(sw, vec, i);
k10_put_v(dw, out, i, v);
}
release_object((V **)vec); R out;
}
V *k10_cast_c_b(I tgt, V **vec) {
R promote_to_target_type(tgt, vec);
}
V *k10_narrow(V *vec) { R narrow_long_to_int(vec); }
V *k10_proj_cols(J a, J b, I c) {
V **v = (V **)a; (void)b; (void)c; if (!v) R NULL;
if (TAG(v)) R k10_canon_homo_list((J *)v,
0, 0);
if (XT(v) == K_TYPE_PAIR_IMMEDIATE)
v = (V **)expand_pair_immediate((J *)v);
K_unary_fn bx = (K_unary_fn)box_immediate_to_heap;
R apply_unary_each(bx, (J *)v);
}
J *k10_prom_bool(J *vec) {
R promote_to_unique_bool(vec);
}
J k10_recip(J sh, __int128 *vec, J a) {
(void)a; __int128 *dst = (__int128 *)sh;
if (!vec || !dst) R 0;
I n = XN(vec);
uJ nl = (uJ)((n + 3) >> 2);
for (uJ i = 0; i < nl; i++) {
F d0 = ((F *)vec)[i * 4 + 0];
F d1 = ((F *)vec)[i * 4 + 1];
F d2 = ((F *)vec)[i * 4 + 2];
F d3 = ((F *)vec)[i * 4 + 3];
I a[4] = { (I)d0, (I)d1, (I)d2, (I)d3 };
memcpy(&dst[i], a, sizeof a);
}
R 0;
}
J *k10_iter(I vb, V *base, V **vec) {
if (TAG(vec)) R (J *)vec;
if (!base) R (J *)fold_engine_full(vb,
vec, 0);
V **acc = (V **)retain_object(base);
uJ n = (uJ)XN(vec);
for (uJ i = 0; i < n; i++) {
V **e = (V **)retain_object(vec[i]);
J args[2] = { (J)acc, (J)e };
acc = (V **)verb_byte_apply((J)vb, 2,
(uJ)(uintptr_t)args);
}
release_object((V **)vec); R (J *)acc;
}
V *k10_bi_norm(V **vec) {
R bigint_normalize_in_place(vec);
}
V *k10_bi_load(V *vec) { R vec; }
J *k10_store(J *dst, J idx, V *val) {
if (!dst || (uJ)dst < K_HEAP_LOW_ADDR) R dst;
uJ t = (uJ)XT(dst);
if (t == 8) {
uJ bit = (uJ)((J)val & 1);
if (bit) dst[idx >> 6] |= (1LL << (idx & 63));
else dst[idx >> 6] &= ~(1LL << (idx & 63));
} else if ((0x1fc00u >> t) & 1)
((I *)dst)[idx] = (I)(uintptr_t)val;
else if (t == K_TYPE_SHORT)
((I16 *)dst)[idx] = (I16)(uintptr_t)val;
else if (t == K_TYPE_CHAR || t == 1)
((char *)dst)[idx] = (char)(uintptr_t)val;
else dst[idx] = (J)val;
R dst;
}
V k10_bit_cp(V *dst, const V *src, J o, J b) {
G *d = (G *)dst;
const G *s = (const G *)src;
for (J i = 0; i < b; i++) {
J sb = (s[i >> 3] >> (i & 7)) & 1;
J di = o + i; J by = di >> 3; J bi = di & 7;
d[by] = (d[by] & ~(1u << bi)) |
((G)sb << bi);
}
}
J *k10_render_list(J *v, G h) {
K_unary_fn f = (K_unary_fn)format_one_node_for_display;
V **r = (V **)apply_unary_each(f, v);
J *j = join_charvecs_with_separator(' ', r);
*((I *)j - 1) -= 1;
if ((h & K_BYTE_HIGH_BIT_MASK) == 0x10) {
char l = (char)format_temporal_field_letter(h);
R (J *)append_byte_to_charvec((V **)j, l);
}
R j;
}
J *k10_render_val(J *vec) {
J *v = vec;
while (XT(v) == K_TYPE_PAIR_IMMEDIATE)
v = (J *)expand_pair_immediate(v);
G h = XT(v);
if (h == K_TYPE_CHAR) {
if (!memchr(v, '\n', (size_t)XN(v)))
R (J *)wrap_string_literal(NULL, (V **)v);
}
if ((h - 2) <= 5) {
V *p = pair_chain_walk_recurse(0, v);
R (J *)flatten_pair_chain_to_atoms(0x60,
(J *)p);
}
R k10_render_list(v, h);
}
J *k10_render_pair_j(J *pair) {
V **slot = (V **)pair; V *left = retain_object((V *)*pair);
J *right = (J *)retain_object((V *)pair[1]);
release_object((V **)slot);
K_unary_fn f = (K_unary_fn)format_value_recursive;
J *c = (J *)pair_cell_make(K_TYPE_KEYED_PAIR, (J)left,
(J *)apply_unary_each(f, right));
V **rp = (V **)retain_object((V *)c[1]);
J *lp = (J *)retain_object((V *)*c);
release_object((V **)c); V **df = (V **)8;
if (!TAG(rp) && !XT(rp)) {
J k = 0;
while (k < (J)XN(rp) &&
!TAG(rp[k]) && XT(rp[k]) == 1) k++;
if (k >= (J)XN(rp))
df = (V **)pair_chain_walk_recurse(0, lp);
}
R (J *)wrap_string_literal(
(char *)&verb_class_classifier[K_PRINT_TAB_INDEX], df);
}
J *k10_render_asgn(J *left, J *right) {
V *l = render_pair_to_source(left);
V *r = render_pair_to_source(right);
V *lc = make_charvec_concat_byte('[', (char *)l);
R (J *)concat_charvecs((V **)lc,
(char *)pair_chain_walk_recurse(0, r));
}
J *k10_render_dyad(char vb, V **l, V **r) {
J i = 0;
J *out = allocate_typed_vector(0, XN(l));
do {
out[i] = compare_aux_a(vb, (J)retain_object(l[i]),
(J)retain_object(r[i]));
i++;
} while (i < (J)XN(out));
release_object((V **)r); release_object((V **)l); R out;
}
K k10_render_table(I cols, K hdr, K vcols) {
if (!cols) R retain_object(runtime_builtin_sym_table);
J n = kind_or_length_walk(vcols);
K res = allocate_typed_vector(K_TYPE_LIST, (I)n);
I cnt = XN(res), i = 0;
while (i < cnt) {
K c = (K)index_typed_vector(vcols, (uJ)i);
K rd = k10_rend_val(cols, c);
res[i] = (J)elide_at_columns(cols, rd);
i++;
}
R k10_rend_fin(cols, hdr, vcols, res);
}
K k10_rend_fin(I cols, K hdr, K vcols, K res) {
I w = k10_rend_wide(hdr, res);
k10_rend_pad(vcols, res, w);
R k10_rend_hdr(hdr, res, w, vcols);
}
K k10_rend_val(I c, K x) {
if (k10_tag(x)) R (K)render_value_to_source(x);
G t = XT(x);
if (t == K_TYPE_PAIR_CHAIN)
R (K)pair_chain_walk_recurse(0, x);
if (t == K_TYPE_LITERAL_FUNC)
R (K)render_value_to_source(x);
if ((I)pair_chain_length((V**)x) > c)
x = (K)reshape_take_recursive(c, x);
R (K)format_value_recursive(x);
}
I k10_rend_wide(K h, K r) {
I w = (h) ? XN(h) : 0, n = XN(r), i = 0;
while (i < n) {
I cw = XN(r[i]);
if (cw > w) w = cw;
i++;
}
return w;
}
V k10_rend_pad(K v, K r, I w) {
G t = XT(v);
I n = XN(r);
typedef K (*P)(I, K);
P f = ((t - 8) < 6) ? (P)emit_pad_for_print_lhs
: (P)emit_pad_for_print_rhs;
for (J i = 0; i < n; i++)
r[i] = (J)f(w, (K)r[i]);
}
K k10_rend_hdr(K h, K r, I w, K v) {
if (h) {
K p1 = (K)emit_pad_for_print_rhs(w, h);
J p2 = digits_or_truncate(w, (V**)0x10000000000002dULL);
V** hp = (V**)make_pair_J((J)p1, (J)p2);
r = (K)concat_charvecs(hp, (S)r);
}
release_object((V **)v);
R r;
}
K k10_intern_dot(J c) { R intern_dotted(c); }
K k10_mark_ip(K x, J y, I f) {
if (!x || k10_tag(x) || XT(x) != K_TYPE_KEYED_PAIR)
R (K)6;
if (!is_unique_sorted(*x, y, f)) R (K)9;
*((G*)x - 6) = 1;
R x;
}
uJ k10_temp_let(I f) {
if ((f & 0xfffffff0u) != 0x10) {
uJ m = 0xcccccccdULL;
I i = f - (I)((uJ)((((uJ)f * m) >> 37) << 3) * 3);
return (uJ)(G)date_field_letters_b[i];
}
return (uJ)(G)temporal_suffix_letters_b[f & 7];
}
V k10_cast_temp(I l, J v) {
if (l == 'y') R k10_cast_y(v);
R k10_cast_t(l, v);
}
V k10_cast_y(J v) {
J d = (J)reshape_to_target_tag(0x18, v);
if (K_IS_ERR_RETURN(d)) return d;
if (!k10_tag((K)d)) {
J p = clone_or_recycle_header(d);
XT(p) = K_TYPE_INT;
K r = (K)reciprocal_with_cap(0xc, p, 0);
return (J)reshape_cast_for_letter(0x7d1, (V**)r);
}
uJ x = (uJ)d, m = 0xaaaaaaabULL;
I y = (I)((x * m) >> 35) + 0x7d1;
return (J)((0xcULL << 48) | (uJ)y);
}
V k10_cast_t(I l, J v) {
J s = -8;
while (s != 0) {
if ((G)temporal_suffix_letters_b[s + 8] == l) {
I b = ((I)s + 8 - 1) < 2;
I t = (I)(s + 8 + (b << 3)) + 0xf;
if (t) return (J)reshape_to_target_tag(t, v);
break;
}
s++;
}
write_cstr_stderr((S)l);
write_cstr_stderr("\n");
R (void)4;
}
K k10_flatten(I v, K x) {
R (K)wrap_string_literal((S)v, (V**)x);
}
K k10_prom_alias(I t, J x) {
R (K)promote_to_target_type(t, x);
}
V k10_unq_fs_prom(J a, J a1, J a2, I f) {
if (k10_tag((K)a)) R a;
if (XT(a) > K_TYPE_PAIR_CELL) R a;
J c = canonicalize_into_typed_pair_imm(a, a1, a2, f);
if (K_IS_ERR_RETURN(c)) R c;
if (XT(c) == K_TYPE_PAIR_IMMEDIATE)
R k10_unq_fs_split(c);
if (is_widely_typed_sorted((K)c, a1, f) == 0)
R (void)k10_build_idx(XT(c),
(K)pair_chain_walk_recurse_alt(c));
K m = (K)0xd00000000000001LL;
R (void)scalar_grouper(c, (J)m, a2, f);
}
V k10_unq_fs_split(J c) {
J h = retain_object(*(V**)c);
J t = retain_object(((V**)c)[1]);
release_object((V **)c);
return (J)pair_cell_make(K_TYPE_KEYED_PAIR, (J)h,
(K)k10_unq_p_imm(t));
}
J k10_build_idx(I h, K v) {
K v2 = (K)retain_object(v);
if (h == 0) v2 = (K)list_element_lengths((V**)v2);
char m[16];
K bv = (K)cast_graph_int_tail((J)k10_bool_inner(v2, m));
K u = (K)pair_chain_walk_recurse(0, v);
release_object((V **)v);
R (J)pair_cell_make(K_TYPE_KEYED_PAIR,
(J)cast_to_tag((J)h, (__int128*)bv), u);
}
K k10_unq_p_imm(J a) {
if (k10_tag((K)a)) R (K)6;
G h = XT(a);
if (h == K_TYPE_LITERAL_FUNC) R (K)6;
if (h != K_TYPE_KEYED_PAIR) R k10_unq_p_p(a);
J hd = retain_object(*(V**)a), tl = retain_object(((V**)a)[1]);
release_object((V **)a);
J in = k10_unq_p_imm(tl);
if (K_IS_ERR_RETURN(in)) return (V**)in;
return (V**)pair_cell_concat_value((V**)hd, (V**)in);
}
K k10_unq_p_p(J a) {
J c = canonicalize_into_typed_pair_imm(a, 0, 0, 0);
if (K_IS_ERR_RETURN(c)) return (V**)c;
if (XT(c) == K_TYPE_PAIR_IMMEDIATE)
return k10_unq_p_s(c);
if (is_widely_typed_sorted((K)c, 0, 0) == 0)
return (V**)k10_build_idx(XT(c),
(K)pair_chain_walk_recurse_alt(c));
K i = (K)apply_unary_each((K_unary_fn)k10_box,
(K)reshape_take_recursive(0, (J)*(uI*)((S)c-4)));
return (V**)pair_cell_make(K_TYPE_KEYED_PAIR, (J)c, i);
}
K k10_unq_p_s(J c) {
J h = retain_object(*(V**)c), t = retain_object(((V**)c)[1]);
release_object((V **)c);
K b;
if (*((char*)t - 6) <= 1) b = k10_scalar_grp(t, 0, 0, 0);
else b = k10_unq_p_l(t);
return (V**)pair_cell_make(K_TYPE_KEYED_PAIR, (J)h, b);
}
K k10_unq_p_l(J t) {
I i = 0, n = XN(t);
K o = allocate_typed_vector(0, n);
do {
I p = (i) ? *((I*)t + (i-1)) : 0;
I c = *((I*)t + i);
o[i] = (J)k10_digit_pos(p, c - p);
} while (++i < XN(o));
release_object((V **)t);
R o;
}
K k10_delta_idx(J a) {
if (XT(a) == K_TYPE_BOOL)
R (K)pair_immediate_canonicalize((K)a);
I n = *((uI*)((S)a-4)) + 1;
K o = allocate_typed_vector(K_TYPE_LIST, n);
K l = (K)bigint_split_at(XN(o), a);
for (J i = 0; i < XN(o); i++) {
K b = allocate_typed_vector(K_TYPE_INT, *((I*)l + i));
if (XN(b) >= 2) *((char*)b - 6) = 4;
o[i] = (J)b;
}
k10_delta_fill(a, o, l);
release_object((V **)l); release_object((V **)a);
R o;
}
V k10_delta_fill(J a, K o, K l) {
I n = XN(a);
if (!n) return;
J i = n - 1;
do {
G h = XT(a);
uJ b;
if ((K_TAGCLASS_INT32_LANE >> h) & 1)
b = (uJ)*((I*)a + i);
else if (h != K_TYPE_SHORT)
b = (uJ)*((G*)a + i);
else b = (uJ)*((I16*)a + i);
K bu = (K)o[b];
I p = *((I*)l + b) - 1;
*((I*)l + b) = p;
((I*)bu)[p] = (I)i;
if (i == 0) break;
i--;
} while (1);
}
K k10_pair_walk(V **v) {
V *c = v;
while (!k10_tag((K)c) && (XT(c) == K_TYPE_PAIR_CELL ||
XT(c) == K_TYPE_PAIR_IMMEDIATE))
c = *(V**)((S)c + 8);
R (K)retain_object(c);
}
K k10_alloc_p_imm(I h, K i) {
if (K_IS_ERR_RETURN(i)) R i;
V **d = clone_or_recycle_header((V**)i);
XT(d) = (G)h;
R (K)d;
}
V k10_log_j(uJ v) {
char b[24];
I l = sprintf(b, "%llu\n", (unsigned long long)v);
if (extension_keyword_table) {
K lg = (K)extension_keyword_table;
for (I i = 0; i < l; i++)
lg = (K)charvec_append_byte((V**)lg, b[i]);
extension_keyword_table = (J)lg;
} else write(2, b, (size_t)l);
}
K k10_digit_pos(I c, I b) {
K o = allocate_typed_vector(K_TYPE_INT, c);
for (I i = 0; i < c; i++) ((I*)o)[i] = b;
if (c >= 2) *((char*)o - 6) = 4;
R o;
}
K k10_bigint_split(I w, J v) {
K o = allocate_typed_vector(K_TYPE_INT, w);
if (K_IS_ERR_RETURN(v)) {
memset(o, 0, (size_t)w * 4);
R o;
}
I *s = (I*)v;
uI n = XN(v);
for (I i = 0; i < w; i++) {
I c = (i < (I)n) ? s[i] : 0;
I p = (i == 0) ? 0 : ((i-1) < (I)n ? s[i-1] : 0);
((I*)o)[i] = c - p;
}
R o;
}
K k10_scalar_grp(J v, J a1, J a2, I f) {
G h = XT(v);
if (h == K_TYPE_LONG)
R (K)group_long_to_index_dict((K)v);
if (((K_TAGCLASS_INT32_LANE >> h) & 1) ||
h == K_TYPE_SHORT || h == K_TYPE_PAIR_CHAIN ||
h == 1) R k10_grp_cst(v, h);
R k10_grp_gen(v);
}
K k10_grp_cst(J v, G h) {
K l = (K)cast_to_tag((J)K_TYPE_LONG,
(__int128*)retain_object(v));
K g = (K)group_long_to_index_dict(l);
J k = (J)*g, s = (J)g[1];
J bk = cast_to_tag((J)h, (__int128*)k);
release_object((V **)v);
R (K)pair_cell_make(K_TYPE_KEYED_PAIR, (J)bk, s);
}
K k10_grp_gen(J v) {
I n = XN(v);
K u = allocate_typed_vector(K_TYPE_LIST, 0), m = allocate_typed_vector(K_TYPE_LIST, 0);
for (uJ i = 0; i < (uJ)n; i++) {
J c = ((V**)v)[i];
I f = 0, un = XN(u);
for (uJ j = 0; j < (uJ)un; j++) {
if (deep_equal((V**)u[j], (V**)c, 0, 0)) {
u[j] = (J)list_append_value((V**)u[j], (K)i, 0);
f = 1; break;
}
}
if (!f) k10_grp_add(&u, &m, c, i);
}
release_object((V **)v);
R (K)pair_cell_make(K_TYPE_KEYED_PAIR, (J)u, m);
}
V k10_grp_add(K *u, K *m, J c, uJ i) {
*u = (K)list_append_value((V**)*u, (K)retain_object(c), 0);
K idx = allocate_typed_vector(K_TYPE_LONG, 0);
idx = (K)list_append_value((V**)idx, (K)i, 0);
*m = (K)list_append_value((V**)*m, idx, 0);
}
V k10_boot_lamb(void) {
runtime_random_lambda = (J)eval_source_or_dispatch(
"{1!?2 sv 0 0;`r}", 0, 0);
runtime_inv_sqrt_lambda = (J)eval_source_or_dispatch(
"{(x-y*y%z)%z}", 0, 0);
runtime_count_dispatch = (J)eval_source_or_dispatch(
":count", 0, 0);
}
V k10_sort_disp(char d, K c, K v, I f) {
K s = v;
if (!k10_tag(v) && XT(v) == K_TYPE_LITERAL_FUNC &&
*((G*)v - 6) == 0 && XN(v) <= 6)
s = (K)ensure_singleton_or_box(v, (J)v, f);
I h = (I)is_homogeneous_list(s, 0, 0, f);
J b;
if (!h || k10_tag(c) || XT(c) != K_TYPE_PAIR_CELL)
b = k10_sort_apply(c, s, f);
else b = 0;
if (K_IS_ERR_RETURN(b)) return b;
char m[16];
I *bt = (I*)cast_to_bool_packed((__int128*)b, m);
if (d & 1) bt = (I*)bitwise_complement_vector((J)bt);
J r = (J)cast_graph_int_tail((J)bt);
return r ? r : (void)bt;
}
J k10_sort_apply(K c, K s, I f) {
(void)f;
I h = (I)leaf_int_value(c);
K_unary_fn fn = (K_unary_fn)apply_functor_atomic;
if (!k10_tag(s) && XT(s) == K_TYPE_LITERAL_FUNC)
fn = (K_unary_fn)apply_functor_atomic;
if (XT(c) == K_TYPE_KEYED_PAIR) c = (K)c[1];
I rd = (I)release_object((V **)s);
return (J)size_match_or_clone(h, (J)fn(retain_object(c)), rd);
}
V k10_sort_cmp(J c, V **l) {
uJ n = (uJ)XN(l);
if (!n) return l;
for (uJ i = 0; i < n; i++) {
J r = sort_then_canonicalize(c, (K)retain_object(l[i]));
if (K_IS_ERR_RETURN(r)) return r;
}
return l;
}
K k10_ban(void) {
write_cstr_stderr("ba\n");
R (K)5;
}
K k10_triple(K p, J t) {
J l = retain_object((J)*p), r = retain_object((J)p[1]);
release_object((V **)p);
K tr = make_triple_J((J)l, (J)r, t);
if (!K_IS_ERR_RETURN(tr)) {
tr = (K)clone_or_recycle_header((V**)tr);
XT(tr) = (char)K_TYPE_KEYED_PAIR;
}
R tr;
}
V k10_pop_last(V **v) {
V **d = clone_or_recycle_header(v);
K i = (K)*d;
*d = (J)reshape_take_recursive(XN(i) - 1, i);
return d;
}
K k10_ins_fn(I v, V *val, K b, V *s) {
K r = b;
if (!K_IS_ERR_RETURN(b)) {
K res;
if (v == 'd')
res = (K)pair_cell_make(K_TYPE_KEYED_PAIR, (J)val, b);
else res = k10_ins_v(v, val, b, s);
r = res;
release_object((V **)s);
}
R r;
}
K k10_ins_v(I v, V *val, K b, V *s) {
S cx = (S)((J *)s)[2];
if (v) {
K_dyadic_left_fn f = (K_dyadic_left_fn)apply_unary_each;
K d = (K)apply_dyadic_left_each(f, (J)cx,
(K)promote_atom_to_singleton((V**)b, 0));
R d;
}
if (XN(b) > 1) R (K)list_first_bytes((V**)b);
R (K)keyed_first((V**)b);
}
K k10_walk_ass(V *a, K k, J v) {
K keys = (K)k[1], o = allocate_typed_vector(K_TYPE_LIST, XN((S)k[2]));
S c = (S)k[2]; J i = 0;
while (1) {
K s;
if (c[i] == 0) s = (K)(leaf_int_value(a) | (0xdULL << K_TAG_SHIFT));
else {
K ky = (K)retain_object((J)keys[i]);
s = (K)resolve_dotted_name(NULL, (uJ*)ky, 0);
release_object((V **)ky);
}
o[i] = (J)s;
if (K_IS_ERR_RETURN(s)) break;
if (++i >= XN(o)) break;
}
R o;
}
I k10_is_homo_k(K v, I f) {
if (!v) R 0;
G o = XT(v);
if (o != 0) R 1;
uI n = XN(v);
if (!n) R 1;
J ft = (J)v[0];
if (k10_tag((K)ft)) R 0;
G t0 = XT(ft);
if ((uI)(t0 - 1) > 0x3e) R 0;
for (uI i = 1; i < n; i++) {
J e = (J)v[i];
if (k10_tag((K)e)) R 0;
G t = XT(e);
if (t != t0 || (uI)(t - 1) > 0x3e) R 0;
}
R 1;
}
K k10_app_2_disp(K f, K l, K r, uJ x, uJ fl) {
for (;;) {
if ((uJ)f > K_BYTE_MAX) {
uI t = k10_tag(f);
if (k10_high(f, t)) return k10_app_2_v(f, l, r);
I ok = l ? list_of_short_function_table(l,0,fl):0;
if ((!l || ok) && same_outer_kind(r, 0, fl))
return k10_sort_pair(retain_object(f), l, fl);
if (t == 0) return (K)sym_lookup_and_apply(f, r, fl);
return (K)3;
}
return k10_app_2_v(f, l, r);
}
}
K k10_app_2_v(K f, K l, K r) {
J a[2] = {(J)l, (J)r};
R (K)verb_byte_apply(f, 2, a);
}
K k10_app_n(K f, I a, J r) {
uJ *b = (uJ*)r;
if ((uJ)f < K_ASCII_SPACE) R (K)3;
uI t = k10_tag(f);
if (!k10_can_run(f, a, r, t)) R f;
if (a == 2) R k10_app_2_disp(f, (K)b[0], (K)b[1], 0, 0);
if ((uJ)f <= K_BYTE_MAX) R k10_app_prim(f, a, b);
if (k10_high(f, t)) R k10_app_high(f, a, b);
R (a == 3) ? k10_app_c3(f, b) : (K)3;
}
I k10_can_run(K f, I a, J r, uI t) {
I i = ((uJ)f < K_HEAP_LOW_ADDR || k10_high(f, t)) && !a;
I s = i ? ((I)apply_at_one_arg(f, a, (uJ)r)) <= a : 0;
R !(((uJ)f >= K_HEAP_LOW_ADDR && t == 0 &&
XT(f) != K_TYPE_LITERAL_FUNC) ||
((uJ)f >= K_HEAP_LOW_ADDR && t != 0 && t <= K_VERB_GROUP_PRIME) || s);
}
K k10_app_prim(K f, I a, uJ *b) {
if (((uJ)f - K_PRINT_TAB_INDEX) > 2 || a > 4) R (K)3;
if (a == 3) {
K_triadic_verb v = (K_triadic_verb)verb_dispatch_primary[(2 + (uJ)f)];
R (K)v(b[0], b[1], b[2]);
}
K_tetradic_verb v = (K_tetradic_verb)verb_dispatch_primary[(uJ)f];
R (K)v(b[0], b[1], b[2], b[3]);
}
K k10_app_high(K f, I a, uJ *b) {
J z[4] = {(J)b[0], (J)b[1], (J)b[2], (J)b[3]};
R (K)verb_byte_apply(f, a, z);
}
K k10_app_c3(K f, uJ *b) {
J k = (J)b[0], v = (J)b[1];
I ok = k ? list_of_short_function_table(k, 0, 0) : 1;
if (!ok) R (K)8;
ok = v ? same_outer_kind(v, 0, 0) : 1;
if (ok && same_outer_kind((K)b[2], 0, 0))
R (K)compile_lambda_resolver(retain_object(f), b[0], b[1], b[2]);
R (K)8;
}
K k10_app_1(K f, I n, J a) {
if (!f || (uJ)f < K_HEAP_LOW_ADDR) R f;
R k10_app_n(f, n, a);
}
uI k10_tag(K x) { R (uI)((uJ)x >> K_TAG_SHIFT); }
I k10_high(K f, uI t) {
R (t == 0 && XT(f) == K_TYPE_LITERAL_FUNC) ||
(t != 0 && t > K_VERB_GROUP_PRIME);
}
K k10_box(J x) { R (K)box_immediate_to_heap(x); }
K k10_sort_pair(K c, K l, I f) {
R (K)sort_then_canonicalize((J)c, (K)l);
}
K k10_bool_inner(J x, S z) {
R cast_to_bool_packed(x, z);
}
J k10_resolve_lambda(V *f, J k, J v, J a) {
if (!f) return a;
retain_object((V *)v);
J p = pair_cell_make(K_TYPE_KEYED_PAIR, (V *)k,
(J *)retain_object(f));
return p ? p : a;
}
J k10_flatten_pair(I v, J *vec) {
V *res = wrap_string_literal((char *)(J)v,
(V **)vec);
return (J)res;
}
J *k10_iter_each(I v, V **vec, uJ n) {
J *out = allocate_typed_vector(K_TYPE_LIST, (I)n);
for (uJ i = 0; i < n; i++) {
J arg = (J)retain_object(vec[i]);
out[i] = verb_byte_apply((J)v, 1, (uJ)&arg);
}
release_object((V **)vec);
return out;
}
J k10_iter_fold(I v, V *base, V **vec, uJ n) {
V *acc = retain_object(base);
for (uJ i = 0; i < n; i++) {
V *e = retain_object(vec[i]);
J pair[2] = { (J)acc, (J)e };
acc = (V *)verb_byte_apply((J)v, 2, (uJ)pair);
}
release_object((V **)vec);
return (J)acc;
}
J *k10_iter_verb(I v, V *b, V **vec) {
if (!vec || (uJ)vec < K_MIN_VALID_HEAP_ADDR)
return (J *)vec;
uJ n = (uJ)*(I *)((char *)vec - 4);
if (!b) return k10_iter_each(v, vec, n);
return (J *)k10_iter_fold(v, b, vec, n);
}
J k10_eq(V **a, V **b) {
uJ ta = (uJ)a >> K_TAG_SHIFT;
uJ wide = (uJ)b >= 0x100000000000000ULL;
if (ta != 0 && wide) {
return generic_compare_dispatch(2, a, b);
}
return generic_compare_dispatch(7, a, b);
}
J k10_cmp_lt(V **a, V **b) {
I eq = (I)tagged_atom_equal((J)a, (J)b);
V **first = eq ? a : b;
V **second = eq ? b : a;
release_object((V **)first);
return (J)second;
}
J k10_cmp_table(I v, V **a, V **b) {
J (*f)(V **, V **, I, J);
f = (v & 1) ? (V *)deep_equal : (V *)generic_atom_lt;
J r = f(a, b, v, 0);
J res = r | (0x8ULL << K_TAG_SHIFT);
release_object((V **)b);
release_object((V **)a);
return res;
}
J k10_cmp(I v, V **a, V **b) {
uI ta = (uI)((J)a >> K_TAG_SHIFT);
uI tb = (uI)((J)b >> K_TAG_SHIFT);
if (ta != tb) {
if ((ta - 8) > K_LOG2_BITS_INDEX_MASK || (tb - 8) > K_LOG2_BITS_INDEX_MASK) {
release_object((V **)a);
return 8;
}
}
if (v > 1) return k10_cmp_table(v, a, b);
return k10_cmp_lt(a, b);
}
V **k10_vec_cmp_eq(I v, J *a, V *rb) {
uI ta = (uI)*(G *)((char *)a - 5);
if ((ta - 8) <= 5) {
I m = (((uJ)rb - 8) <= 5) && ta != K_TYPE_BOOL ?
range_max_long(a) : 0;
if (*(I *)((char *)a - 4) == 0 || m >= (I)(uJ)rb)
return per_tag_compare_helper(v, rb, a);
}
return per_tag_compare_helper(v, a, rb);
}
V **k10_vec_cmp(I v, J *a, uJ b) {
if ((uJ)a < K_MIN_VALID_HEAP_ADDR) return (V **)6;
if (b < K_HEAP_LOW_ADDR) return (V **)6;
V *rb = (V *)b;
if (((J)a >> K_TAG_SHIFT) != 0) {
if (*(G *)((char *)rb - 5) == K_TYPE_PAIR_IMMEDIATE)
rb = expand_pair_immediate((J *)rb);
} else {
if (*(G *)((char *)a - 5) == K_TYPE_PAIR_IMMEDIATE)
a = expand_pair_immediate(a);
if (((J)rb >> K_TAG_SHIFT) != 0 && v == 2)
return k10_vec_cmp_eq(v, a, rb);
}
return per_tag_compare_helper(v, a, rb);
}
J k10_atom_lt_imm(V **a, V **b, uI ta) {
if ((ta - 8) <= 6) {
J pa = (J)((((uJ)(J)a) << 8) >> 8);
J pb = (J)((((uJ)(J)b) << 8) >> 8);
return (J)(pa < pb);
}
if (ta == K_TYPE_FLOAT) {
F pa = *(F *)((uJ)(J)a & K_PTR_MASK);
F pb = *(F *)((uJ)(J)b & K_PTR_MASK);
return (J)(pa < pb);
}
return (J)((uJ)a < (uJ)b);
}
J k10_atom_lt_heap(V **a, V **b) {
G ta = *(G *)((char *)a - 5);
G tb = *(G *)((char *)b - 5);
if (ta == K_TYPE_PAIR_CHAIN &&
tb == K_TYPE_PAIR_CHAIN) {
uI la = (uI)*(I *)((char *)a - 4);
uI lb = (uI)*(I *)((char *)b - 4);
uI c = la < lb ? la : lb;
I cmp = memcmp(a, b, (size_t)c);
return (J)((cmp < 0) || (cmp == 0 && la < lb));
}
return (J)((uJ)a < (uJ)b);
}
J k10_atom_lt(V **a, V **b, I v, J aux) {
(void)v; (void)aux;
uI ta = (uI)((J)a >> K_TAG_SHIFT);
uI tb = (uI)((J)b >> K_TAG_SHIFT);
if (ta == tb && ta != 0)
return k10_atom_lt_imm(a, b, ta);
if (ta == 0 && tb == 0 && (uJ)a >= K_HEAP_LOW_ADDR &&
(uJ)b >= K_HEAP_LOW_ADDR)
return k10_atom_lt_heap(a, b);
return (J)((uJ)a < (uJ)b);
}
V **k10_tag_cmp(I v, V *a, V *b) {
if (!a || !b) return (V **)b;
switch (v) {
case 1: return (V **)generic_atom_lt((V **)a,
(V **)b, v, 0);
case 2: return (V **)deep_equal((V **)a,
(V **)b, 0, 0);
case 4: return (V **)generic_atom_lt((V **)b,
(V **)a, v, 0);
case 7: return (V **)deep_equal((V **)a,
(V **)b, 0, 0);
default: return (V **)b;
}
}
I k10_max_long(V *v) {
return (I)max_long_vector(v, 0, 0, K_TYPE_LONG);
}
V k10_fill_pos(J *out, V **cnts, uJ n) {
J *w = out;
for (uJ b = 0; b < n; b++) {
uJ c = (uJ)*(I *)((char *)cnts + (b << 2));
while (c--) {
*(I *)w = (I)b;
w = (J *)((char *)w + 4);
}
}
}
J *k10_bucket_pos(I total, V **cnts) {
J *out = allocate_typed_vector(K_TYPE_INT, total);
if (*(I *)((char *)out - 4) >= 2)
*(int8_t *)((char *)out - 6) = 3;
uJ n = (uJ)*(I *)((char *)cnts - 4);
if (n != 0) k10_fill_pos(out, cnts, n);
release_object((V **)cnts);
return out;
}
J *k10_bucket_cnt_small(J *out, V *v, I nb) {
uJ n = (uJ)*(I *)((char *)out - 4);
for (uJ b = 0; b < n; b++) {
V *m = cast_to_char_or_bool((I)b,
(V **)retain_object(v));
I pc = popcount_bool_vec(m);
release_object((V **)m);
((I *)out)[b] = pc;
}
return out;
}
V k10_bucket_cnt_loop(J *out, V *v, uJ n) {
G t = *(G *)((char *)v - 5);
for (uJ i = 0; i < n; i++) {
uJ b;
if ((K_TAGCLASS_INT32_LANE >> t) & 1)
b = (uJ)((I *)v)[i];
else if (t != K_TYPE_SHORT)
b = (uJ)((G *)v)[i];
else b = (uJ)((I16 *)v)[i];
((I *)out)[b]++;
}
}
J *k10_bucket_cnt(I nb, V *v) {
J *out = allocate_zero_filled_typed(K_TYPE_INT, nb);
G t = *(G *)((char *)v - 5);
I is_bb = (t == 1 || t == K_TYPE_BOOL);
if (nb <= 0x10 && is_bb)
return k10_bucket_cnt_small(out, v, nb);
uJ n = (uJ)*(I *)((char *)v - 4);
if (n != 0) k10_bucket_cnt_loop(out, v, n);
return out;
}
V k10_bool_mask_loop(J *out, V **v, I n, I target) {
G t = *(G *)((char *)v - 5);
for (I i = 0; i < n; i++) {
uJ c;
if ((K_TAGCLASS_INT32_LANE >> t) & 1)
c = (uJ)((I *)v)[i];
else if (t != K_TYPE_SHORT)
c = (uJ)((G *)v)[i];
else c = (uJ)((I16 *)v)[i];
if (c == (uJ)(uI)target) ((char *)out)[i] = 1;
}
}
V **k10_bool_mask(I target, V **v) {
I n = *(I *)((char *)v - 4);
J *out = allocate_zero_filled_typed(K_TYPE_BOOL, n);
k10_bool_mask_loop(out, v, n, target);
G t = *(G *)((char *)v - 5);
char m[16];
V *p = cast_to_bool_packed((__int128 *)out, m);
V *g = (V *)cast_graph_int_tail((J)p);
V **res = (V **)cast_to_tag((V *)(uJ)t,
(__int128 *)g);
release_object((V **)v);
return res;
}
V **k10_recast(I a1, V **v) {
G t = *(G *)((char *)v - 5);
I n = *(I *)((char *)v - 4);
J *cnt = k10_bucket_cnt(a1, v);
J *pos = k10_bucket_pos(n, (V **)cnt);
V **res = (V **)cast_to_tag((V *)(uJ)t,
(__int128 *)pos);
release_object((V **)v);
return res;
}
J k10_is_canonical_list(J *a) {
V *head = (V *)*a;
I n = *(I *)((char *)a - 4);
for (I i = 0; i < n; i++) {
V *c = (V *)a[i];
if (((J)c >> K_TAG_SHIFT) != 0) return 0;
uI ct = (uI)*(G *)((char *)c - 5);
if ((ct - 1) > 0x3e) return 0;
if (*(G *)((char *)head - 5) != ct) return 0;
}
return 1;
}
J k10_is_canonical(J *a, I flags) {
G h = *(G *)((char *)a - 5);
if (h == 0) return k10_is_canonical_list(a);
uJ tag = (uJ)a >> K_TAG_SHIFT;
return (tag == (uJ)(flags - flags)) && (h-1 < 0x3f);
}
uJ k10_hash_lookup(V *v, J k, I f) {
uJ p = ((uJ)k) & K_PAYLOAD_BITS_48;
V *d;
if (p < K_SYM_INDEX_CUTOFF) {
if (runtime_sym_table_charvecs && (I)p >= 0)
d = (V *)runtime_sym_table_charvecs[(I)p];
else d = (V *)p;
} else d = (V *)*(J *)p;
I pos = (I)linear_lookup_raw(v, (V **)d, f);
I res = 0;
if (*(I *)((char *)v - 4) > pos) res = pos + 1;
return (uJ)res;
}
I k10_compare_raw_elem(V *v, uJ i, uJ h, V **t) {
uJ c;
if ((K_TAGCLASS_ATOMIC_BOX >> h) & 1)
c = (uJ)((J *)v)[i];
else if ((K_TAGCLASS_INT32_LANE >> h) & 1)
c = (uJ)((I *)v)[i];
else if (h == K_TYPE_SHORT)
c = (uJ)((I16 *)v)[i];
else c = (uJ)((G *)v)[i];
return c == (uJ)(uintptr_t)t;
}
uJ k10_linear_lookup_loop(V *v, V **t, I f, uJ h) {
uJ n = (uJ)*(I *)((char *)v - 4);
if (n == 0) return 0;
for (uJ i = 0; i < n; i++) {
if (h == 0) {
V *c = (V *)((J *)v)[i];
if (deep_equal((V **)c, t, f, h)) return i;
} else {
if (k10_compare_raw_elem(v, i, h, t)) return i;
}
}
return n;
}
uJ k10_linear_lookup(V *v, V **t, I f) {
if (!v || (uJ)v < K_MIN_VALID_HEAP_ADDR) return 0;
uJ h = (uJ)*(G *)((char *)v - 5);
if (h == K_TYPE_PAIR_CHAIN || h == 1) {
I n = *(I *)((char *)v - 4);
V *hit = memchr(v, (I)(uJ)t, n);
return hit ? (uJ)((char *)hit - (char *)v) : n;
}
return k10_linear_lookup_loop(v, t, f, h);
}
J k10_unary_pair(K_unary_atom_fn f, J *p) {
J *v = (J *)retain_object((V *)p[1]);
V *l = retain_object((V *)*p);
release_object((V **)(V **)p);
V *h = retain_object((V *)*v);
release_object((V **)(V **)v);
J res = f((J)h);
V *pair = pair_cell_make(K_TYPE_PAIR_CELL, (J)l,
make_singleton_J(res));
return (J)pair;
}
J k10_bin_search(K_dyadic_left_fn c, I lo, I hi,
__int128 *v) {
if (lo <= hi) return c((J)lo, (J)hi);
J r = c((J)hi, (J)cast_to_int_typed(lo, v));
return (J)cast_to_typed_inner_helper(lo,
(__int128 *)r);
}
V k10_prefix_sum(J *c, uJ n) {
I r = 0;
for (uJ i = 0; i < n; i++) {
I cur = ((I *)c)[i] + r;
((I *)c)[i] = r;
r = cur;
}
}
V k10_fill_perm(J *p, V **v, J *c, I total) {
for (uJ i = 0; i < (uJ)total; i++) {
G t = *(G *)((char *)v - 5);
uJ b;
if ((K_TAGCLASS_INT32_LANE >> t) & 1)
b = (uJ)((I *)v)[i];
else if (t != K_TYPE_SHORT)
b = (uJ)((G *)v)[i];
else b = (uJ)((I16 *)v)[i];
uJ pos = (uJ)((I *)c)[b];
((I *)c)[b] = (I)(pos + 1);
((I *)p)[pos] = (I)i;
}
}
J *k10_permute_bucket(I nb, V **v) {
J *cnts = k10_bucket_cnt(nb, v);
uJ n = (uJ)*(I *)((char *)cnts - 4);
if (n != 0) k10_prefix_sum(cnts, n);
I total = *(I *)((char *)v - 4);
J *perm = allocate_typed_vector(K_TYPE_INT, total);
if (total != 0) k10_fill_perm(perm, v, cnts, total);
release_object((V **)(V **)cnts);
return perm;
}
J *k10_resolve_dotted(V ***a1, V ***a2, J d) {
J *out = (J *)a2;
G t = *(G *)((char *)a1 - 5);
J tag = (J)a1 >> K_TAG_SHIFT;
if (tag == 0 && t == 1) {
out = (J *)namespace_step_apply((V *)a1,
(V *)a2);
} else if (tag == 0 && t == K_TYPE_LITERAL_FUNC) {
J args = (J)a2;
out = (J *)apply_n_args((J *)a1, 1, (uJ)&args);
}
(void)d;
return out;
}
V **k10_resolve_promote(V **a1, J *a2, I a3, I f) {
J *r = k10_resolve_dotted((V ***)a1,
(V ***)a2, a3);
return canonicalize_for_send((V **)r, 0, 0, f);
}
J *k10_cast_off(I tag, __int128 *v) {
J *c = (J *)cast_to_tag((V *)(uJ)tag, v);
return vector_add_constant(0, (__int128 *)c);
}
J *k10_vec_add_c(J off, __int128 *v) {
(void)off;
return (J *)((char *)v + 0);
}
J k10_ns_step(V *s, V *n) {
return (J)dictionary_lookup((J *)n,
(uJ *)s, 0);
}
V k10_not_lane(V **out, uJ o) {
*(__int128 *)((char *)out + o) ^= ~(__int128)0;
*(__int128 *)((char *)out + o + 0x10) ^=
~(__int128)0;
}
V **k10_not_vec(V **v) {
V **out = clone_or_recycle_header(v);
G t = *(G *)((char *)out - 5);
uJ cls = (uJ)k_type_cast_gradient_table[t];
I n = *(I *)((char *)out - 4);
uJ b = ((((uJ)n << cls) + 7) >> 3);
uJ l = (b + 0x1f) >> 5;
for (uJ o = 0; o != l << 5; o += K_AVX2_STRIDE_BYTES) {
k10_not_lane(out, o);
}
return out;
}
V k10_neg_f(V **dst, __int128 *src) {
uJ count = (uJ)((((uJ)*(I *)((char *)dst - 4)) + 7) >> 3);
uJ bytes = count << 5;
__int128 sign_bits = *(__int128 *)ieee_f64_sign_lane;
for (uJ off = 0; off != bytes; off += K_AVX2_STRIDE_BYTES) {
*(__int128 *)((char *)dst + off) =
*(__int128 *)((char *)src + off) ^ sign_bits;
*(__int128 *)((char *)dst + off + 0x10) =
*(__int128 *)((char *)src + off + 0x10) ^ sign_bits;
}
}
V k10_neg_i(V **dst, __int128 *src) {
uJ count = (uJ)((((uJ)*(I *)((char *)dst - 4)) + 3) >> 2);
uJ bytes = count << 5;
for (uJ off = 0; off != bytes; off += K_AVX2_STRIDE_BYTES) {
__int128 a = *(__int128 *)((char *)src + off);
__int128 c = *(__int128 *)((char *)src + off + 0x10);
*(__int128 *)((char *)dst + off) = 0 - a;
*(__int128 *)((char *)dst + off + 0x10) = 0 - c;
}
}
V **k10_neg(__int128 *v) {
uI tag = (uI)*(G *)((char *)v - 5);
if ((tag - 8) > K_LOG2_BITS_INDEX_MASK) return (V **)(uintptr_t)K_TYPE_BOOL;
__int128 *src = v;
if (tag <= 0x29) {
src = (__int128 *)cast_to_tag(
(V *)(uJ)K_TYPE_LONG, src);
}
V **dst = (V **)clone_or_recycle_full(src);
uI elem_tag = (uI)*(G *)((char *)src - 5);
if (elem_tag == K_TYPE_F64_VEC) k10_neg_f(dst, src);
else k10_neg_i(dst, src);
release_object((V **)(V **)src);
return dst;
}
J k10_pop_word(char *d, V *b, J off) {
uJ word_count = (uJ)((*(I *)(d - 4) + 7) >> 3);
if (word_count == 0) return 0;
for (uJ i = 0; i < word_count; i++) {
I n = *(I *)((char *)b - 4);
I res = 0;
for (uJ j = 0; j < 8; j++) {
uJ idx = (uJ)*(I *)(off + (j << 2));
if ((uJ)n > idx) {
uJ w = ((uJ *)b)[idx >> 6];
if ((w >> (idx & 63)) & 1) res |= (1 << j);
}
}
d[i] = (char)res;
off += K_AVX2_STRIDE_BYTES;
}
return 0;
}
V k10_f2i_scan(__int128 *d, __int128 *s) {
I n = *(I *)((char *)d - 4);
uJ l = (uJ)((((uJ)n) + 7) >> 3);
if (l == 0) return;
for (uJ o = 0; o != l << 5; o += K_AVX2_STRIDE_BYTES) {
float *sf = (float *)((char *)s + o);
I *di = (I *)((char *)d + o);
for (I i = 0; i < 8; i++) di[i] = (I)sf[i];
}
}
V k10_tr_d_scan(__int128 *d, J sa) {
I n = *(I *)((char *)d - 4);
uJ l = (uJ)((((uJ)n) + 3) >> 2);
if (l == 0) return;
for (uJ o = 0; o != l << 4; o += 0x10) {
F *p = (F *)(sa + (o << 1));
I *oi = (I *)((char *)d + o);
oi[0] = (I)p[0];
oi[1] = (I)p[1];
p = (F *)(sa + (o << 1) + 0x10);
oi[2] = (I)p[0];
oi[3] = (I)p[1];
}
}
V k10_tr_f_scan(V *d, __int128 *s) {
I n = *(I *)((char *)d - 4);
uJ l = (uJ)((((uJ)n) + 3) >> 2);
if (l == 0) return;
for (uJ o = 0; o != l << 4; o += 0x10) {
float *p = (float *)((char *)s + o);
I *oi = (I *)((char *)d + (o << 1));
I *oi2 = (I *)((char *)d + (o << 1) + 0x10);
oi[0] = (I)p[0];
oi[1] = (I)p[1];
oi2[0] = (I)p[2];
oi2[1] = (I)p[3];
}
}
I k10_popcount(uJ w) {
return __builtin_popcountll(w);
}
V k10_cb_p_c4(I *d, I *s) {
I n = d[-1];
uJ l = (uJ)((n + 0xf) >> 4);
for (uJ i = 0; i < l; i++) {
I16 m = 0;
for (I j = 0; j < 16 && (i*16+j) < (uJ)n; j++) {
if (((I16 *)s)[i*16+j]) m |= (1 << j);
}
((I16 *)d)[i] = m;
}
}
V k10_cb_p_def(I *d, I *s) {
I n = d[-1];
uJ l = (uJ)((n + 7) >> 3);
for (uJ i = 0; i < l; i++) {
G b = 0;
for (I j = 0; j < 8 && (i*8+j) < (uJ)n; j++) {
if (((I *)s)[i*8+j]) b |= (1 << j);
}
((G *)d)[i] = b;
}
}
V k10_cb_p_c3(I *d, I *s) {
I n = d[-1];
uJ l = (uJ)((n + 0x1f) >> 5);
for (uJ i = 0; i < l; i++) {
uI m = 0;
for (I j = 0; j < 32 && (i*32+j) < (uJ)n; j++) {
if (((G *)s)[i*32+j]) m |= (1u << j);
}
((uI *)d)[i] = m;
}
}
I *k10_cast_bool_vec(I *s, G h) {
I *d = (I *)allocate_typed_vector(K_TYPE_BOOL, s[-1]);
uJ c = (uJ)k_type_dyadic_index_table[h];
if (c == 4) k10_cb_p_c4(d, s);
else if (c != 3) k10_cb_p_def(d, s);
else k10_cb_p_c3(d, s);
release_object((V **)(V **)s);
return d;
}
I *k10_cast_bool_p(I *s, char z[16]) {
G h = *(G *)((char *)s - 5);
if (h == 1 || h == K_TYPE_BOOL) return s;
if (!((K_TAGCLASS_HEAP_BOXED >> h) & 1)) {
return k10_cast_bool_vec(s, h);
}
(void)z;
return (I *)bitwise_complement_in_place((V **)s);
}
V *k10_zero1(I t) {
uJ tag = (uJ)(uI)t;
if ((K_TAGCLASS_PAIR_PAYLOAD >> tag) & 1)
return (V *)box_pair_payload((I)tag, (__int128)0);
if ((K_TAGCLASS_ATOMIC_BOX >> tag) & 1)
return (V *)box_atom((I)tag, 0);
return (V *)(tag << K_TAG_SHIFT);
}
J k10_min_red_byte(V *v, uJ n, G h) {
G *p = (G *)v;
I res = (n != 0) ? p[0] : 0xff;
for (uJ i = 1; i < n; i++)
if (p[i] < res) res = p[i];
return ((uJ)res) | ((uJ)h << K_TAG_SHIFT);
}
J k10_min_red_short(V *v, uJ n, G h) {
I16 *p = (I16 *)v;
I res = (n != 0) ? p[0] : 0;
for (uJ i = 1; i < n; i++)
if (p[i] < res) res = p[i];
return ((uJ)(uint16_t)res) | ((uJ)h << K_TAG_SHIFT);
}
J k10_min_red_int(V *v, uJ n, G h) {
I *p = (I *)v;
I res = (n != 0) ? p[0] : 0;
for (uJ i = 1; i < n; i++)
if (p[i] < res) res = p[i];
return ((uJ)(uI)res) | ((uJ)h << K_TAG_SHIFT);
}
J k10_min_red_long(V *v, uJ n, G h) {
J *p = (J *)v;
J res = (n != 0) ? p[0] : INT64_MAX;
for (uJ i = 1; i < n; i++)
if (p[i] < res) res = p[i];
return ((uJ)res) | ((uJ)h << K_TAG_SHIFT);
}
J k10_min_red(V *v) {
G h = *(G *)((char *)v - 5);
uJ n = (uJ)*(I *)((char *)v - 4);
if (h == 1 || h == K_TYPE_PAIR_CHAIN)
return k10_min_red_byte(v, n, h);
if (h == K_TYPE_SHORT)
return k10_min_red_short(v, n, h);
if (h == K_TYPE_INT)
return k10_min_red_int(v, n, h);
if (h == K_TYPE_LONG)
return k10_min_red_long(v, n, h);
return 0;
}
J k10_max_red_byte(V *v, uJ n, G h) {
G *p = (G *)v;
I res = (n != 0) ? p[0] : 0;
for (uJ i = 1; i < n; i++)
if (p[i] > res) res = p[i];
return ((uJ)res) | ((uJ)h << K_TAG_SHIFT);
}
J k10_max_red_short(V *v, uJ n, G h) {
I16 *p = (I16 *)v;
I res = (n != 0) ? p[0] : 0;
for (uJ i = 1; i < n; i++)
if (p[i] > res) res = p[i];
return ((uJ)(uint16_t)res) | ((uJ)h << K_TAG_SHIFT);
}
J k10_max_red_int(V *v, uJ n, G h) {
I *p = (I *)v;
I res = (n != 0) ? p[0] : 0;
for (uJ i = 1; i < n; i++)
if (p[i] > res) res = p[i];
return ((uJ)(uI)res) | ((uJ)h << K_TAG_SHIFT);
}
J k10_max_red_long(V *v, uJ n, G h) {
J *p = (J *)v;
J res = (n != 0) ? p[0] : INT64_MIN;
for (uJ i = 1; i < n; i++)
if (p[i] > res) res = p[i];
return ((uJ)res) | ((uJ)h << K_TAG_SHIFT);
}
J k10_max_red(V *v) {
G h = *(G *)((char *)v - 5);
uJ n = (uJ)*(I *)((char *)v - 4);
if (h == 1 || h == K_TYPE_PAIR_CHAIN)
return k10_max_red_byte(v, n, h);
if (h == K_TYPE_SHORT)
return k10_max_red_short(v, n, h);
if (h == K_TYPE_INT)
return k10_max_red_int(v, n, h);
if (h == K_TYPE_LONG)
return k10_max_red_long(v, n, h);
return 0;
}
J k10_sum_red_f(V *v, uJ n, G h) {
F *p = (F *)v;
F s = 0.0;
for (uJ i = 0; i < n; i++) s += p[i];
union { F d; J l; } u; u.d = s;
return u.l | ((uJ)h << K_TAG_SHIFT);
}
J k10_sum_red_l(V *v, uJ n) {
J *p = (J *)v;
J s = 0;
for (uJ i = 0; i < n; i++) s += p[i];
return s;
}
J k10_sum_red_i(V *v, uJ n) {
I *p = (I *)v;
J s = 0;
for (uJ i = 0; i < n; i++) s += (J)p[i];
return s;
}
J k10_sum_red_s(V *v, uJ n) {
I16 *p = (I16 *)v;
J s = 0;
for (uJ i = 0; i < n; i++) s += (J)p[i];
return s;
}
J k10_sum_red_b(V *v, uJ n) {
G *p = (G *)v;
J s = 0;
for (uJ i = 0; i < n; i++) s += (J)p[i];
return s;
}
J k10_sum_red(V *v) {
G h = *(G *)((char *)v - 5);
uJ n = (uJ)*(I *)((char *)v - 4);
if (h == K_TYPE_FLOAT) return k10_sum_red_f(v, n, h);
J s = 0;
if (h == K_TYPE_LONG) s = k10_sum_red_l(v, n);
else if (h == K_TYPE_INT) s = k10_sum_red_i(v, n);
else if (h == K_TYPE_SHORT) s = k10_sum_red_s(v, n);
else if (h == 1 || h == K_TYPE_PAIR_CHAIN)
s = k10_sum_red_b(v, n);
return s | ((uJ)K_TYPE_LONG << K_TAG_SHIFT);
}
J k10_cast_seeded(I tag, J *vec) {
J seed = (uJ)tag |
0x100000000000000ULL;
V **s = (V **)seed;
return (J)pair_or_collapse_dyadic(9,
s, vec);
}
J *k10_unique_list(J *arg) {
I n = *(I *)((char *)arg - 4);
J *out = allocate_typed_vector(K_TYPE_PAIR_CHAIN, n);
for (J i = 0; i < n; i++) {
char eq = 0;
if (i != 0) {
eq = (char)deep_equal((V **)arg[i],
(V **)arg[i - 1], 0, 0);
}
((char *)out)[i] = eq;
}
V *t = (V *)(uintptr_t)K_TYPE_BOOL;
return (J *)cast_to_tag(t, (__int128 *)out);
}
J *k10_unique_pair(J *arg) {
J *items = (J *)arg[1];
uI len = *(I *)((char *)items - 4);
if (len > 3) len = 3;
J *cur = arg;
for (uJ i = 0; i < len; i++) {
J *val = (J *)((char *)items + (i << 3));
J *next = k10_unique_mask(*(J **)val);
cur = (i == 0) ? next : (J *)
pair_or_collapse_dyadic(5, (V **)cur,
next);
}
return cur;
}
J *k10_unique_mask(J *arg) {
G hdr = *(G *)((char *)arg - 5);
if (hdr == 0) return k10_unique_list(arg);
if (hdr == K_TYPE_PAIR_CELL)
return k10_unique_pair(arg);
if (hdr != K_TYPE_PAIR_IMMEDIATE) {
V *dup = retain_object(arg);
V *p = permute_by_bucket_count(0,
(V **)arg);
J *next = (J *)pair_or_collapse_dyadic(
9, (V **)dup, (J *)p);
*(int8_t *)next &= 0xfe;
return next;
}
return (J *)5;
}
V *k10_rotate_pair(V *arg, I flags) {
uI tag = (uI)((J)arg >> K_TAG_SHIFT);
if (tag == 0) {
G hdr = *(G *)((char *)arg - 5);
if ((int8_t)(hdr + 3) < 2) {
V *right = retain_object((V *)((J *)arg)[1]);
V *left = retain_object((V *)*(J *)arg);
release_object((V **)arg);
return pair_cell_make((I)hdr,
(J)left, (J *)
k10_rotate_pair(right, flags));
}
}
return unwrap_pair_chain_inner(arg, flags);
}
V *unwrap_pair_chain_inner(V *vec,
I flags) { (void)flags; return vec; }
J *k10_negate_vec(__int128 *vec, I flag) {
V **dst = clone_or_recycle_full(vec);
I n = *(I *)((char *)dst - 4);
uJ lanes = (uJ)((n + 3) >> 2);
uJ bytes = lanes << 5;
for (uJ off = 0; off < bytes; off += K_AVX2_STRIDE_BYTES) {
__int128 *a = (__int128 *)((char *)vec + off);
__int128 *b = (__int128 *)((char *)dst + off);
b[0] = -a[0];
b[1] = -a[1];
}
release_object((V **)vec);
(void)flag;
return (J *)dst;
}
uJ k10_min_bool(V *vec, J aux) {
(void)aux;
I n = *(I *)((char *)vec - 4);
uJ nw = (n + 63) >> 6;
for (uJ i = 0; i < nw; i++) {
uJ mask = (i + 1 == nw) ?
((1ULL << (n & 63)) - 1) : ~0ULL;
if (mask == 0) mask = ~0ULL;
if ((((uJ *)vec)[i] & mask) != mask)
return 0;
}
return 1;
}
uJ k10_min_any(char *vec) {
G hdr = (G)vec[-5];
if (hdr == K_TYPE_BOOL) return 0;
if (hdr == K_TYPE_SHORT)
return k10_min_short(vec);
if ((K_TAGCLASS_INT32_LANE >> hdr) & 1)
return k10_min_int(vec);
return k10_min_byte(vec);
}
uJ k10_min_short(char *vec) {
I16 *p = (I16 *)vec;
I n = *(I *)(vec - 4);
if (n == 0) return 0xffffffffULL;
if (vec[-6] >= 2) return (uJ)*p;
I16 m = p[0];
for (I i = 1; i < n; i++)
if (p[i] < m) m = p[i];
return (uJ)(uint16_t)m;
}
uJ k10_min_int(char *vec) {
I *p = (I *)vec;
I n = *(I *)(vec - 4);
if (n == 0) return 0xffffffffULL;
if (vec[-6] >= 2) return (uJ)*p;
I m = p[0];
for (I i = 1; i < n; i++)
if (p[i] < m) m = p[i];
return (uJ)(uI)m;
}
uJ k10_min_byte(char *vec) {
G *p = (G *)vec;
I n = *(I *)(vec - 4);
if (n == 0) return 0xffffffffULL;
G m = p[0];
for (I i = 1; i < n; i++)
if (p[i] < m) m = p[i];
return (uJ)m;
}
uJ k10_max_long_u(V *vec) {
J *p = (J *)vec;
I n = *(I *)((char *)vec - 4);
if (n == 0) return 0;
char s = *(int8_t *)((char *)vec - 6);
return (uJ)k10_scan_max_long(p, n, s >= 2);
}
J k10_scan_max_long(J *p, I n, I s) {
if (s) return p[n - 1];
J m = p[0];
for (I i = 1; i < n; i++)
if (p[i] > m) m = p[i];
return m;
}
J k10_scan_min_long(J *p, I n, I s) {
if (s) return p[0];
J m = p[0];
for (I i = 1; i < n; i++)
if (p[i] < m) m = p[i];
return m;
}
J k10_min_signed_long(V *vec) {
J *p = (J *)vec;
I n = *(I *)((char *)vec - 4);
if (n == 0) return INT64_MAX;
char s = *(int8_t *)((char *)vec - 6);
return k10_scan_min_long(p, n, s >= 2);
}
J k10_max_signed_long(V *vec) {
J *p = (J *)vec;
I n = *(I *)((char *)vec - 4);
if (n == 0) return INT64_MIN;
char s = *(int8_t *)((char *)vec - 6);
return k10_scan_max_long(p, n, s >= 2);
}
I k10_count_set_bits(V *vec) {
uJ *p = (uJ *)vec;
I n = *(I *)((char *)vec - 4);
uJ nw = (n + 63) >> 6;
I total = 0;
for (uJ i = 0; i < nw; i++) {
uJ m = (i + 1 == nw) ?
((1ULL << (n & 63)) - 1) : ~0ULL;
if ((n & 63) == 0 && i + 1 == nw) m = ~0ULL;
total += __builtin_popcountll(p[i] & m);
}
return total;
}
static I k10_bool_sorted(J *vec) {
I n = k10_count_set_bits(vec);
I total = *(I *)((char *)vec - 4);
return (n == total) ? 1 : 0;
}
static I k10_probe_sorted(G hdr, J *vec) {
if (hdr == 0) return k10_is_sorted_list(vec);
if (hdr == K_TYPE_BOOL) return k10_bool_sorted(vec);
if ((hdr - 2) >= 6) return k10_is_sorted_long(vec);
if (hdr != K_TYPE_F64_VEC && (hdr & K_BYTE_HIGH_BIT_MASK) != K_TYPE_F64_VEC &&
hdr != 1 && hdr != K_TYPE_PAIR_CHAIN) {
if (hdr == K_TYPE_SHORT)
return k10_is_sorted_short((I16 *)vec);
return k10_is_sorted_int((I *)vec);
}
if ((K_TAGCLASS_PAIR_PAYLOAD >> hdr) & 1)
return k10_is_sorted_float((__int128 *)vec);
return k10_is_sorted_byte((G *)vec);
}
static V k10_mark_unique(J *v) {
J *bools = k10_unique_mask(v);
I pop = k10_count_set_bits(bools);
if (pop == 0) *(int8_t *)((char *)v - 6) += 1;
release_object((V **)bools);
}
J *k10_canonicalize(J *v, J a, uJ f) {
(void)a; (void)f;
I n = *(I *)((char *)v - 4);
if (n < 2 || *(G *)((char *)v - 6) != 0) return v;
G hdr = *(G *)((char *)v - 5);
I p = k10_probe_sorted(hdr, v);
*(int8_t *)((char *)v - 6) = (int8_t)(p + 1);
if (p + 1 >= 3) k10_mark_unique(v);
return v;
}
uJ k10_bool_sorted_type(V *vec) {
I pop = k10_count_set_bits(vec);
if (pop == 0) return 1;
I n = *(I *)((char *)vec - 4);
uJ nw = (n + 63) >> 6;
uJ first = (uJ)n;
for (uJ i = 0; i < nw; i++) {
uJ word = ((uJ *)vec)[i];
if (word != 0) {
first = (uJ)__builtin_ctzll(word) | (i<<6);
if (first > (uJ)n) first = (uJ)n;
break;
}
}
return (first == (uJ)pop) ? 2 : 1;
}
I k10_is_sorted_list(J *vec) {
I n = *(I *)((char *)vec - 4);
for (I i = 0; i < n - 1; i++) {
if (k10_lt_gen((J *)vec[i + 1],
(J *)vec[i]) > 0) return 0;
}
return 1;
}
I k10_lt_gen(J *a, J *b) {
return ((uintptr_t)a < (uintptr_t)b) ? 1 : 0;
}
I k10_is_sorted_long(J *vec) {
I n = *(I *)((char *)vec - 4);
for (I i = 1; i < n; i++) {
if (vec[i] < vec[i - 1]) return 0;
}
return 1;
}
I k10_is_sorted_int(I *vec) {
I n = *(I *)((char *)vec - 4);
for (I i = 1; i < n; i++) {
if (vec[i] < vec[i - 1]) return 0;
}
return 1;
}
I k10_is_sorted_short(I16 *vec) {
I n = *(I *)((char *)vec - 4);
for (I i = 1; i < n; i++) {
if (vec[i] < vec[i - 1]) return 0;
}
return 1;
}
I k10_is_sorted_byte(G *vec) {
I n = *(I *)((char *)vec - 4);
for (I i = 1; i < n; i++) {
if (vec[i] < vec[i - 1]) return 0;
}
return 1;
}
I k10_is_sorted_float(__int128 *vec) {
if (vec == NULL) return 0;
I n = *(I *)((char *)vec - 4);
if (n < 2) return 1;
const F *p = (const F *)vec;
for (I i = 1; i < n; i++) {
if (!(p[i - 1] <= p[i])) return 0;
}
return 1;
}
uJ k10_max_int(V *vec) {
I *p = (I *)vec;
I n = *(I *)((char *)vec - 4);
if (n == 0) return 0;
if (*(int8_t *)((char *)vec - 6) >= 2)
return (uJ)(uI)p[n - 1];
I m = p[0];
for (I i = 1; i < n; i++)
if (p[i] > m) m = p[i];
return (uJ)(uI)m;
}
uJ k10_max_short(V *vec) {
I16 *p = (I16 *)vec;
I n = *(I *)((char *)vec - 4);
if (n == 0) return 0;
if (*(int8_t *)((char *)vec - 6) >= 2)
return (uJ)(uint16_t)p[n - 1];
I16 m = p[0];
for (I i = 1; i < n; i++)
if (p[i] > m) m = p[i];
return (uJ)(uint16_t)m;
}
uJ k10_max_byte(V *vec) {
G *p = (G *)vec;
I n = *(I *)((char *)vec - 4);
if (n == 0) return 0xffffULL;
G m = p[0];
for (I i = 1; i < n; i++)
if (p[i] > m) m = p[i];
return (uJ)m;
}
uJ k10_sym_intern(I b, J k,
I (*s)[4]) {
(void)s;
uJ hit = k10_sym_lookup(b, k);
if (hit != 0) return hit;
return 0;
}
uJ k10_sym_lookup(I b, J k) {
if (!runtime_root_namespace_anchor) return 0;
J *root = (J *)runtime_root_namespace_anchor;
if (*(G *)((char *)root - 5) !=
K_TYPE_KEYED_PAIR) return 0;
J *keys = (J *)*root;
uJ idx = (uJ)b;
if (idx >= *(I *)((char *)keys - 4))
return 0;
J *bk = (J *)keys[idx];
I n = *(I *)((char *)bk - 4);
for (I i = 0; i < n; i++)
if (bk[i] == k) return i + 1;
return 0;
}
J k10_get_val(V **vec, I i, I w) {
if (w == 0) return (((G *)vec)[i >> 3]
>> (i & 7)) & 1;
if (w == 3) return ((char *)vec)[i];
if (w == 4) return ((I16 *)vec)[i];
if (w == 5) return ((I *)vec)[i];
if (w == 6) return ((J *)vec)[i];
return 0;
}
V k10_set_val(V **vec, I i, I w,
J v) {
if (w == 0) {
if (v) ((uJ *)vec)[i >> 6] |= (1ULL << (i&63));
else ((uJ *)vec)[i >> 6] &= ~(1ULL << (i&63));
} else if (w == 3) ((char *)vec)[i] = (char)v;
else if (w == 4) ((I16 *)vec)[i] = (I16)v;
else if (w == 5) ((I *)vec)[i] = (I)v;
else if (w == 6) ((J *)vec)[i] = v;
}
static V **k10_cast_copy(I n, G tgt,
V **vec, G src) {
V **out = allocate_typed_vector((I)tgt, n);
I sw = k_type_log2_bits_table_alias[src];
I dw = k_type_log2_bits_table_alias[tgt];
for (I i = 0; i < n; i++) {
J v = k10_get_val(vec, i, sw);
k10_set_val(out, i, dw, v);
}
release_object((V **)vec);
return out;
}
V **k10_cast_class(V *tgt, V **vec, G hdr) {
uI t = (uI)(uintptr_t)tgt;
G w_cl = k_type_cast_gradient_table[t];
if (w_cl == k_type_cast_gradient_table[hdr]) {
if (K_IS_ERR_RETURN(vec)) return vec;
V **dup = clone_or_recycle_header(vec);
*(G *)((char *)dup - 5) = (G)t;
return dup;
}
return k10_cast_copy(*(I *)((char *)vec - 4),
(G)t, vec, hdr);
}
static V **k10_cast_grad_path(V *t, V **v,
uI w, G h) {
while (1) {
if (w <= h) h = (G)w;
if (h > 0xc) return cast_to_tag(t, (__int128 *)v);
v = cast_to_tag((V *)(uintptr_t)K_TYPE_INT,
(__int128 *)v);
h = *(G *)((char *)v - 5);
if (h == (uintptr_t)t) return v;
if (w < 0x2a && h < 0x2a) break;
}
return k10_cast_class(t, v, h);
}
V **k10_cast_inner(V *tgt, V **vec) {
G hdr = *(G *)((char *)vec - 5);
if (hdr == (uintptr_t)tgt) return vec;
uI want = (uI)(uintptr_t)tgt;
if (want >= 0x2a || hdr >= 0x2a) {
return k10_cast_grad_path(tgt, vec, want, hdr);
}
return k10_cast_class(tgt, vec, hdr);
}
static V k10_sub_s(I16 *s, I16 *d,
I val, I n) {
for (I i = 0; i < n; i++) d[i] = s[i] - (I16)val;
}
static V k10_sub_i(I *s, I *d,
I val, I n) {
for (I i = 0; i < n; i++) d[i] = s[i] - val;
}
static V k10_sub_b(char *s, char *d,
I val, I n) {
for (I i = 0; i < n; i++) d[i] = s[i] - (char)val;
}
static V k10_sub_lane_s(I s, V *v,
V *o, I n) {
uJ bytes = ((n + 0xf) >> 4) << 5;
for (uJ off = 0; off < bytes; off += K_AVX2_STRIDE_BYTES) {
k10_sub_s((I16 *)((char *)v + off),
(I16 *)((char *)o + off), s, 8);
k10_sub_s((I16 *)((char *)v + off + 16),
(I16 *)((char *)o + off + 16), s, 8);
}
}
static V k10_sub_lane_i(I s, V *v,
V *o, I n) {
uJ bytes = ((n + 7) >> 3) << 5;
for (uJ off = 0; off < bytes; off += K_AVX2_STRIDE_BYTES) {
k10_sub_i((I *)((char *)v + off),
(I *)((char *)o + off), s, 4);
k10_sub_i((I *)((char *)v + off + 16),
(I *)((char *)o + off + 16), s, 4);
}
}
static V k10_sub_lane_b(I s, V *v,
V *o, I n) {
uJ bytes = ((n + 0x1f) >> 5) << 5;
for (uJ off = 0; off < bytes; off += K_AVX2_STRIDE_BYTES) {
k10_sub_b((char *)v + off, (char *)o + off, s, 16);
k10_sub_b((char *)v + off + 16,
(char *)o + off + 16, s, 16);
}
}
J *k10_sub_scalar(I s, __int128 *vec) {
J *out = clone_or_recycle_full(vec);
G *p = (G *)((char *)vec - 5);
G hdr = k_type_cast_gradient_table[*p];
I n = *(I *)((char *)out - 4);
if (hdr == 4) k10_sub_lane_s(s, vec, out, n);
else if (hdr != 3) k10_sub_lane_i(s, vec, out, n);
else k10_sub_lane_b(s, vec, out, n);
release_object((V **)vec);
return out;
}
V **k10_cast_dec_pad(__int128 *vec) {
V **out = (V **)cast_to_tag((V *)1, vec);
I n = *(I *)((char *)out - 4);
uJ bytes = ((n + 0x1f) >> 5) << 5;
for (uJ o = 0; o < bytes; o += K_AVX2_STRIDE_BYTES) {
char *p = (char *)out + o;
for (I i = 0; i < 16; i++) p[i] += '0';
p += 16;
for (I i = 0; i < 16; i++) p[i] += '0';
}
return out;
}
V **k10_cast_log_max(I tgt, __int128 *vec) {
V **out = k10_cast_inner((V *)(uintptr_t)tgt,
(V **)vec);
uJ mx = k10_max_long(out);
char f = 3;
if (mx <= K_BYTE_MAX) f = 1;
else if (mx <= 0xffff) f = 2;
*(int8_t *)((char *)out - 6) = f;
return out;
}
uJ k10_check_rank(J *fn, I n,
J aux) {
(void)aux;
I r = k10_get_rank(fn);
return (uJ)((r == n) ? r : 0);
}
I k10_get_rank(J *fn) {
if (((J)fn >> K_TAG_SHIFT) != 0) return 1;
if (*(G *)((char *)fn - 5) !=
K_TYPE_LITERAL_FUNC) return 1;
return *(I *)((char *)fn - 4);
}
static V **k10_fold_loop(J *fn, V **seed,
V **vec) {
V **res = seed;
I n = *(I *)((char *)vec - 4);
for (I i = 0; i < n; i++) {
J c = index_typed_vector((J *)vec, i);
if (res == seed && i == 0) res = (V **)c;
else res = (V **)apply_dyadic_dispatch(fn,
(J *)res, (J *)c, 0, 0);
if (((uintptr_t)res - 1) <= 0xe) break;
}
release_object((V **)vec);
return res;
}
V **k10_fold_list(J *fn, V **seed,
V **vec) {
G hdr = *(G *)((char *)vec - 5);
if (hdr == K_TYPE_PAIR_CELL ||
hdr == K_TYPE_PAIR_IMMEDIATE) return (V **)5;
if (seed == NULL && *(I *)((char *)vec - 4) <= 1)
return (V **)keyed_first(vec);
return k10_fold_loop(fn, seed, vec);
}
static V **k10_fold_type(J *fn, uJ vec,
J aux) {
uJ bit = (uJ)((uintptr_t)fn & K_BYTECODE_LOCAL_LIMIT);
I cls = (bit < 7) ? (I)bit : 7;
if (!((0x95u >> cls) & 1)) {
G hdr = *(G *)((char *)vec - 5);
if (hdr == K_TYPE_PAIR_IMMEDIATE ||
hdr == K_TYPE_PAIR_CELL || (hdr - 1) <= 0x3e)
return fold_engine_full(0, (V **)vec, aux);
}
return k10_fold_list(fn, NULL, (V **)vec);
}
V **k10_fold(J *fn, uJ vec, J aux) {
if (vec_total_length((V *)vec) == 2) {
J a = index_typed_vector((J *)vec, 0);
J b = index_typed_vector((J *)vec, 1);
V **out = (V **)apply_dyadic_dispatch(fn,
(J *)a, (J *)b, 0, 0);
release_object((V **)(V *)vec);
return out;
}
if ((uintptr_t)fn == 0x20)
return (V **)keyed_last((V **)vec);
return k10_fold_type(fn, vec, aux);
}
uJ k10_is_truthy_atom(V **arg) {
uJ tag = (uJ)arg >> K_TAG_SHIFT;
I r = 1;
if (tag == 1) {
r = (uI)(uintptr_t)arg > 0x20 ? 1 : 0;
} else {
if (!((K_TAGCLASS_PAIR_PAYLOAD >> tag) & 1)) {
uJ v = TEST_BITQ(K_TAGCLASS_SCALAR_IMMED,
tag) ? (uJ)(uintptr_t)arg :
*(uJ *)((uintptr_t)arg & K_PTR_MASK);
r = (v != 0) ? 1 : 0;
}
release_object((V **)arg);
}
return (uJ)r;
}
static V **k10_each_pair(V **arg, J a2,
I aux, I flags) {
G hdr = *(G *)((char *)arg - 5);
V *right = retain_object((V *)((J *)arg)[1]);
V *left = retain_object((V *)*(J *)arg);
release_object((V **)arg);
V **res = k10_each((V **)right, a2, aux, flags);
if (K_IS_ERR_RETURN(res)) return res;
J *cell = allocate_typed_vector((I)hdr, 2);
cell[0] = (J)left; cell[1] = (J)res;
return (V **)cell;
}
static V **k10_each_list_loop(V **arg,
J a2, I aux, I flags, J *out) {
I n = *(I *)((char *)arg - 4);
for (I i = 0; i < n; i++) {
V **val = (V **)index_typed_vector(
(J *)arg, (uJ)i);
V **res = k10_each(val, a2, aux, flags);
out[i] = (J)res;
if (K_IS_ERR_RETURN(res)) return res;
}
return NULL;
}
static V **k10_each_list(V **arg, J a2,
I aux, I flags, G hdr) {
if ((uI)(hdr - 1) <= 0x3e)
return (V **)arithmetic_negate((__int128 *)arg);
I n = *(I *)((char *)arg - 4);
J *out = allocate_typed_vector(K_TYPE_LIST, n);
V **err = k10_each_list_loop(arg, a2, aux,
flags, out);
if (err) return err;
V **fin = (V **)canonicalize_homogeneous_list(
out, 0, 0);
release_object((V **)arg);
return fin;
}
V **k10_each(V **arg, J a2, I aux,
I flags) {
uI tag = (uI)((J)arg >> K_TAG_SHIFT);
if (tag != 0) return arg;
G hdr = *(G *)((char *)arg - 5);
if ((int8_t)(hdr + 3) < 2)
return k10_each_pair(arg, a2, aux, flags);
if (hdr == K_TYPE_PAIR_IMMEDIATE) {
arg = (V **)expand_pair_immediate((J *)arg);
hdr = *(G *)((char *)arg - 5);
}
if (hdr == K_TYPE_PAIR_IMMEDIATE ||
hdr != K_TYPE_LITERAL_FUNC)
return k10_each_list(arg, a2, aux, flags, hdr);
return arg;
}
J *k10_atomize(V *vec) {
if (K_IS_ERR_RETURN(vec)) return (J *)vec;
if (((J)vec >> K_TAG_SHIFT) != 0) return (J *)vec;
if (*(I *)((char *)vec - 4) != 1)
return (J *)vec;
G hdr = *(G *)((char *)vec - 5);
if ((hdr - 1) > 0x3e) return (J *)vec;
J cur = index_typed_vector((J *)vec, 0);
release_object((V **)vec);
return (J *)cur;
}
J k10_first_byte(char *vec) {
if (*(I *)(vec - 4) == 0) return 0;
return (J)(G)vec[0];
}
J k10_first_word(I *vec) {
if (*(I *)((char *)vec - 4) == 0) return 0;
return (J)vec[0];
}
I k10_list_lt(J *a, J *b) {
if (a == b) return 0;
if (deep_equal((V **)a, (V **)b, 0, 0) != 0)
return 0;
return ((uintptr_t)a < (uintptr_t)b) ? 1 : 0;
}
static J k10_at_atom_adj(V *t, J v) {
k10_at_atom((J *)t, (V **)v);
return (J)t;
}
static V **k10_at_vec_adj(V *t, V *v) {
return (V **)index_at_vector((J *)t, v);
}
J k10_at_v(J a1, V **a2) {
return (J)generic_cast_worker(
(J)k10_at_atom_adj,
(J)k10_at_vec_adj, a1, a2);
}
V k10_at_atom(J *vec, V **idx) {
uI tag = (uI)((J)idx >> K_TAG_SHIFT);
if (tag == 0) return;
I pos;
if ((tag - 8) <= 6) {
if (tag == K_TYPE_LONG) {
pos = (I)*(J *)(((uintptr_t)idx)
& K_PTR_MASK);
release_object((V **)idx);
} else {
pos = (I)(uintptr_t)idx;
}
vector_at_or_first_atom(vec, pos);
}
}
static J k10_idx_sh(J *v, J *as) {
V *r = shape_with_int_dimensions(v, (V *)as);
R (J)r;
}
J k10_idx_at_vec(J *vec, V *idx) {
V *n = narrow_long_if_fits_int(idx);
if (XT(n) - 8 > 5) R 8;
J *as = cast_to_tag((V *)K_TYPE_INT, (V *)n);
I len = (I)kind_or_length_walk(vec);
if (!XN(as)) R k10_idx_sh(vec, as);
I m = (I)cached_max_element(as, 0, 0);
if (m < len) {
V *r = slice_into_new_slot(0, len, vec);
R (J)r;
}
R k10_idx_sh(vec, as);
}
static J k10_dyad_3(J a, J *b, I f) {
R apply_dyadic_with_promote(a, b, f, 0);
}
static J *k10_idx_path_keyed(J *root, J *path, I f) {
G t = *(G *)((char *)root - 6);
J (*s)(J, J *, I) = (t == 0)
? k10_dyad_3 : (V *)cast_dyadic_pair_chain;
V *r = (V *)s(*root, path, f);
J *n = (J *)root[1];
P(K_IS_ERR(r), (J *)r);
R (J *)generic_cast_worker(
(J)index_at_atom_adapter,
(J)index_at_vector_adapter,
(J)n, (V **)r);
}
J *k10_idx_path(J *root, J *path, I f) {
if (!path) {
if (XT(root) == K_TYPE_KEYED_PAIR)
root = (J *)root[1];
R (J *)retain_object(root);
}
uI pt = (uI)((uJ)path >> K_TAG_SHIFT);
uI out = pt ? pt : XT(path);
G rt = XT(root);
if (rt == K_TYPE_KEYED_PAIR ||
(out == 2 && rt == K_TYPE_PAIR_CELL))
R k10_idx_path_keyed(root, path, f);
if (rt == K_TYPE_PAIR_CELL && (out & ~0xfu) == 0x10) {
J *r = (J *)cast_dyadic_pair_chain(root[1], path, f);
P(K_IS_ERR(r), r);
R (J *)generic_cast_worker(
(J)index_at_atom_adapter,
(J)index_at_vector_adapter,
(J)root, (V **)r);
}
R (J *)generic_cast_worker(
(J)index_at_atom_adapter,
(J)index_at_vector_adapter,
(J)root, (V **)path);
}
static J k10_prom_f(J a, J b, I f) {
uJ pa = TEST_BITQ(K_TAGCLASS_ATOMIC_BOX, TAG(a))
? *(J *)UNMASK(a) : (J)a;
uJ pb = TEST_BITQ(K_TAGCLASS_ATOMIC_BOX, TAG(b))
? *(J *)UNMASK(b) : (J)b;
if (f == 0) R (J)box_atom(K_TYPE_BOOL, pa == pb);
if (f == 1) R (J)box_atom(K_TYPE_BOOL, pa < pb);
if (f == 2) R (J)box_atom(K_TYPE_LONG, pa + pb);
if (f == 3) R (J)box_atom(K_TYPE_LONG, pa - pb);
if (f == 4) R (J)box_atom(K_TYPE_LONG, pa * pb);
R 6;
}
J k10_prom_dyad(J a, J *b, I f, I f2) {
G ta = TAG(a), tb = TAG(b);
if (ta == tb && ta - 8 <= 6)
R k10_prom_f(a, (J)b, f2);
J args[2] = { a, (J)b };
R verb_byte_apply((J *)f2, 2, args);
}
J k10_dyad_chain(J a, J *b, I f) {
P(K_IS_ERR(b), (J)b);
G h = XT(b);
if (h == K_TYPE_PAIR_CELL || h == K_TYPE_KEYED_PAIR) {
V *l = retain_object((V *)*b);
J *r = (J *)retain_object((V *)b[1]);
release_object((V **)b);
J *n = (J *)k10_dyad_chain(a, r, f);
R (J)pair_cell_make(h, (J)l, n);
}
R k10_prom_dyad(a, b, f, 0);
}
J *k10_shape_p(J *r, V *idx) {
R shape_with_int_dimensions(r, (V *)idx);
}
J *k10_slice_p(I a, I b, J *v) {
R slice_into_new_slot(a, b, v);
}
J *k10_seed_in(V ***s, J *a2, J *a3, J *a4) {
V **v = *s;
V **cl = clone_or_recycle_header(*s);
*s = cl;
if (XT(cl) == K_TYPE_KEYED_PAIR)
R (J *)retain_object(v);
R a2;
}
J *k10_app_seed(J *a1, J *a2, J *a3, J *a4) {
J *s = a1;
if (!TAG(a1) && XT(a1) != K_TYPE_LITERAL_FUNC) {
J *b = k10_seed_in((V ***)&s, a2, a3, a4);
release_object((V **)a3);
if ((uJ)b - 1 > 0xe) s = b;
R s;
}
R (J *)6;
}
J *k10_app_each(J *fn, V **arg, J *a3, J *a4) {
I n = XN(arg);
J *out = allocate_typed_vector(K_TYPE_LIST, n);
for (I i = 0; i < n; i++)
out[i] = apply_n_args(fn, 2, (uJ)arg[i]);
release_object((V **)arg);
R out;
}
J *k10_app_pair(J *fn, J *kv, J *a3, J *a4) {
if (XT(kv) != K_TYPE_KEYED_PAIR) R kv;
V *k = retain_object((V *)*kv);
V *v = retain_object((V *)kv[1]);
release_object((V **)kv);
J *out = k10_app_each(fn, (V **)v, a3, a4);
R (J *)pair_cell_make(K_TYPE_KEYED_PAIR, (J)k, out);
}
uJ k10_pimm_dest(I w, V *v, J aux) {
V *t = ((J *)v)[w];
release_object((V **)t);
R 0;
}
J k10_pimm_at(J *v, J *i, J *o, uJ aux) {
if (!v) R 0;
J w = (J)i;
if (!TAG(i) && i)
w = ((uJ)i >= K_SYM_INDEX_CUTOFF) ? *i : w;
else
w = (J)UNMASK(i);
w = (w < 0) ? 0 : (w > 1) ? 1 : w;
R (J)retain_object((V *)v[w]);
}
J *k10_pimm_tail(V **v) {
while (XT(v) == K_TYPE_PAIR_IMMEDIATE)
v = (V **)((J *)v)[1];
R (J *)v;
}
J k10_pimm_head(V **v) {
if (XT(v) != K_TYPE_PAIR_IMMEDIATE)
R (J)retain_object(v);
R (J)retain_object((V *)*v);
}
static J k10_diag(S s) {
write_cstr_stderr(s);
write_cstr_stderr("\n");
R 5;
}
J k10_err_srt(void) { R k10_diag("msrt"); }
J k10_err_rev(void) { R k10_diag("mrev"); }
J k10_err_cat(void) { R k10_diag("mcat"); }
J k10_pimm_tag(J *a) { R XT(*(J *)a); }
J pair_immediate_to_canonical_inner(V **arg1) {
if (!arg1) return 0;
return (J)arg1;
}
J k10_pimm_can(V **v) {
if (*(G *)((S)v - 6) > 1) {
V *h = clone_or_recycle_header(v);
R (J)bigint_normalize_in_place(h);
}
if (XT(v) != K_TYPE_BOOL) {
I n = (I)((uI)((J *)v)[-1]) + 1;
J *o = bigint_grow_to_target_lo(n, v);
release_object((V **)v);
R (J)o;
}
R (J)cast_to_tag((V *)K_TYPE_LONG, (V *)v);
}
J k10_pimm_b(J *a) {
J *e = expand_pair_immediate(a);
J *b = promote_to_unique_bool_engine(e);
release_object((V **)e);
R (J)b;
}
I k10_is_srt_pimm(J *v) { R *(G *)((S)v - 6) > 1; }
I k10_is_srt_typed(J *v) { R *(G *)((S)v - 6) >= 2; }
I k10_is_ukey(J *v) { R XT(v) == K_TYPE_KEYED_PAIR; }
J k10_ls_sh_fn(V *v) {
R list_of_short_function_table(v, 0, 0);
}
V *k10_srt_ls(V *c, V **l) {
R sort_with_comparator(c, l);
}
I k10_at_eq(J a, J b) {
if (a == b) R 1;
G ta = TAG(a), tb = TAG(b);
if (ta != tb && ta - 8 <= K_LOG2_BITS_INDEX_MASK && tb - 8 <= K_LOG2_BITS_INDEX_MASK) {
J pa = (ta != 0) ? *(J *)UNMASK(a) : a;
J pb = (tb != 0) ? *(J *)UNMASK(b) : b;
R pa == pb;
}
R 0;
}
J *k10_sym_look(I i) {
if (!runtime_sym_table_charvecs) R 0;
R (J *)runtime_sym_table_charvecs[i];
}
I k10_sym_ins(V *v) {
static I n = 0, cap = 0;
if (n >= cap) {
cap = cap ? cap * 2 : 256;
J *t = realloc(runtime_sym_table_charvecs,
(size_t)cap * 8);
if (!t) R -1;
runtime_sym_table_charvecs = t;
}
runtime_sym_table_charvecs[n] = (J)retain_object(v);
R n++;
}
V *k10_srt_in(V *s, V **l) {
V *r = 0, *b = s;
if (l && XN(l)) {
r = sort_with_comparator(s, l);
if (!K_IS_ERR(r)) {
V *idx = cast_graph_int_tail((J)r);
b = shape_with_int_dimensions(s, idx);
}
}
if (!l || !XN(l) || !K_IS_ERR(r)) {
release_object((V **)l);
R b;
}
R r;
}
J *k10_is_cnt_b(V *l) {
I n = XN(l);
J *out = allocate_typed_vector(K_TYPE_PAIR_CHAIN, n);
for (I i = 0; i < n; i++) {
J *lam = (J *)*(J *)((char *)l + (i << 3));
I *b = (I *)lam[2];
G m = 0;
if ((b[1] ^ 0x74) | (b[0] ^ 0x6e756f63u)) {
V *f = (V *)*lam;
m = ((G *)f)[XN(f) - 1] - 0x34;
}
((char *)out)[i] = (char)m;
}
R out;
}
J *k10_srt_disp(J *a1, J *a2, J *a3) {
uI m = 0; V **s = 0; G b = 0;
if (XT(a1) == K_TYPE_KEYED_PAIR && a3) {
if (XT(*(J *)a1) == 0x19) {
S f = (S)((J *)*a3)[2];
if (f[0] == 'd') {
m = (f[1] == '.') ? f[2] : 'd';
if (m) { s = (V **)retain_object(a1); b = 1; }
}
}
}
J *c = k10_is_cnt_b(a2[1]);
J *r = a1;
if (XT(a1) == K_TYPE_KEYED_PAIR) {
r = (J *)retain_object((V *)a1[1]); release_object((V **)a1);
}
R sort_canonical(r, c, a3, s, (V *)(uJ)b);
}
J *k10_srt_can(J *l, J *c, J *i, V *s, V *b) {
R l;
}
V *k10_enr_app(uJ f, V **l, J *r, J *m) {
if (TAG(f)) R (V *)6;
J *kp = (J *)f;
if (XT(kp) == K_TYPE_PAIR_CELL) {
V *res = resolve_class_dispatch(kp, l);
if (!K_IS_ERR(res))
R (V *)ensure_singleton_or_box(res, (J)res, 0);
}
R (V *)6;
}
J k10_gen_vb(I f, J *fn, V **v) {
J args[1] = { (J)v };
R verb_byte_apply(fn, 1, args);
}
J *k10_at_rec(I v, V **a, I f) {
if (v < 0 || v > K_BYTE_MAX) R (J *)6;
R (J *)atomic_eval_recursive(a, 0, 0, v);
}
J k10_ls_mod(void) {
J *l = (J *)loader_keyword_table;
if (!l || XT(l) != K_TYPE_KEYED_PAIR) {
write_cstr_stderr("(no modules loaded)\n");
R 0;
}
J *n = (J *)*l, *p = (J *)l[1];
for (I i = 0; i < XN(n); i++) {
S nv = (S)n[i], pv = (S)p[i];
write(1, nv, XN(nv));
write(1, " => ", 4);
write(1, pv, XN(pv));
write(1, "\n", 1);
}
R 0;
}
J k10_help_str(void) {
write_cstr_stderr("\\\\<cmd> -- system command\n"
"\\\\\\ -- exit\n"
"\\\\h -- this help\n");
R 0;
}
J k10_ws_tog(void) {
parse_in_dyadic_context = !parse_in_dyadic_context;
write_cstr_stderr(parse_in_dyadic_context ? "workspace: on\n"
: "workspace: off\n");
R parse_in_dyadic_context;
}
J *k10_sh_p(J *r, V *i) {
R shape_with_int_dimensions(r, (V *)i);
}
J *k10_sl_p(I a, I b, J *v) {
R slice_into_new_slot(a, b, v);
}
J k10_br_rec(V **a1, J *a2, J *a3) {
if (!TAG(a3) && XT(a3) != K_TYPE_LITERAL_FUNC)
R bracket_index_with_atom(0xffffffff, a1, a2, a3);
R 3;
}
J k10_br_at(I v, V **a2, J *a3, J *a4) {
if (XT(a4) != K_TYPE_KEYED_PAIR)
R bracket_index_inner_full(v, a2, a3, a4);
J *r = (J *)retain_object((V *)a4[1]);
V *l = retain_object((V *)*a4); release_object((V **)a4);
J i = (J)bracket_index_inner_full(v, a2, a3, r);
R (J)pair_cell_make(K_TYPE_KEYED_PAIR, (J)l, (J *)i);
}
J k10_br_full(I v, V **a2, J *a3, J *a4) {
if (!a3 || K_IS_ERR(a3)) R (J)retain_object(a4);
I n = XN(a3);
if (!n) R (J)retain_object(a4);
J c = (J)a4;
for (I i = 0; i < n; i++) {
J x = a3[i];
if (TAG(x) == K_TYPE_LONG) {
J p = *(J *)UNMASK(x);
c = (J)vector_at_or_first_atom((J *)c, p);
} else if (!TAG(x))
c = (J)k10_idx_at_vec((J *)c, (V *)x);
if ((uJ)c - 1 < 0xf) R c;
}
R c;
}
J *k10_zip_p(I v, V **a2, V ***a3, I f) {
if (TAG(a3)) R (J *)6;
G rt = XT(a3), lt = XT(a2);
if (rt == K_TYPE_LITERAL_FUNC) R (J *)6;
if (((rt == K_TYPE_KEYED_PAIR) ||
(rt != K_TYPE_KEYED_PAIR && lt == K_TYPE_KEYED_PAIR)) &&
lt != rt) R (J *)6;
if (lt == rt) {
if (!deep_equal((V **)((J *)a2)[0],
(V **)((J *)a3)[0], f, 0)) {
write_cstr_stderr("dd\n"); R (J *)5;
}
R (J *)pair_cell_make(K_TYPE_KEYED_PAIR,
(J)retain_object(a2), (J *)retain_object(a3));
}
if (v == 0x2c || (v - 4) < 0xa)
R (J *)apply_dyadic_with_promote((J)a2, (J *)a3, v, f);
write_cstr_stderr("dd\n"); R (J *)5;
}
uJ k10_hi_sp(J *v, I vb, J a, I f) {
if (TAG(v)) R 0;
G h = XT(v);
if ((vb & 0xf0) == 0x60 || (vb & 0xf0) == K_TYPE_BASE_BOX_TAG) R 1;
if ((vb & 0xf0) == 0x70 && h >= K_TYPE_PAIR_IMMEDIATE_LO && h <= 0xfd) R 1;
R 0;
}
J *k10_gen_n_d(I f, J v, uJ a) {
if (TAG(a) && TAG(a) - 8 > K_LOG2_BITS_INDEX_MASK) {
write_cstr_stderr("nyi\n"); R (J *)5;
}
if (v > K_BYTE_MAX) R (J *)6;
J args[1] = { (J)a };
R (J *)verb_byte_apply((J *)v, 1, args);
}
V **k10_resh_i(I t, V **s) {
I n = XN(s);
V **o = (V **)allocate_typed_vector(t, n);
for (I i = 0; i < n; i++)
element_store_into_typed((J *)o, i, retain_object(s[i]));
release_object((V **)s);
R o;
}
V k10_st_idx(J *d, J i, V *v) {
element_store_into_typed(d, i, v);
}
J k10_num_app(uJ s, uJ d, V *v) {
if (!s) R 6;
if (s == d) R (J)v;
if (d - 8 > 5 || s - 8 > 5) {
V **b = promote_vector_to_tag((I)d,
singleton_coerce_atom((J)v));
R K_IS_ERR(b) ? (J)b : (J)keyed_first(b);
}
R (J)(K_TAG(d) | (uJ)v);
}
V *sort_via_list_comparator(V *cmp, V **list, V *running_mask, J *aux)
{
uJ n = (uJ)*(I *)((char *)list - 4);
if (n != 0) {
J i = 0;
do {
char zmm1[16];
V *row_result = sort_then_canonicalize(cmp,
(J *)retain_object(list[i]));
if (K_IS_ERR_RETURN(row_result)) return row_result;
running_mask = cast_to_bool_packed((__int128 *)row_result, zmm1);
if (i != 0) {
running_mask = (V *)pair_or_collapse_dyadic(5,
(V **)running_mask, (J *)aux);
}
i++;
aux = (J *)running_mask;
} while ((uJ)i != n);
}
release_object(list);
return running_mask;
}
V **cast_pair_promote_to_uniform(J *arg1, V **arg2)
{
J *vec_lhs = (J *)*arg1;
uJ hdr_lhs = (uJ)*(G *)((char *)vec_lhs - 5);
uJ hdr_rhs = (uJ)*(G *)((char *)arg2 - 5);
if (hdr_lhs > hdr_rhs) {
return cast_to_tag((V *)(uintptr_t)hdr_lhs, (__int128 *)arg2);
}
V **promoted = cast_to_tag((V *)(uintptr_t)hdr_rhs, (__int128 *)vec_lhs);
*arg1 = (J)promoted;
if (((uintptr_t)promoted - 1) > 0xe) {
promoted = arg2;
}
return promoted;
}
J *k10_cast_pair(J h, J p, J t, J *v) {
G tag = XT(v);
J *r = retain_object((J *)v[1]);
V *l = retain_object((V *)*v);
release_object((V **)v);
J *i = k10_cast_recurse(h, p, t, r);
P(K_IS_ERR(i), i);
J *c = allocate_typed_vector(tag, 2);
c[0] = (J)l;
c[1] = (J)i;
R c;
}
J *k10_cast_list(J h, J p, J t, J *v) {
I n = XN(v);
J *out = allocate_typed_vector(0, n);
for (I i = 0; i < n; i++) {
J *x = (J *)index_typed_vector(v, i);
J *r = k10_cast_recurse(h, p, t, x);
out[i] = (J)r;
P(K_IS_ERR(r), r);
}
if (!n) {
J *v0 = (J *)out[0];
out[0] = (J)k10_finalize(v0, 0, 0, 0);
}
J *res = canonicalize_homogeneous_list(out, 0, 0);
release_object((V **)v);
R res;
}
J *k10_cast_vec(J h, J p, J t, J *v, G hdr) {
if (hdr - 1 <= 0x3e)
R ((K_promote_fn)p)((V *)t, v);
R k10_cast_list(h, p, t, v);
}
J *k10_cast_recurse(J h, J p, J t, J *v) {
if (K_TOP_TAG(v))
R ((K_alloc_into_fn)h)((V *)t, (J)v);
G hdr = XT(v);
if ((int8_t)(hdr + 3) < 2)
R k10_cast_pair(h, p, t, v);
if (hdr == K_TYPE_PAIR_IMMEDIATE) {
write_cstr_stderr("nyc\n");
R (J *)5;
}
if (hdr != K_TYPE_LITERAL_FUNC)
R k10_cast_vec(h, p, t, v, hdr);
R ((K_alloc_into_fn)h)((V *)t, (J)v);
}
J *k10_cyclic_fill(I want, J *vec) {
R reshape_or_take(want, vec);
}
J *k10_size_match_j(I want, J *arg2, I flags) {
R size_match_or_clone(want, arg2, flags);
}
J *k10_emit_line(I line) {
char buf[24];
I len = sprintf(buf, " at line %d", line);
write(2, buf, (size_t)len);
parse_cursor = line;
R 0;
}
J *k10_emit_col(I col) {
char buf[24];
I len = sprintf(buf, " col %d", col);
write(2, buf, (size_t)len);
parse_token_start = col;
R 0;
}
J *k10_make_call(I kind, J left, J *right) {
R pair_cell_make(kind, left, right);
}
J *k10_finalize(J *vec, J aux2, J aux3, I flags) {
R unwrap_pair_chain(vec, aux2, aux3, flags);
}
J *k10_tri_loop(K_triadic_each_fn f, J *v,
J a1, J a2, J *res) {
I i = 0, n = XN(v);
for (; i < n; i++) {
J x = index_typed_vector(v, i);
J *r = f(x, a1, a2);
res[i] = (J)r;
P(K_IS_ERR(r), r);
}
R 0;
}
J *k10_tri_each(K_triadic_each_fn f,
J *vec, J a1, J a2) {
P(XT(vec) != 0, (J *)5);
I n = XN(vec);
J *out = allocate_typed_vector(0, n);
J *err = k10_tri_loop(f, vec, a1, a2, out);
P(err, err);
if (!n) {
J *v0 = (J *)out[0];
out[0] = (J)k10_finalize(v0, 0, 0, 0);
}
out = canonicalize_homogeneous_list(out, 0, 0);
release_object((V **)vec);
R out;
}
J *k10_range_keyed(J verb, J *v, I flags) {
J *right = retain_object((J *)v[1]);
V *left = retain_object((V *)*v);
release_object((V **)v);
J *res = k10_range_dispatch(
verb, (uJ)right, flags);
R k10_make_call(
K_TYPE_KEYED_PAIR, (J)left, res);
}
I k10_is_cvec_list(J *v) {
I i = 0, n = XN(v);
for (; i < n; i++) {
J x = v[i];
if (K_TOP_TAG(x) || XT((V *)x) != 1) R 0;
}
R 1;
}
J *k10_range_base(J verb, J *v, G t, I flags) {
if (verb == '.' &&
is_homogeneous_list(v, 0, 0, flags))
R list_element_lengths((V **)v);
if (verb == ',')
R apply_unary_or_singleton(v, 0, flags);
if (verb == '#' && t == 0 && k10_is_cvec_list(v))
R list_element_lengths((V **)v);
J args[1] = { (J)v };
R verb_byte_apply((J *)verb, 1, args);
}
J *k10_range_dispatch(J verb, uJ arg, I flags) {
P(K_TOP_TAG(arg), (J *)3);
J *v = (J *)arg;
G t = XT(v);
P(t == K_TYPE_LITERAL_FUNC, (J *)3);
if (t == K_TYPE_KEYED_PAIR)
R k10_range_keyed(verb, v, flags);
R k10_range_base(verb, v, t, flags);
}
I k10_is_simple(V *v) {
uJ x = (uJ)v;
if (K_TOP_TAG(x)) R 1;
R (XT(v) - 1 <= 0x3e);
}
I k10_is_num_v(V *v) {
G t = K_TOP_TAG(v);
uI h = t ? t : XT(v);
R (h - 8 <= 0x21);
}
I k10_is_str(V *v) {
G t = K_TOP_TAG(v);
uI h = t ? t : XT(v);
R (h == 1 || h == 2 ||
h == K_TYPE_CHAR || h == K_TYPE_CHAR_BOX);
}
J k10_banner(I mem) {
char buf[64];
I len = sprintf(buf, " K10 1.0\n %dg\n", mem);
write(1, buf, (size_t)len);
R 0;
}
V k10_hex_byte(S dst, G v) {
S d = "0123456789abcdef";
dst[0] = d[v >> 4];
dst[1] = d[v & 15];
}
I k10_is_digit(G b) { R b >= '0' && b <= '9'; }
I k10_is_lower(G b) { R b >= 'a' && b <= 'z'; }
I k10_is_alnum(G b) {
if (k10_is_digit(b) || k10_is_lower(b))
R 1;
R (b >= 'A' && b <= 'Z');
}
I k10_is_start(G b) {
R k10_is_lower(b) ||
k10_is_digit(b) || b == '_';
}
I k10_classify(G b) {
if (k10_is_lower(b) || b == '_') R 1;
if (k10_is_digit(b)) R 2;
R (b == '\"') ? 3 : 0;
}
J *k10_disp_dyad(J *fn, uJ arg) {
J a = index_typed_vector((J *)arg, 0);
J b = index_typed_vector((J *)arg, 1);
J *out = apply_dyadic_dispatch(
fn, (J *)a, (J *)b, 0, 0);
release_object((V **)arg);
R out;
}
J *k10_disp_gen(J *fn, uJ arg) {
G h = XT(arg);
if (h == K_TYPE_PAIR_IMMEDIATE ||
h == K_TYPE_PAIR_CELL || (h - 1 <= 0x3e))
R generic_n_arity_dispatch(0, (J)fn, arg);
R 0;
}
J *k10_disp_verb(J *fn, uJ arg, J aux, I cls) {
if (has_infix_specialisation(
(J *)arg, (J)fn, aux, cls)) {
write_cstr_stderr("\n");
R (J *)5;
}
if ((uJ)fn != ',')
R iterate_verb_into_list_outer(
fn, 0, (J *)arg);
R list_concat_or_canon((J *)arg, 0, 0);
}
static J *k10_disp_cls(J *fn, uJ arg, J aux, I cls) {
if (!((0x95u >> cls) & 1)) {
J *out = k10_disp_gen(fn, arg);
if (out) return out;
}
return k10_disp_verb(fn, arg, aux, cls);
}
J *k10_dispatch_arg(J *fn, uJ arg, J aux) {
if (vec_total_length((V *)arg) == 2)
R k10_disp_dyad(fn, arg);
if ((uJ)fn == ' ') R keyed_last((J *)arg);
uJ bit = (uJ)fn & K_BYTECODE_LOCAL_LIMIT;
R k10_disp_cls(fn, arg, aux,
(bit < 7) ? (I)bit : 7);
}
static J k10_pair_res(V **a1, J *r1, J *r2) {
if ((intptr_t)a1 - 4 <= 9)
return (J)extract_first_typed_word_full((I *)a1);
return (J)bracket_index_inner_full(0, a1, r1, r2);
}
J k10_pair_apply_sym(V **a1, J *a2, V **a3) {
V *left = retain_object((V *)*a2);
J *r1 = retain_object((J *)a2[1]); release_object((V **)a2);
J *r2 = retain_object((J *)((J *)a3)[1]); release_object((V **)a3);
J res = k10_pair_res(a1, r1, r2);
R (J)k10_make_call(
K_TYPE_KEYED_PAIR, (J)left, (J *)res);
}
static uJ k10_probe_h(I verb, G head_t) {
if (verb == ',' && head_t == 1) R 1;
if (verb == '#' && head_t == 1) R 1;
if (head_t == K_TYPE_KEYED_PAIR && verb != ',')
R 1;
R 0;
}
uJ k10_verb_probe(J *v, I verb, J aux, I flags) {
if (K_TOP_TAG(v) || XT(v) != 0) R 0;
J h = *v;
if (K_TOP_TAG(h)) R 0;
R k10_probe_h(verb, XT((V *)h));
}
V k10_num_err(const char *msg) {
write_cstr_stderr(msg);
write_cstr_stderr("\n");
}
J k10_verb_take(J a, J b) {
R (J)reshape_to_target_tag((I)a, (V **)b);
}
J k10_verb_drop(J a, J b) {
I n = XN((V *)b);
R (J)slice_into_new_slot(
(I)a, n - (I)a, (J *)b);
}
J k10_verb_at(J a, J b) {
R index_at_dispatch(a, (V **)b);
}
J k10_verb_dot(J a, J b) {
R (J)index_path_walk((J *)a, (J *)b, 0);
}
J *k10_eval_line_simple(S line) {
R eval_line_or_dispatch(line, 0, 0);
}
J k10_fmt_f(F v) { R format_double_to_charvec(v); }
J k10_fmt_j(J v) { R print_long_to_stdout(v); }
F k10_pr_f(F v) { R print_double_to_stdout(v); }
static J k10_each_l(I mode, J *left, J *right, J *out, I i) {
if (mode == 0)
return (J)vector_at_or_first_atom(left, i);
if (mode == 1)
return i ? index_typed_vector(out, i - 1) :
(J)retain_object(left);
return i ? index_typed_vector(right, i - 1) :
(J)retain_object(left);
}
J k10_each_val(I m, J *fn, J *l, J *r, J *o, I i) {
J rv = (J)vector_at_or_first_atom(r, i);
if (i == 0 && l == 0) R rv;
J lv = k10_each_l(m, l, r, o, i);
if (m == 2) { J t = rv; rv = lv; lv = t; }
R (J)apply_dyadic_dispatch(
fn, (J *)lv, (J *)rv, 0, 0);
}
static uJ k10_each_loop(I m, J *f, J *l,
J *r, J *o, I n) {
for (I i = 0; i < n; i++) {
J v = k10_each_val(m, f, l, r, o, i);
o[i] = v;
if (K_IS_ERR(v)) return (uJ)v;
}
return 0;
}
J k10_each_pair_core(I mode, J **fn, J *left, J *right) {
I n = (I)vector_total_length(right);
if (!n && !pair_chain_terminal_length(fn, (J)fn, 0)) {
release_object((V **)left); R (uJ)right;
}
J *out = allocate_typed_vector(0, n);
uJ err = k10_each_loop(mode, (J *)fn,
left, right, out, n);
if (err) return err;
if (!n)
out[0] = (J)k10_finalize((J *)out[0], 0, 0, 0);
out = canonicalize_homogeneous_list(out, 0, 0);
release_object((V **)right); release_object((V **)left);
R (uJ)out;
}
J *k10_atomic_broadcast(I verb, J *value) {
P(K_IS_ERR(value), value);
if (XN(value)) R value;
R (J *)zero_box(verb);
}
static J *k10_kj_eq(J *l, J *r, V *lk, J *lv, J *rv) {
V *c = concat_charvecs((V **)lv, (S)rv);
release_object((V **)l); release_object((V **)r);
return k10_make_call(K_TYPE_KEYED_PAIR, (J)lk, (J *)c);
}
J *k10_keyed_join(J *l, J *r, I f) {
V *lk = retain_object((V *)*l); J *lv = retain_object((J *)l[1]);
V *rk = retain_object((V *)*r); J *rv = retain_object((J *)r[1]);
if (deep_equal((V **)lk, (V **)rk, f, 0)) {
release_object((V **)rk); return k10_kj_eq(l, r, lk, lv, rv);
}
release_object((V **)lk); release_object((V **)lv); release_object((V **)rk); release_object((V **)rv);
R (J *)concat_charvecs((V **)l, (S)r);
}
J *k10_concat_keyed(V **l, V *r, I f) {
if (XT(l) == K_TYPE_KEYED_PAIR &&
XT(r) == K_TYPE_KEYED_PAIR)
R k10_keyed_join((J *)l, (J *)r, f);
R (J *)concat_charvecs(l, (S)r);
}
J *k10_cast_atom(I target, V *v) {
G t = K_TOP_TAG(v);
if (!t)
R cast_to_tag((V *)(uJ)target, (__int128 *)v);
J p = TEST_BITQ(K_TAGCLASS_SCALAR_IMMED, t) ?
(J)(uintptr_t)v : *(J *)((uJ)v & K_PTR_MASK);
R (J *)(K_TAG(target) | (uJ)p);
}
static S k10_read_all(I fd, size_t sz) {
S buf = malloc(sz + 1);
if (!buf) return NULL;
if (read(fd, buf, sz) < (ssize_t)sz) {
free(buf); return NULL;
}
buf[sz] = 0; return buf;
}
J *k10_load_file(S path) {
I fd = open(path, O_RDONLY);
P(fd < 0, (J *)5);
struct stat st;
if (fstat(fd, &st) < 0) {
close(fd); R (J *)5;
}
S b = k10_read_all(fd, (size_t)st.st_size);
close(fd); P(!b, (J *)5);
J *r = (J *)eval_source_or_dispatch(b, 0, 0);
free(b); R r;
}
static J *k10_pwd(void) {
char cwd[4096];
if (!getcwd(cwd, sizeof cwd)) return (J *)5;
write(1, cwd, strlen(cwd)); write(1, "\n", 1);
return 0;
}
J *k10_cd(S path) {
if (!path || !path[0]) return k10_pwd();
return chdir(path) == 0 ? 0 : (J *)5;
}
J k10_timer(J sec) {
dyadic_keyword_table = sec;
if (!sec) {
write_cstr_stderr("timer: disabled\n");
} else {
char buf[64];
I len = sprintf(buf, "timer: every %lld s\n",
(long long)sec);
write(2, buf, (size_t)len);
}
R sec;
}
V k10_day_ymd(J jul, I *y, I *m, I *d) {
J a = jul + JULIAN_GREGORIAN_OFFSET;
uJ yq = (uJ)((a * JULIAN_QUAD_FP_SCALE + 3) >> 7);
uJ z = (uJ)((yq * JULIAN_QUAD_FP_SCALE + 0xff) >> 8);
*y = (I)(z + 1);
J o = (J)(z * 365 + (z / 4) - (z / 100) + (z / 400));
J rem = a - o;
*m = (I)(rem * 12 + 373) / 367;
*d = (I)(rem - ((*m * 367 - 362) / 12));
if (*m > 12) { (*m) -= 12; (*y)++; }
}
J k10_date_jul(const char *iso) {
I y = (iso[0]-'0')*1000 + (iso[1]-'0')*100 +
(iso[2]-'0')*10 + (iso[3]-'0');
I m = (iso[5] - '0') * 10 + (iso[6] - '0');
I d = (iso[8] - '0') * 10 + (iso[9] - '0');
if (m <= 2) { m += 12; y--; }
J o = (J)((uJ)y*365 + (y/4) - (y/100) + (y/400));
R o + (m * 367 - 362) / 12 + d -
JULIAN_GREGORIAN_OFFSET;
}
J k10_hms_ns(I h, I m, I s, J ns) {
J t = (J)h * 3600 + (J)m * 60 + (J)s;
R t * 1000000000LL + ns;
}
V k10_ns_hms(J total, I *h, I *m, I *s, J *ns) {
J sec = total / 1000000000LL;
*ns = total - sec * 1000000000LL;
*s = (I)(sec % 60); sec /= 60;
*m = (I)(sec % 60); *h = (I)(sec / 60);
}
uJ k10_ipc_pack(I type, uI len, I comp) {
union { uJ w; G b[8]; } h;
h.b[0] = 1; h.b[1] = (G)type;
h.b[2] = (G)(comp ? 1 : 0); h.b[3] = 0;
h.b[4] = (G)(len); h.b[5] = (G)(len >> 8);
h.b[6] = (G)(len >> 16);
h.b[7] = (G)(len >> 24);
R h.w;
}
J k10_ipc_val_hdr(const uJ *h) {
const G *b = (const G *)h;
if (b[0] > 2 || b[1] > 2 || b[2] > 2) R -1;
uI len = (uI)b[4] | ((uI)b[5] << 8) |
((uI)b[6] << 16) | ((uI)b[7] << 24);
if (b[2] != 2 && b[3] != 0) R -1;
J tot = (J)len | ((J)b[3] << 32);
if (tot < 8 || tot > 0x400000000LL) R -1;
R tot - 8;
}
static const G k10_ipc_sztab[20] = {
0, 1, 16, 0, 1, 2, 4, 8, 4, 8,
1, 0, 8, 4, 4, 8, 8, 4, 4, 4
};
J k10_walk_at(G t, const G **p, const G *e) {
I sz = (t <= 19) ? k10_ipc_sztab[t] : 8;
if (t == 11) {
while (*p < e && **p) (*p)++;
if (*p >= e) R -1;
(*p)++; R 1;
}
if (!sz || *p + sz > e) R -1;
*p += sz; R 1;
}
static J k10_walk_n(const G **p, const G *e, uJ *n) {
G a = *(*p)++;
if (a & K_BYTE_SIGN_BIT) {
if (*p + 8 > e) return -1;
*n = *(uJ *)*p; *p += 8;
} else {
if (*p + 4 > e) return -1;
*n = *(uI *)*p; *p += 4;
}
return (*n > (uJ)(e - *p)) ? -1 : 1;
}
static J k10_walk_els(G t, const G **p,
const G *e, uJ n) {
I sz = k10_ipc_sztab[t];
if (!sz || n * (uJ)sz > (uJ)(e - *p)) return -1;
*p += n * sz; return 1;
}
static J k10_walk_11(const G **p, const G *e, uJ n) {
for (uJ i = 0; i < n; i++) {
while (*p < e && **p) (*p)++;
if (*p >= e) return -1; (*p)++;
}
return 1;
}
J k10_walk_v(G t, const G **p, const G *e, I d) {
uJ n; if (k10_walk_n(p, e, &n) < 0) R -1;
if (!t) {
for (uJ i = 0; i < n; i++)
if (k10_walk(p, e, d + 1) < 0) R -1;
} else if (t == 11) R k10_walk_11(p, e, n);
else R k10_walk_els(t, p, e, n);
R 1;
}
static J k10_walk_list(G t, const G **p,
const G *e, I d) {
if (k10_walk(p, e, d + 1) < 0) return -1;
if (t == 99 && k10_walk(p, e, d + 1) < 0)
return -1;
return 1;
}
static J k10_walk_100(const G **p, const G *e, I d) {
while (*p < e && **p) (*p)++;
if (*p >= e) return -1; (*p)++;
return k10_walk(p, e, d + 1);
}
J k10_walk(const G **p, const G *e, I d) {
if (*p >= e || d > 256) R -1;
G t = *(*p)++;
if (!ipc_oK10_tag_ok((int8_t)t)) R -1;
if ((int8_t)t < 0)
R k10_walk_at((G)-(int8_t)t, p, e);
if (t == 99 || t == 127 || (t >= 104 && t <= 113))
R k10_walk_list(t, p, e, d);
if (t == 100) R k10_walk_100(p, e, d);
if (t >= 101 && t <= 103) R 1;
R k10_walk_v(t, p, e, d);
}
J k10_walk_root(const G *p, const G *e, I d) {
const G *curr = p;
if (k10_walk(&curr, e, d) < 0) R -1;
R curr - p;
}
I k10_ipc_val(const G *f, J n) {
if (n < 9) R 0;
J blen = k10_ipc_val_hdr((const uJ *)f);
if (blen < 0 || blen + 8 != n) R 0;
if (f[2]) R 1;
if (f[8] == K_BYTE_SIGN_BIT) {
J elen = (J)strlen((const char *)&f[9]) + 2;
R (elen == n - 8);
}
R k10_walk_root(f + 8, f + n, 0) == blen;
}
I k10_tcp_opt(I s) {
I one = 1;
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, 4);
setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &one, 4);
R s;
}
static V k10_tcp_addr(struct sockaddr_in *a, I p) {
memset(a, 0, sizeof(*a));
a->sin_family = AF_INET;
a->sin_addr.s_addr = htonl(INADDR_ANY);
a->sin_port = htons((uH)p);
}
I k10_tcp_listen(I port) {
I s = socket(AF_INET, SOCK_STREAM, 0);
P(s < 0, -1); k10_tcp_opt(s);
struct sockaddr_in a; k10_tcp_addr(&a, port);
if (bind(s, (struct sockaddr *)&a, sizeof a) < 0) {
close(s); R -1;
}
if (listen(s, 16) < 0) {
close(s); R -1;
}
R s;
}
I k10_tcp_accept(I s) {
struct sockaddr_in a; uI l = sizeof a;
I fd = accept(s, (struct sockaddr *)&a, &l);
if (fd >= 0) {
I one = 1;
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, 4);
}
R fd;
}
V k10_prompt(void) { write_cstr_stderr("K10) "); }
V k10_cont(void) { write_cstr_stderr(" "); }
I k10_add_sat(I a, I b) {
J r = (J)a + b;
if (r > 2147483647) R 2147483647;
if (r < -2147483648LL) R -2147483648LL;
R (I)r;
}
I k10_sub_sat(I a, I b) {
J r = (J)a - b;
if (r > 2147483647) R 2147483647;
if (r < -2147483648LL) R -2147483648LL;
R (I)r;
}
I k10_mul_sat(I a, I b) {
J r = (J)a * b;
if (r > 2147483647) R 2147483647;
if (r < -2147483648LL) R -2147483648LL;
R (I)r;
}
uJ k10_up_pow2(uJ v) {
if (!v) R 1;
v--;
v |= v >> 1; v |= v >> 2; v |= v >> 4;
v |= v >> 8; v |= v >> 16; v |= v >> 32;
R v + 1;
}
uI k10_log2(uJ v) {
R (uI)(63 - __builtin_clzll(v | 1));
}
uI k10_ceil_log2(uJ v) {
R k10_log2(v - 1) + 1;
}
I k10_ends(S v, const char *s) {
uJ n = XN(v), m = strlen(s);
if (n < m) R 0;
R !memcmp(v + n - m, s, m);
}
I k10_starts(S v, const char *p) {
uJ n = XN(v), m = strlen(p);
if (n < m) R 0;
R !memcmp(v, p, m);
}
I k10_has_b(S v, char b) {
uJ n = XN(v);
R !!memchr(v, (G)b, n);
}
J *k10_add_j(J *a, J *b) {
if (!a || (uJ)a < 256) R b;
if (!b || (uJ)b < 256) R a;
uJ n = XN(a);
J *r = allocate_typed_vector(K_TYPE_LONG, n);
for (uJ i = 0; i < n; i++) r[i] = a[i] + b[i];
release_object((V **)a); release_object((V **)b); R r;
}
J *k10_sub_j(J *a, J *b) {
if (!a || (uJ)a < 256) R b;
if (!b || (uJ)b < 256) R a;
uJ n = XN(a);
J *r = allocate_typed_vector(K_TYPE_LONG, n);
for (uJ i = 0; i < n; i++) r[i] = a[i] - b[i];
release_object((V **)a); release_object((V **)b); R r;
}
J *k10_mul_j(J *a, J *b) {
uJ n = XN(a);
J *r = allocate_typed_vector(K_TYPE_LONG, n);
for (uJ i = 0; i < n; i++) r[i] = a[i] * b[i];
release_object((V **)a); release_object((V **)b); R r;
}
J *k10_div_j(J *a, J *b) {
uJ n = XN(a);
J *r = allocate_typed_vector(K_TYPE_LONG, n);
for (uJ i = 0; i < n; i++)
r[i] = b[i] ? a[i] / b[i] : INT64_MIN;
release_object((V **)a); release_object((V **)b); R r;
}
F *k10_add_f(F *a, F *b) {
uJ n = XN(a);
F *r = (F *)allocate_typed_vector(K_TYPE_FLOAT, n);
for (uJ i = 0; i < n; i++) r[i] = a[i] + b[i];
release_object((V **)a); release_object((V **)b); R r;
}
F *k10_sub_f(F *a, F *b) {
uJ n = XN(a);
F *r = (F *)allocate_typed_vector(K_TYPE_FLOAT, n);
for (uJ i = 0; i < n; i++) r[i] = a[i] - b[i];
release_object((V **)a); release_object((V **)b); R r;
}
F *k10_mul_f(F *a, F *b) {
uJ n = XN(a);
F *r = (F *)allocate_typed_vector(K_TYPE_FLOAT, n);
for (uJ i = 0; i < n; i++) r[i] = a[i] * b[i];
release_object((V **)a); release_object((V **)b); R r;
}
F *k10_div_f(F *a, F *b) {
uJ n = XN(a);
F *r = (F *)allocate_typed_vector(K_TYPE_FLOAT, n);
for (uJ i = 0; i < n; i++) r[i] = a[i] / b[i];
release_object((V **)a); release_object((V **)b); R r;
}
J *k10_lt_j(J *a, J *b) {
uJ n = XN(a);
J *r = allocate_zero_filled_typed(
K_TYPE_BOOL, n);
for (uJ i = 0; i < n; i++)
if (a[i] < b[i]) ((S)r)[i] = 1;
release_object((V **)a); release_object((V **)b); R r;
}
J *k10_eq_j(J *a, J *b) {
uJ n = XN(a);
J *r = allocate_zero_filled_typed(
K_TYPE_BOOL, n);
for (uJ i = 0; i < n; i++)
if (a[i] == b[i]) ((S)r)[i] = 1;
release_object((V **)a); release_object((V **)b); R r;
}
J *k10_csv_add(J *r, S s, I n) {
V *c = allocate_typed_vector_init(1, n, s);
R (J *)list_append_value((V **)&r, c, 0);
}
static J *k10_csv_step(J *r, S s,
I *p, I i, I *q) {
if (s[i] == '"') *q = !(*q);
if (s[i] == ',' && !(*q)) {
r = k10_csv_add(r, s + *p, i - *p);
*p = i + 1;
}
return r;
}
J *k10_csv_split(S s, I n) {
J *r = allocate_typed_vector(K_TYPE_LIST, 0);
I q = 0, p = 0;
for (I i = 0; i < n; i++)
r = k10_csv_step(r, s, &p, i, &q);
if (p < n) r = k10_csv_add(r, s + p, n - p);
R r;
}
J *k10_csv_emit(V **v, char s) {
J *r = allocate_typed_vector(K_TYPE_PAIR_CHAIN, 0);
uJ n = XN(v);
for (uJ i = 0; i < n; i++) {
if (i)
r = (J *)charvec_append_byte((V **)r, s);
r = (J *)concat_charvecs((V **)r, (S)v[i]);
}
R r;
}
J *k10_json_j(J v) {
char b[32];
I n = sprintf(b, "%lld", (long long)v);
R (J *)allocate_typed_vector_init(
1, n, b);
}
J *k10_json_f(F v) {
char b[32];
I n = sprintf(b, "%.16g", v);
R (J *)allocate_typed_vector_init(
1, n, b);
}
J *k10_esc_c(J *r, char a, char b) {
r = (J *)charvec_append_byte((V **)r, a);
R (J *)charvec_append_byte((V **)r, b);
}
J *k10_json_hex(J *r, char c) {
char e[8];
I l = sprintf(e, "\\u%04x", (G)c);
for (I j = 0; j < l; j++)
r = (J *)charvec_append_byte((V **)r, e[j]);
R r;
}
J *k10_json_esc(J *r, char c) {
if (c == '"' || c == '\\')
R k10_esc_c(r, '\\', c);
if (c == '\n') R k10_esc_c(r, '\\', 'n');
if (c == '\t') R k10_esc_c(r, '\\', 't');
if ((G)c < K_ASCII_SPACE) R k10_json_hex(r, c);
R (J *)charvec_append_byte((V **)r, c);
}
J *k10_json_s(S v) {
uJ n = XN(v);
J *r = allocate_typed_vector(K_TYPE_PAIR_CHAIN, 0);
r = (J *)charvec_append_byte((V **)r, '"');
for (uJ i = 0; i < n; i++)
r = k10_json_esc(r, v[i]);
r = (J *)charvec_append_byte((V **)r, '"');
R r;
}
J *k10_read_f(I f, I s) {
J *r = allocate_typed_vector(K_TYPE_PAIR_CHAIN, s);
ssize_t n = read(f, r, (size_t)s);
if (n < 0) { release_object((V **)r); R (J *)5; }
XN(r) = (I)n;
R r;
}
J *k10_read(const char *p) {
I f = open(p, O_RDONLY);
if (f < 0) R (J *)5;
struct stat s;
if (fstat(f, &s) < 0) {
close(f); R (J *)5;
}
J *r = k10_read_f(f, (I)s.st_size);
close(f); R r;
}
J k10_write_path(const char *p, S v) {
I f = open(p, O_WRONLY|O_CREAT|O_TRUNC, 0644);
if (f < 0) R 5;
uJ n = XN(v);
ssize_t w = write(f, v, n);
close(f); R (w < 0 || (uJ)w != n) ? 5 : 0;
}
J k10_append(const char *p, S v) {
I f = open(p, O_WRONLY|O_CREAT|O_APPEND, 0644);
if (f < 0) R 5;
uJ n = XN(v);
ssize_t w = write(f, v, n);
close(f); R (w < 0 || (uJ)w != n) ? 5 : 0;
}
J k10_spawn(const char *c, S const v[]) {
pid_t p = fork();
if (p < 0) R 5;
if (!p) { execvp(c, (char *const *)v); _exit(1); }
I s; waitpid(p, &s, 0);
R (J)WEXITSTATUS(s);
}
uJ k10_mono(void) {
struct timespec t;
clock_gettime(CLOCK_MONOTONIC, &t);
R (uJ)t.tv_sec * NS_PER_SEC + (uJ)t.tv_nsec;
}
uJ k10_real(void) {
struct timespec t;
clock_gettime(CLOCK_REALTIME, &t);
R (uJ)t.tv_sec * NS_PER_SEC + (uJ)t.tv_nsec;
}
J *k10_mod_j(J *a, J *b) {
uJ n = XN(a);
J *r = allocate_typed_vector(K_TYPE_LONG, n);
for (uJ i = 0; i < n; i++)
r[i] = b[i] ? a[i] % b[i] : INT64_MIN;
release_object((V **)a); release_object((V **)b); R r;
}
J *k10_min_j(J *a, J *b) {
uJ n = XN(a);
J *r = allocate_typed_vector(K_TYPE_LONG, n);
for (uJ i = 0; i < n; i++) r[i] = a[i] < b[i] ? a[i] : b[i];
release_object((V **)a); release_object((V **)b); R r;
}
J *k10_max_j_p(J *a, J *b) {
uJ n = XN(a);
J *r = allocate_typed_vector(K_TYPE_LONG, n);
for (uJ i = 0; i < n; i++) r[i] = a[i] > b[i] ? a[i] : b[i];
release_object((V **)a); release_object((V **)b); R r;
}
J *k10_and_j(J *a, J *b) {
uJ n = XN(a);
J *r = allocate_typed_vector(K_TYPE_LONG, n);
for (uJ i = 0; i < n; i++) r[i] = a[i] & b[i];
release_object((V **)a); release_object((V **)b); R r;
}
J *k10_or_j(J *a, J *b) {
uJ n = XN(a);
J *r = allocate_typed_vector(K_TYPE_LONG, n);
for (uJ i = 0; i < n; i++) r[i] = a[i] | b[i];
release_object((V **)a); release_object((V **)b); R r;
}
J *k10_xor_j(J *a, J *b) {
uJ n = XN(a);
J *r = allocate_typed_vector(K_TYPE_LONG, n);
for (uJ i = 0; i < n; i++) r[i] = a[i] ^ b[i];
release_object((V **)a); release_object((V **)b); R r;
}
J *k10_shl_j(J *a, J *b) {
uJ n = XN(a);
J *r = allocate_typed_vector(K_TYPE_LONG, n);
for (uJ i = 0; i < n; i++) {
I ok = (b[i] >= 0 && b[i] < 64);
r[i] = ok ? a[i] << b[i] : 0;
}
release_object((V **)a); release_object((V **)b); R r;
}
J *k10_shr_j(J *a, J *b) {
uJ n = XN(a);
J *r = allocate_typed_vector(K_TYPE_LONG, n);
for (uJ i = 0; i < n; i++) {
I ok = (b[i] >= 0 && b[i] < 64);
r[i] = ok ? a[i] >> b[i] : 0;
}
release_object((V **)a); release_object((V **)b); R r;
}
uJ k10_where_w(J *r, uJ j, uJ v, uJ o, uJ n) {
while (v) {
I b = __builtin_ctzll(v);
if (o + b < n) r[j++] = (J)(o + b);
v &= v - 1;
}
R j;
}
J *k10_where(J *x) {
uJ n = XN(x), p = (uJ)popcount_bool_vec(x);
J *r = allocate_typed_vector(K_TYPE_LONG, p);
uJ j = 0, nw = (n + 63) >> 6;
for (uJ w = 0; w < nw; w++)
j = k10_where_w(r, j, ((uJ *)x)[w], w << 6, n);
release_object((V **)x); R r;
}
I k10_has_j(J *v, J x) {
uJ n = XN(v);
for (uJ i = 0; i < n; i++) if (v[i] == x) R 1;
R 0;
}
J *k10_distinct_j(J *v) {
uJ n = XN(v);
J *r = allocate_typed_vector(K_TYPE_LONG, 0);
for (uJ i = 0; i < n; i++)
if (!k10_has_j(r, v[i]))
r = (J *)list_append_value(
(V **)&r, (V *)v[i], 0);
release_object((V **)v); R r;
}
V k10_rev_j(J *p, uJ n) {
for (uJ i = 0; i < n/2; i++) {
J t = p[i]; p[i] = p[n-1-i]; p[n-1-i] = t;
}
}
V k10_rev_i(I *p, uJ n) {
for (uJ i = 0; i < n/2; i++) {
I t = p[i]; p[i] = p[n-1-i]; p[n-1-i] = t;
}
}
V k10_rev_h(I16 *p, uJ n) {
for (uJ i = 0; i < n/2; i++) {
I16 t = p[i]; p[i] = p[n-1-i]; p[n-1-i] = t;
}
}
V k10_rev_b(S p, uJ n) {
for (uJ i = 0; i < n/2; i++) {
char t = p[i]; p[i] = p[n-1-i]; p[n-1-i] = t;
}
}
V k10_rev_v(V **p, uJ n) {
for (uJ i = 0; i < n/2; i++) {
V *t = p[i]; p[i] = p[n-1-i]; p[n-1-i] = t;
}
}
static V k10_rev_sw(V **r, G t, uJ n) {
if (t == K_TYPE_LONG) k10_rev_j((J *)r, n);
else if (t == K_TYPE_INT) k10_rev_i((I *)r, n);
else if (t == K_TYPE_SHORT) k10_rev_h((I16 *)r, n);
else if (t == K_TYPE_PAIR_CHAIN ||
t == K_TYPE_CHAR) k10_rev_b((S)r, n);
else k10_rev_v((V **)r, n);
}
V *k10_rev(V *v) {
V **r = clone_or_recycle_header((V **)v);
k10_rev_sw(r, XT(v), XN(v));
R r;
}
J *k10_take(I n, V *v) {
R reshape_or_take(n, (J *)v);
}
J *k10_drop(I n, V *v) {
uJ l = XN(v);
I s = (n < 0) ? 0 : (n > (I)l ? (I)l : n);
R slice_into_new_slot(
s, (I)l - s, (J *)v);
}
J runtime_rng_state = 0x100000000ULL;
uJ k10_rng(void) {
uJ x = (uJ)runtime_rng_state;
if (!x) x = 0xdeadbeefcafebabeULL;
x ^= x << 13; x ^= x >> 7; x ^= x << 17;
runtime_rng_state = (J)x; R x;
}
J *k10_rand_n(I n) {
uJ c = (uJ)((n < 0) ? -n : n);
J *r = allocate_typed_vector(K_TYPE_LONG, (I)c);
for (uJ i = 0; i < c; i++) {
uJ v = k10_rng() & 0x7fffffffffffffffULL;
r[i] = (J)v;
}
R r;
}
J *k10_rand_m(I n, J x) {
if (x <= 0) R k10_rand_n(n);
J *r = allocate_typed_vector(K_TYPE_LONG, n);
for (I i = 0; i < n; i++)
r[i] = (J)(k10_rng() % (uJ)x);
R r;
}
J *k10_group_one(J *v, uJ n, J k) {
J *r = allocate_typed_vector(K_TYPE_LONG, 0);
for (uJ j = 0; j < n; j++)
if (v[j] == k)
r = (J *)list_append_value(
(V **)&r, (V *)j, 0);
R r;
}
static V k10_group_loop(J *v, uJ n,
J *u, J *vs, uJ k) {
for (uJ i = 0; i < k; i++)
vs[i] = (J)k10_group_one(v, n, u[i]);
}
J *k10_group_j(J *v) {
uJ n = XN(v);
J *u = k10_distinct_j((J *)retain_object(v));
uJ k = XN(u);
J *vs = allocate_typed_vector(K_TYPE_LIST, (I)k);
k10_group_loop(v, n, u, vs, k);
release_object((V **)v);
R (J *)pair_cell_make(
K_TYPE_KEYED_PAIR, (J)u, vs);
}
J *k10_lower(S v) {
uJ n = XN(v);
J *r = allocate_typed_vector(K_TYPE_PAIR_CHAIN, (I)n);
for (uJ i = 0; i < n; i++) {
char c = v[i];
((S)r)[i] = (c >= 'A' && c <= 'Z') ? c + 32 : c;
}
R r;
}
J *k10_upper(S v) {
uJ n = XN(v);
J *r = allocate_typed_vector(K_TYPE_PAIR_CHAIN, (I)n);
for (uJ i = 0; i < n; i++) {
char c = v[i];
((S)r)[i] = (c >= 'a' && c <= 'z') ? c - 32 : c;
}
R r;
}
I k10_is_sp(char c) {
R c == ' ' || c == '\t' || c == '\n';
}
J *k10_trim_s(S v) {
uJ n = XN(v), s = 0, e = n;
while (s < n && k10_is_sp(v[s])) s++;
while (e > s && k10_is_sp(v[e-1])) e--;
R (J *)allocate_typed_vector_init(
1, e-s, v+s);
}
J k10_over(K_dyadic_atom_fn f, J *v) {
uJ n = XN(v); if (!n) R 0;
J a = v[0];
for (uJ i = 1; i < n; i++) a = f(a, v[i]);
R a;
}
J k10_over_s(K_dyadic_atom_fn f, J s, J *v) {
uJ n = XN(v), a = s;
for (uJ i = 0; i < n; i++) a = f(a, v[i]);
R a;
}
J *k10_scan_fn(K_dyadic_atom_fn f, J *v) {
uJ n = XN(v); J *r = allocate_typed_vector(K_TYPE_LONG, (I)n);
if (!n) R r;
r[0] = v[0];
for (uJ i = 1; i < n; i++) r[i] = f(r[i-1], v[i]);
R r;
}
J *k10_prior(K_dyadic_atom_fn f, J *v) {
uJ n = XN(v); J *r = allocate_typed_vector(K_TYPE_LONG, (I)n);
if (!n) R r;
r[0] = v[0];
for (uJ i = 1; i < n; i++) r[i] = f(v[i], v[i-1]);
R r;
}
J k10_fix(K_unary_atom_fn f, J s, I m) {
J c = s;
for (I i = 0; i < m; i++) {
J n = f(c); if (n == c) R c;
c = n;
}
R c;
}
I k10_part_j(J *p, I l, I h) {
J v = p[l + (h - l) / 2];
I i = l - 1, j = h + 1;
while (1) {
do { i++; } while (p[i] < v);
do { j--; } while (p[j] > v);
if (i >= j) R j;
J t = p[i]; p[i] = p[j]; p[j] = t;
}
}
V k10_qs_j_r(J *p, I l, I h) {
while (l < h) {
I j = k10_part_j(p, l, h);
if (j - l < h - j) {
k10_qs_j_r(p, l, j); l = j+1;
} else {
k10_qs_j_r(p, j + 1, h); h = j;
}
}
}
V k10_qs_j(J *p, I n) {
if (n > 1) k10_qs_j_r(p, 0, n - 1);
}
I k10_part_f(F *p, I l, I h) {
F v = p[l + (h - l) / 2];
I i = l - 1, j = h + 1;
while (1) {
do { i++; } while (p[i] < v);
do { j--; } while (p[j] > v);
if (i >= j) R j;
F t = p[i]; p[i] = p[j]; p[j] = t;
}
}
V k10_qs_f_r(F *p, I l, I h) {
while (l < h) {
I j = k10_part_f(p, l, h);
if (j - l < h - j) {
k10_qs_f_r(p, l, j); l = j+1;
} else {
k10_qs_f_r(p, j + 1, h); h = j;
}
}
}
V k10_qs_f(F *p, I n) {
if (n > 1) k10_qs_f_r(p, 0, n - 1);
}
static I k10_node_cmp(const V *a, const V *b) {
const GradeNode *x = a, *y = b;
if (x->value != y->value)
R x->value < y->value ? -1 : 1;
R x->orig_idx - y->orig_idx;
}
V k10_grade_fill(GradeNode *d, J *v, uJ n) {
for (uJ i = 0; i < n; i++) {
d[i].value = v[i]; d[i].orig_idx = (I)i;
}
}
J *k10_grade_out(GradeNode *d, uJ n) {
J *r = allocate_typed_vector(K_TYPE_LONG, (I)n);
for (uJ i = 0; i < n; i++) r[i] = d[i].orig_idx;
R r;
}
J *k10_grade_up(J *v) {
uJ n = XN(v);
GradeNode *d = malloc(n * sizeof(GradeNode));
k10_grade_fill(d, v, n);
qsort(d, n, sizeof(GradeNode), k10_node_cmp);
J *r = k10_grade_out(d, n);
free(d); release_object((V **)v); R r;
}
uJ k10_hash_j(J k) {
uJ h = 0xcbf29ce484222325ULL, v = (uJ)k;
for (I i = 0; i < 8; i++) {
h ^= (v & K_BYTE_MAX); h *= 0x100000001b3ULL; v >>= 8;
}
R h;
}
uJ k10_hash_s(const char *s, I n) {
uJ h = 0xcbf29ce484222325ULL;
for (I i = 0; i < n; i++) {
h ^= (G)s[i]; h *= 0x100000001b3ULL;
}
R h;
}
J k10_sum_j(J *v) {
uJ n = XN(v); J s = 0;
for (uJ i = 0; i < n; i++) s += v[i];
R s;
}
F k10_avg_j(J *v) {
uJ n = XN(v); if (!n) R 0.0;
R (F)k10_sum_j(v) / (F)n;
}
F k10_var_j(J *v) {
uJ n = XN(v); if (!n) R 0.0;
F m = k10_avg_j(v), s = 0.0;
for (uJ i = 0; i < n; i++) {
F d = (F)v[i] - m; s += d * d;
}
R s / (F)n;
}
F k10_dev_j(J *v) {
R sqrt(k10_var_j(v));
}
J *k10_roll_sum(J *v, I w) {
uJ n = XN(v); J *r = allocate_typed_vector(K_TYPE_LONG, (I)n);
J a = 0;
for (uJ i = 0; i < n; i++) {
a += v[i];
if ((I)i >= w) a -= v[i - w];
r[i] = a;
}
R r;
}
J k10_roll_m1(J *v, I i, I w) {
J m = v[i]; I s = i - w + 1;
if (s < 0) s = 0;
for (I j = s; j < i; j++)
if (v[j] > m) m = v[j];
R m;
}
J *k10_roll_max(J *v, I w) {
uJ n = XN(v); J *r = allocate_typed_vector(K_TYPE_LONG, (I)n);
for (uJ i = 0; i < n; i++) r[i] = k10_roll_m1(v, (I)i, w);
R r;
}
J *k10_union(J *a, J *b) {
uJ na = XN(a), nb = XN(b);
J *r = allocate_typed_vector(K_TYPE_LONG, 0);
for (uJ i = 0; i < na; i++)
r = (J *)list_append_value((V **)&r, (V *)a[i], 0);
for (uJ i = 0; i < nb; i++)
if (!k10_has_j(a, b[i]))
r = (J *)list_append_value((V **)&r, (V *)b[i], 0);
release_object((V **)a); release_object((V **)b); R r;
}
J *k10_inter(J *a, J *b) {
uJ na = XN(a); J *r = allocate_typed_vector(K_TYPE_LONG, 0);
for (uJ i = 0; i < na; i++)
if (k10_has_j(b, a[i]))
r = (J *)list_append_value((V **)&r, (V *)a[i], 0);
release_object((V **)a); release_object((V **)b); R r;
}
J *k10_diff(J *a, J *b) {
uJ na = XN(a); J *r = allocate_typed_vector(K_TYPE_LONG, 0);
for (uJ i = 0; i < na; i++)
if (!k10_has_j(b, a[i]))
r = (J *)list_append_value((V **)&r, (V *)a[i], 0);
release_object((V **)a); release_object((V **)b); R r;
}
F *k10_sqrt(F *v) {
uJ n = XN(v); F *r = (F *)allocate_typed_vector(K_TYPE_FLOAT, (I)n);
for (uJ i = 0; i < n; i++) r[i] = sqrt(v[i]);
release_object((V **)v); R r;
}
F *k10_sin(F *v) {
uJ n = XN(v); F *r = (F *)allocate_typed_vector(K_TYPE_FLOAT, (I)n);
for (uJ i = 0; i < n; i++) r[i] = sin(v[i]);
release_object((V **)v); R r;
}
F *k10_cos(F *v) {
uJ n = XN(v); F *r = (F *)allocate_typed_vector(K_TYPE_FLOAT, (I)n);
for (uJ i = 0; i < n; i++) r[i] = cos(v[i]);
release_object((V **)v); R r;
}
F *k10_exp(F *v) {
uJ n = XN(v); F *r = (F *)allocate_typed_vector(K_TYPE_FLOAT, (I)n);
for (uJ i = 0; i < n; i++) r[i] = exp(v[i]);
release_object((V **)v); R r;
}
F *k10_log(F *v) {
uJ n = XN(v); F *r = (F *)allocate_typed_vector(K_TYPE_FLOAT, (I)n);
for (uJ i = 0; i < n; i++) r[i] = log(v[i]);
release_object((V **)v); R r;
}
F *k10_vec_abs_f(F *v) {
I n = *(I *)((char *)v - 4);
F *o = (F *)allocate_typed_vector(K_TYPE_FLOAT, n);
for (I i = 0; i < n; i++) o[i] = fabs(v[i]);
release_object((V **)v); R o;
}
F *k10_vec_pow_f(F *b, F *e) {
I n = *(I *)((char *)b - 4);
F *o = (F *)allocate_typed_vector(K_TYPE_FLOAT, n);
for (I i = 0; i < n; i++)
o[i] = pow(b[i], e[i]);
release_object((V **)b); release_object((V **)e); R o;
}
J *k10_vec_abs_i(J *v) {
I n = *(I *)((char *)v - 4);
J *o = allocate_typed_vector(K_TYPE_LONG, n);
for (I i = 0; i < n; i++)
o[i] = v[i] < 0 ? -v[i] : v[i];
release_object((V **)v); R o;
}
J *k10_vec_neg_i(J *v) {
I n = *(I *)((char *)v - 4);
J *o = allocate_typed_vector(K_TYPE_LONG, n);
for (I i = 0; i < n; i++) o[i] = -v[i];
release_object((V **)v); R o;
}
J *k10_dict_make(V **k, V **v) {
R (J *)pair_cell_make(
K_TYPE_KEYED_PAIR, (J)k, (J *)v);
}
J *k10_dict_keys(J *d) {
if (*(G *)((char *)d - 5) != K_TYPE_KEYED_PAIR)
R (J *)6;
R (J *)retain_object((V *)*d);
}
J *k10_dict_vals(J *d) {
if (*(G *)((char *)d - 5) != K_TYPE_KEYED_PAIR)
R (J *)6;
R (J *)retain_object((V *)d[1]);
}
J k10_dict_at_i(J *d, J k) {
if (*(G *)((char *)d - 5) != K_TYPE_KEYED_PAIR)
R 0;
J *ks = (J *)*d, *vs = (J *)d[1];
uJ n = (uJ)*(I *)(ks - 4);
for (uJ i = 0; i < n; i++)
if (ks[i] == k) R vs[i];
R 0;
}
static J *k10_dict_grow_i(J *ks,
J *vs, J k, J v) {
ks = (J *)list_append_value((V **)ks,
(J *)k, 0);
vs = (J *)list_append_value((V **)vs,
(J *)v, 0);
R (J *)pair_cell_make(
K_TYPE_KEYED_PAIR, (J)ks, vs);
}
J *k10_dict_set_i(J *d, J k, J v) {
J *ks = (J *)*d, *vs = (J *)d[1];
uJ n = (uJ)*(I *)(ks - 4);
for (uJ i = 0; i < n; i++)
if (ks[i] == k) { vs[i] = v; R d; }
R k10_dict_grow_i(ks, vs, k, v);
}
I k10_tbl_rows(J *t) {
J *cs = (J *)t[1];
I n = *(I *)((char *)cs - 4);
if (n == 0) R 0;
R *(I *)(cs[0] - 4);
}
I k10_tbl_cols(J *t) {
R *(I *)(t[1] - 4);
}
J *k10_tbl_col(J *t, J k) {
J *ks = (J *)*t, *vs = (J *)t[1];
uJ n = (uJ)*(I *)(ks - 4);
for (uJ i = 0; i < n; i++)
if (ks[i] == k) R (J *)vs[i];
R NULL;
}
J *k10_tbl_filter(J *t, J *m) {
J *ks = (J *)retain_object((V *)*t);
J *cs = (J *)t[1];
uJ nc = (uJ)*(I *)(cs - 4);
J *o = allocate_typed_vector(K_TYPE_LIST, (I)nc);
for (uJ i = 0; i < nc; i++) {
J *c = (J *)cs[i];
J *idx = monadic_where_indices(retain_object(m));
o[i] = (J)index_at_vector(c, idx);
}
release_object((V **)m); R (J *)pair_cell_make(
K_TYPE_KEYED_PAIR, (J)ks, o);
}
static V k10_tbl_sel_step(J *aks, J *acs,
J *nks, J *ncs, uJ na, J w, uJ i) {
nks[i] = w; ncs[i] = 0;
for (uJ j = 0; j < na; j++)
if (aks[j] == w) {
ncs[i] = (J)retain_object((V *)acs[j]); break;
}
}
J *k10_tbl_select(J *t, J *s) {
J *aks = (J *)*t, *acs = (J *)t[1];
uJ n = (uJ)*(I *)(s - 4);
J *nks = allocate_typed_vector(2, (I)n);
J *ncs = allocate_typed_vector(K_TYPE_LIST, (I)n);
uJ na = (uJ)*(I *)(aks - 4);
for (uJ i = 0; i < n; i++)
k10_tbl_sel_step(aks, acs, nks, ncs, na, s[i], i);
R (J *)pair_cell_make(
K_TYPE_KEYED_PAIR, (J)nks, ncs);
}
J *symbol_intern_charvec_view(const char *n, I l) {
return (J *)(uintptr_t)symbol_intern_or_get(n, l);
}
#define symbol_intern_charvec_str symbol_intern_charvec_view
J *k10_fs_ls(const char *p) {
extern V *opendir(const char *);
extern V *readdir(V *);
extern I closedir(V *);
V *d = opendir(p); if (!d) R (J *)5;
J *o = allocate_typed_vector(K_TYPE_LIST, 0); V *e;
while ((e = readdir(d))) {
const char *n = (const char *)e + 19;
if (n[0] == '.' && (n[1] == 0 || (n[1] == '.' &&
n[2] == 0))) continue;
o = (J *)list_append_value((V **)o,
(J *)allocate_typed_vector(K_TYPE_PAIR_CHAIN,
(I)strlen(n)), 0);
}
closedir(d); R o;
}
I k10_fs_exists(const char *p) {
struct stat s; R stat(p, &s) == 0;
}
J k10_fs_size(const char *p) {
struct stat s; if (stat(p, &s) < 0) R -1;
R (J)s.st_size;
}
I k10_fs_rm(const char *p) { R unlink(p); }
I k10_fs_mv(const char *s, const char *d) {
extern I rename(const char *, const char *);
R rename(s, d);
}
J *k10_sym_intern_str(const char *n, I l) {
R (J *)allocate_typed_vector(2, l);
}
J *k10_trace_pre(J *v) {
if (!K_IS_ERR_RETURN(v))
println_object((V **)v);
R v;
}
J *k10_trace_post(J *v) {
if (!K_IS_ERR_RETURN(v))
println_object((V **)v);
R v;
}
static uI k10_lex_skip_ws(const char *s,
uI p, uI e) {
while (p < e && (s[p] == ' ' || s[p] == '\t'))
p++;
R p;
}
static TokenSpan k10_lex_ident(const char *s,
uI p, uI e) {
TokenSpan t; t.start = p;
while (p < e && is_alpha_or_digit(s[p])) p++;
t.kind = 1; t.end = p; R t;
}
static TokenSpan k10_lex_num_span(const char *s,
uI p, uI e) {
TokenSpan t; t.start = p;
while (p < e && (is_decimal_digit(s[p]) ||
s[p] == '.' || s[p] == 'e' || s[p] == 'E' ||
s[p] == '-')) p++;
t.kind = 2; t.end = p; R t;
}
static TokenSpan k10_lex_str(const char *s,
uI p, uI e) {
TokenSpan t; t.start = p++;
while (p < e && s[p] != '"') {
if (s[p] == '\\' && p + 1 < e) p++;
p++;
}
if (p < e) p++;
t.kind = 3; t.end = p; R t;
}
TokenSpan k10_lex_next(const char *s,
uI p, uI e) {
p = k10_lex_skip_ws(s, p, e);
if (p >= e) R (TokenSpan){p, p, 0};
G b = (G)s[p];
if (is_alpha_lower(b) || b == '_')
R k10_lex_ident(s, p, e);
if (is_decimal_digit(b))
R k10_lex_num_span(s, p, e);
if (b == '"') R k10_lex_str(s, p, e);
I k = (b=='\'' || b=='/' || b=='\\') ? 5 : 4;
R (TokenSpan){p, p + 1, k};
}
const char *k10_lex_name_str(I k) {
if (k == 1) R "ident";
if (k == 2) R "number";
if (k == 3) R "string";
if (k == 4) R "verb";
if (k == 5) R "adverb";
R "eof";
}
I k10_re_match_at(const char *p, I np,
const char *t, I o, I n) {
if (o + np > n) R 0;
for (I i = 0; i < np; i++)
if (p[i] != t[o + i]) R 0;
R 1;
}
I k10_re_glob(const char *p, I np,
const char *t, I n) {
I pi = 0, ti = 0, st = -1, m = 0;
while (ti < n) {
if (pi < np && p[pi] == '?') { pi++; ti++; }
else if (pi < np && p[pi] == '*') {
st = pi++; m = ti;
} else if (pi < np && p[pi] == t[ti]) {
pi++; ti++;
} else if (st != -1) {
pi = st + 1; ti = ++m;
} else R 0;
}
while (pi < np && p[pi] == '*') pi++;
R pi == np;
}
I k10_str_find(const char *t, I n,
const char *ndl, I k) {
if (k == 0) R 0;
for (I i = 0; i + k <= n; i++) {
I m = 1;
for (I j = 0; j < k; j++)
if (t[i + j] != ndl[j]) { m = 0; break; }
if (m) R i;
}
R -1;
}
J *k10_str_replace(const char *s, I sn,
const char *f, I fn, const char *t, I tn) {
J *o = allocate_typed_vector(K_TYPE_PAIR_CHAIN, 0); I i = 0;
while (i < sn) {
if (fn > 0 && i + fn <= sn &&
k10_re_match_at(f, fn, s, i, sn)) {
for (I j = 0; j < tn; j++)
o = (J *)charvec_append_byte((V **)o, t[j]);
i += fn;
} else {
o = (J *)charvec_append_byte((V **)o, s[i]);
i++;
}
}
R o;
}
static struct ipc_client_state *k10_ipc_client_get(I fd) {
if (fd < 0 || fd >= IPC_MAX_CLIENTS) R NULL;
if (ipc_client_table[fd] == NULL) {
struct ipc_client_state *c =
calloc(1, sizeof *c);
if (c == NULL) R NULL;
c->fd = fd; ipc_client_table[fd] = c;
}
R ipc_client_table[fd];
}
static V k10_ipc_client_close(I ep, I fd) {
struct ipc_client_state *c =
(fd >= 0 && fd < IPC_MAX_CLIENTS) ?
ipc_client_table[fd] : NULL;
if (c != NULL) {
if (c->body != NULL) free(c->body);
struct ipc_send_chunk *s = c->send_head;
while (s != NULL) {
struct ipc_send_chunk *nx = s->next;
free(s); s = nx;
}
free(c); ipc_client_table[fd] = NULL;
}
epoll_ctl(ep, EPOLL_CTL_DEL, fd, NULL); close(fd);
}
static I k10_ipc_send_q(I fd, const char *p,
I len, I off, struct ipc_client_state *c, I ep) {
I rem = len - off;
struct ipc_send_chunk *chk =
malloc(sizeof(*chk) + (size_t)rem);
if (chk == NULL) R -1;
chk->next = NULL; chk->len = rem; chk->off = 0;
memcpy(chk->data, p + off, (size_t)rem);
if (c->send_tail) c->send_tail->next = chk;
else c->send_head = chk;
c->send_tail = chk;
struct epoll_event ev = {EPOLLIN | EPOLLOUT, {.fd = fd}};
epoll_ctl(ep, EPOLL_CTL_MOD, fd, &ev); R 0;
}
static I k10_ipc_send_ev(I ep, I fd,
const V *data, I len) {
struct ipc_client_state *c = k10_ipc_client_get(fd);
if (c == NULL) R -1;
const char *p = (const char *)data; I off = 0;
if (c->send_head == NULL) {
while (off < len) {
ssize_t w = write(fd, p + off, (size_t)(len - off));
if (w > 0) { off += (I)w; continue; }
if (w < 0 && (errno == EAGAIN ||
errno == EWOULDBLOCK)) break;
R -1;
}
}
if (off < len) R k10_ipc_send_q(fd, p, len, off, c, ep);
R 0;
}
static I k10_ipc_flush(I ep, I fd) {
struct ipc_client_state *c = ipc_client_table[fd];
if (c == NULL) R -1;
while (c->send_head != NULL) {
struct ipc_send_chunk *s = c->send_head;
ssize_t w = write(fd, s->data + s->off,
(size_t)(s->len - s->off));
if (w > 0) {
s->off += (I)w;
if (s->off == s->len) {
c->send_head = s->next;
if (c->send_head == NULL) c->send_tail = NULL;
free(s);
}
continue;
}
if (w < 0 && (errno == EAGAIN ||
errno == EWOULDBLOCK)) R 0;
R -1;
}
struct epoll_event ev = {EPOLLIN, {.fd = fd}};
epoll_ctl(ep, EPOLL_CTL_MOD, fd, &ev); R 0;
}
I ipc_dispatch_request_buffered(I client_fd, V *frame, I len, I epfd) {
(void)epfd;
if (!frame || len <= 0) return -1;
return send_framed_to_fd(client_fd, frame);
}
static I k10_ipc_recv_hdr(I fd,
struct ipc_client_state *c) {
ssize_t r = read(fd, ((char *)&c->hdr) + c->have_hdr,
(size_t)(8 - c->have_hdr));
if (r > 0) { c->have_hdr += (I)r; R 1; }
if (r < 0 && (errno == EAGAIN ||
errno == EWOULDBLOCK)) R 0;
R -1;
}
static I k10_ipc_recv_body(I fd,
struct ipc_client_state *c) {
ssize_t r = read(fd, c->body + c->have_body,
(size_t)(c->body_len - c->have_body));
if (r > 0) { c->have_body += r; R 1; }
if (r < 0 && (errno == EAGAIN ||
errno == EWOULDBLOCK)) R 0;
R -1;
}
static I k10_ipc_recv_step(I ep, I fd,
struct ipc_client_state *c) {
if (c->have_hdr < 8) return k10_ipc_recv_hdr(fd, c);
if (c->body == NULL) {
J n = ipc_header_validate(&c->hdr);
if (n < 0 || n > IPC_OKK_MAX_BODY) R -1;
c->body_len = n; c->have_body = 0;
c->body = (char *)malloc((size_t)(n > 0 ? n : 1));
if (c->body == NULL) R -1;
}
if (c->have_body < c->body_len)
return k10_ipc_recv_body(fd, c);
k10_ipc_dispatch_buf(fd, c->body,
(I)c->body_len, ep);
free(c->body); c->body = NULL;
c->have_hdr = 0; R 1;
}
static I k10_ipc_recv(I ep, I fd) {
struct ipc_client_state *c = ipc_client_get_or_make(fd);
if (c == NULL) R -1;
while (1) {
I r = k10_ipc_recv_step(ep, fd, c);
if (r <= 0) R r;
}
}
static V k10_ipc_handle_ev(I ep, I fd,
uI evs, I lfd) {
if (fd == lfd) {
I c = tcp_accept_one_client(lfd);
if (c < 0 || c >= IPC_MAX_CLIENTS) {
if (c >= 0) close(c); R;
}
I fl = fcntl(c, F_GETFL, 0);
fcntl(c, F_SETFL, fl | O_NONBLOCK);
struct epoll_event ev = {EPOLLIN, {.fd = c}};
if (epoll_ctl(ep, EPOLL_CTL_ADD, c, &ev) < 0)
close(c);
else ipc_client_get_or_make(c);
} else if (evs & (EPOLLERR | EPOLLHUP))
ipc_client_close(ep, fd);
else if (evs & EPOLLOUT) {
if (ipc_client_flush(ep, fd) < 0)
ipc_client_close(ep, fd);
} else if (evs & EPOLLIN) {
if (k10_ipc_recv(ep, fd) < 0)
ipc_client_close(ep, fd);
}
}
I k10_ipc_loop(I lfd) {
I ep = epoll_create1(0);
if (ep < 0) R 5;
struct epoll_event ev = {EPOLLIN, {.fd = lfd}};
if (epoll_ctl(ep, EPOLL_CTL_ADD, lfd, &ev) < 0) {
close(ep); R 5;
}
while (1) {
struct epoll_event evs[64];
I n = epoll_wait(ep, evs, 64, -1);
if (n < 0 && errno == EINTR) continue;
if (n < 0) break;
for (I i = 0; i < n; i++)
k10_ipc_handle_ev(ep, evs[i].data.fd,
evs[i].events, lfd);
}
close(ep); R 0;
}
I k10_ipc_dispatch_buf(I fd, V *f,
I n, I ep) {
if (n < 1) R -1;
J *cur = (J *)&f;
uJ v = decode_one_value(cur);
if (v <= 0xf) R -1;
J r = (J)apply_n_args((J *)v, 0, 0);
release_object((V **)(V *)v);
J *e = encode_to_ipc_buffer(0, (V **)r, 0, 0);
if (K_IS_ERR_RETURN(e)) {
char err[9] = {IPC_BYTE_ORDER_LE,
IPC_MSG_TYPE_RESPONSE, 0, 0};
*(uI *)&err[4] = 9; err[8] = (char)r;
ipc_client_send(ep, fd, err, 9); R 0;
}
uI bl = (uI)*(I *)((char *)e - 4);
uJ h = ipc_header_pack(IPC_MSG_TYPE_RESPONSE,
bl + 8, 0);
ipc_client_send(ep, fd, &h, 8);
ipc_client_send(ep, fd, e, (I)bl);
release_object((V **)e); release_object((V **)(V *)r); R 0;
}
I k10_io_read_exact(I fd, I n, V *b) {
char *p = (char *)b; I g = 0;
while (g < n) {
ssize_t r = read(fd, p + g, (size_t)(n - g));
if (r <= 0) R -1;
g += (I)r;
}
R 0;
}
I k10_ipc_dispatch(I fd, V *f, I n) {
if (n < 1) R -1;
J *cur = (J *)&f;
uJ v = decode_one_value(cur);
if (v <= 0xf) R -1;
J r = (J)apply_n_args((J *)v, 0, 0);
release_object((V **)(V *)v);
J *e = encode_to_ipc_buffer(0, (V **)r, 0, 0);
if (K_IS_ERR_RETURN(e)) {
write(fd, "\x01\x02\x00\x00\x01\x00\x00\x00", 8);
write(fd, &r, 1); R 0;
}
send_framed_to_fd(fd, (V **)e);
release_object((V **)e); release_object((V **)(V *)r); R 0;
}
J *k10_meta_parse(char *s) {
R parse_source_to_ast((__int128 *)s);
}
J *k10_meta_eval(char *s) {
R eval_source_or_dispatch(s, 0, 0);
}
J k10_meta_call(J *f, J *a) {
I n = *(I *)((char *)a - 4);
R apply_n_args(f, n, (uJ)a);
}
V k10_panic(I c, const char *m) {
if (c) R;
write_cstr_stderr("ASSERT: ");
write_cstr_stderr(m);
write_cstr_stderr("\n");
flush_log_and_exit(1);
}
V k10_debug_dump(V **v) {
if (!K_IS_ERR_RETURN(v)) println_object(v);
else {
char b[32];
I n = sprintf(b, "<atom:%p>", (V *)v);
write(STDERR_FILENO, b, (size_t)n);
}
}
static J k10_atom_box_i(J v) {
R (J)box_atom(K_TYPE_LONG, v);
}
static J k10_atom_box_f(F v) {
union { F d; J l; } u; u.d = v;
R (J)box_atom(K_TYPE_FLOAT, u.l);
}
J k10_atom_add(J a, J b) {
uI ta = (uI)((uJ)a >> K_TAG_SHIFT);
uI tb = (uI)((uJ)b >> K_TAG_SHIFT);
if (ta == K_TYPE_LONG && tb == K_TYPE_LONG)
R k10_atom_box_i(*(J *)(a & K_PTR_MASK) +
*(J *)(b & K_PTR_MASK));
if (ta == K_TYPE_FLOAT && tb == K_TYPE_FLOAT)
R k10_atom_box_f(*(F *)(a & K_PTR_MASK) +
*(F *)(b & K_PTR_MASK));
R 6;
}
J k10_atom_sub(J a, J b) {
uI ta = (uI)((uJ)a >> K_TAG_SHIFT);
uI tb = (uI)((uJ)b >> K_TAG_SHIFT);
if (ta == K_TYPE_LONG && tb == K_TYPE_LONG)
R k10_atom_box_i(*(J *)(a & K_PTR_MASK) -
*(J *)(b & K_PTR_MASK));
if (ta == K_TYPE_FLOAT && tb == K_TYPE_FLOAT)
R k10_atom_box_f(*(F *)(a & K_PTR_MASK) -
*(F *)(b & K_PTR_MASK));
R 6;
}
J k10_atom_mul(J a, J b) {
uI ta = (uI)((uJ)a >> K_TAG_SHIFT);
uI tb = (uI)((uJ)b >> K_TAG_SHIFT);
if (ta == K_TYPE_LONG && tb == K_TYPE_LONG)
R k10_atom_box_i(*(J *)(a & K_PTR_MASK) *
*(J *)(b & K_PTR_MASK));
if (ta == K_TYPE_FLOAT && tb == K_TYPE_FLOAT)
R k10_atom_box_f(*(F *)(a & K_PTR_MASK) *
*(F *)(b & K_PTR_MASK));
R 6;
}
J k10_atom_div(J a, J b) {
uI ta = (uI)((uJ)a >> K_TAG_SHIFT);
uI tb = (uI)((uJ)b >> K_TAG_SHIFT);
if (ta == K_TYPE_LONG && tb == K_TYPE_LONG) {
J pb = *(J *)(b & K_PTR_MASK);
if (pb == 0) R k10_atom_box_i(INT64_MIN);
R k10_atom_box_i(*(J *)(a & K_PTR_MASK) / pb);
}
if (ta == K_TYPE_FLOAT && tb == K_TYPE_FLOAT)
R k10_atom_box_f(*(F *)(a & K_PTR_MASK) /
*(F *)(b & K_PTR_MASK));
R 6;
}
const char *k10_vm_op_name(I op) {
if (op == OP_PUSH) R "PUSH";
if (op == OP_LOAD) R "LOAD";
if (op == OP_STORE) R "STORE";
if (op == OP_CALL_VERB) R "CALL_VERB";
if (op == OP_JIF) R "JIF";
if (op == OP_JMP) R "JMP";
if (op == OP_RETURN) R "RETURN";
if (op == OP_DISPATCH) R "DISPATCH";
R "???";
}
static V k10_vm_op_call(I imm, J *stk, I *sp) {
I n = imm;
J r = apply_n_args((J *)stk[*sp - n], n,
(uJ)&stk[*sp - n + 1]);
*sp -= n; stk[*sp] = r;
}
static I k10_vm_op_jif(I imm, J *stk, I *sp, I ip) {
J v = stk[(*sp)--];
if (!is_truthy_full((V **)v)) R ip + imm;
R ip + 5;
}
static V k10_vm_op_dispatch(I imm, J *stk, I *sp) {
J v = stk[(*sp)--];
J r = (J)apply_dyadic_dispatch(
(J *)(intptr_t)imm, (J *)v,
(J *)stk[*sp], 0, 0);
stk[*sp] = r;
}
I k10_vm_step_bc(const int8_t *code, I ip,
J *stk, I *sp, J *loc) {
I op = (I)(G)code[ip];
I imm = *(I *)(code + ip + 1);
switch (op) {
case OP_PUSH: stk[++(*sp)] = imm; break;
case OP_LOAD: stk[++(*sp)] = loc[imm]; break;
case OP_STORE: loc[imm] = stk[(*sp)--]; break;
case OP_CALL_VERB: k10_vm_op_call(imm, stk, sp); break;
case OP_JIF: R k10_vm_op_jif(imm, stk, sp, ip);
case OP_JMP: R ip + imm;
case OP_RETURN: R -1;
case OP_DISPATCH: k10_vm_op_dispatch(imm, stk, sp); break;
}
R ip + 5;
}
V k10_vm_init_dyadic(void) {
verb_dispatch_primary[(G)'+'] = (J)k10_atom_add;
verb_dispatch_primary[(G)'-'] = (J)k10_atom_sub;
verb_dispatch_primary[(G)'*'] = (J)k10_atom_mul;
verb_dispatch_primary[(G)'%'] = (J)k10_atom_div;
verb_dispatch_primary[(G)'='] = (J)tagged_atom_equal;
verb_dispatch_primary[(G)'<'] = (J)compare_lt_general;
verb_dispatch_primary[(G)'#'] = (J)verb_byte_take_from_left;
verb_dispatch_primary[(G)'_'] = (J)verb_byte_drop_from_left;
verb_dispatch_primary[(G)'@'] = (J)verb_byte_index_at;
verb_dispatch_primary[(G)'.'] = (J)verb_byte_apply_at;
}
V k10_vm_init_unary(void) {
verb_dispatch_secondary[(G)'-'] = (J)long_vector_neg;
verb_dispatch_secondary[(G)'#'] = (J)kind_or_length_walk;
verb_dispatch_secondary[(G)'|'] = (J)monadic_reverse;
verb_dispatch_secondary[(G)'&'] = (J)monadic_where_indices;
verb_dispatch_secondary[(G)'?'] = (J)monadic_distinct_long;
verb_dispatch_secondary[(G)'*'] = (J)vector_first;
verb_dispatch_secondary[(G)'!'] = (J)dict_keys;
verb_dispatch_secondary[(G)'~'] = (J)bitwise_complement_in_place;
verb_dispatch_secondary[(G)','] = (J)apply_unary_or_singleton;
}
V k10_vm_init_default(void) {
k10_vm_init_dyadic();
k10_vm_init_unary();
}
J verb_dispatch_secondary[256] = { 0 };
J verb_dispatch_primary[256] = { 0 };
G verb_class_classifier[256] = { 0 };
V *atomic_extension_long_long(K_dyadic_atom_fn fn, J left, J *vec)
{
uJ n = (uJ)*(I *)((char *)vec - 4);
J *out = allocate_typed_vector(K_TYPE_LONG, (I)n);
for (uJ i = 0; i < n; i++) out[i] = fn(left, vec[i]);
release_object((V **)vec);
return out;
}
V *atomic_extension_long_long_each(K_dyadic_atom_fn fn, J *a, J *b)
{
uJ n = (uJ)*(I *)((char *)a - 4);
J *out = allocate_typed_vector(K_TYPE_LONG, (I)n);
for (uJ i = 0; i < n; i++) out[i] = fn(a[i], b[i]);
release_object((V **)a);
release_object((V **)b);
return out;
}
J *vector_match_index(J *corpus, J *query)
{
uJ m = (uJ)*(I *)((char *)corpus - 4);
uJ n = (uJ)*(I *)((char *)query - 4);
J *out = allocate_typed_vector(K_TYPE_LONG, (I)n);
for (uJ i = 0; i < n; i++) {
J needle = query[i];
uJ pos = m;
for (uJ j = 0; j < m; j++) {
if (corpus[j] == needle) { pos = j; break; }
}
out[i] = (J)pos;
}
release_object((V **)query);
return out;
}
J *vector_member_test(J *query, J *corpus)
{
uJ m = (uJ)*(I *)((char *)corpus - 4);
uJ n = (uJ)*(I *)((char *)query - 4);
J *out = allocate_zero_filled_typed(K_TYPE_BOOL, (I)n);
for (uJ i = 0; i < n; i++) {
J needle = query[i];
for (uJ j = 0; j < m; j++) {
if (corpus[j] == needle) {
((char *)out)[i] = 1;
break;
}
}
}
release_object((V **)query);
release_object((V **)corpus);
return out;
}
J *vector_first_or_last_n(I n, J *vec)
{
uJ veclen = (uJ)*(I *)((char *)vec - 4);
if (n == 0) {
J *out = allocate_typed_vector(*(G *)((char *)vec - 5), 0);
release_object((V **)vec);
return out;
}
if (n > 0) {
I take = n;
if (take > (I)veclen) take = (I)veclen;
return slice_into_new_slot(0, take, vec);
}
I take = -n;
if (take > (I)veclen) take = (I)veclen;
return slice_into_new_slot((I)veclen - take, take, vec);
}
static V sort_int32_range(I *p, I lo, I hi)
{
while (lo < hi) {
I pivot = p[lo + (hi - lo) / 2];
I i = lo - 1, j = hi + 1;
while (1) {
do { i++; } while (p[i] < pivot);
do { j--; } while (p[j] > pivot);
if (i >= j) break;
I t = p[i]; p[i] = p[j]; p[j] = t;
}
if (j - lo < hi - (j + 1)) {
sort_int32_range(p, lo, j);
lo = j + 1;
} else {
sort_int32_range(p, j + 1, hi);
hi = j;
}
}
}
V sort_int_vector_in_place(I *p, I n)
{
if (n > 1) sort_int32_range(p, 0, n - 1);
}
static V sort_int16_range(I16 *p, I lo, I hi)
{
while (lo < hi) {
I16 pivot = p[lo + (hi - lo) / 2];
I i = lo - 1, j = hi + 1;
while (1) {
do { i++; } while (p[i] < pivot);
do { j--; } while (p[j] > pivot);
if (i >= j) break;
I16 t = p[i]; p[i] = p[j]; p[j] = t;
}
if (j - lo < hi - (j + 1)) {
sort_int16_range(p, lo, j);
lo = j + 1;
} else {
sort_int16_range(p, j + 1, hi);
hi = j;
}
}
}
V sort_short_vector_in_place(I16 *p, I n)
{
if (n > 1) sort_int16_range(p, 0, n - 1);
}
V sort_byte_vector_in_place(G *p, I n)
{
I counts[256];
memset(counts, 0, sizeof counts);
for (I i = 0; i < n; i++) counts[p[i]]++;
I idx = 0;
for (I v = 0; v < 256; v++) {
while (counts[v]-- > 0) p[idx++] = (G)v;
}
}
F *cumulative_sum_float(F *vec)
{
uJ n = (uJ)*(I *)((char *)vec - 4);
F *out = (F *)allocate_typed_vector(K_TYPE_FLOAT, (I)n);
if (n == 0) return out;
out[0] = vec[0];
for (uJ i = 1; i < n; i++) out[i] = out[i-1] + vec[i];
release_object((V **)vec);
return out;
}
J *cumulative_max_long(J *vec)
{
uJ n = (uJ)*(I *)((char *)vec - 4);
J *out = allocate_typed_vector(K_TYPE_LONG, (I)n);
if (n == 0) return out;
out[0] = vec[0];
for (uJ i = 1; i < n; i++) {
out[i] = vec[i] > out[i-1] ? vec[i] : out[i-1];
}
release_object((V **)vec);
return out;
}
J *cumulative_min_long(J *vec)
{
uJ n = (uJ)*(I *)((char *)vec - 4);
J *out = allocate_typed_vector(K_TYPE_LONG, (I)n);
if (n == 0) return out;
out[0] = vec[0];
for (uJ i = 1; i < n; i++) {
out[i] = vec[i] < out[i-1] ? vec[i] : out[i-1];
}
release_object((V **)vec);
return out;
}
J parse_unsigned_int_skipped(const char *buf, I *pos, I end)
{
J v = 0;
while (*pos < end && is_decimal_digit((G)buf[*pos])) {
v = v * 10 + (buf[*pos] - '0');
(*pos)++;
}
return v;
}
J parse_signed_int_skipped(const char *buf, I *pos, I end)
{
I sign = 1;
if (*pos < end && buf[*pos] == '-') { sign = -1; (*pos)++; }
return sign * parse_unsigned_int_skipped(buf, pos, end);
}
F parse_double_skipped(const char *buf, I *pos, I end)
{
I start = *pos;
while (*pos < end && (is_decimal_digit((G)buf[*pos])
|| buf[*pos] == '.' || buf[*pos] == '-'
|| buf[*pos] == '+' || buf[*pos] == 'e'
|| buf[*pos] == 'E')) {
(*pos)++;
}
if (*pos == start) return 0.0 / 0.0;
char tmp[64];
I len = *pos - start;
if (len >= (I)sizeof tmp) len = (I)sizeof tmp - 1;
memcpy(tmp, buf + start, (size_t)len);
tmp[len] = 0;
return strtod(tmp, NULL);
}
V console_render_long(J *vec)
{
uJ n = (uJ)*(I *)((char *)vec - 4);
if (n == 0) { write(STDOUT_FILENO, "()\n", 3); return; }
char buf[24];
for (uJ i = 0; i < n; i++) {
if (i > 0) write(STDOUT_FILENO, " ", 1);
I len = sprintf(buf, "%lld", (long long)vec[i]);
write(STDOUT_FILENO, buf, (size_t)len);
}
write(STDOUT_FILENO, "\n", 1);
}
V console_render_charvec(char *vec)
{
uI n = (uI)*(I *)(vec - 4);
write(STDOUT_FILENO, vec, n);
write(STDOUT_FILENO, "\n", 1);
}
V console_render_double(F *vec)
{
uJ n = (uJ)*(I *)((char *)vec - 4);
char buf[32];
for (uJ i = 0; i < n; i++) {
if (i > 0) write(STDOUT_FILENO, " ", 1);
I len = sprintf(buf, "%g", vec[i]);
write(STDOUT_FILENO, buf, (size_t)len);
}
write(STDOUT_FILENO, "\n", 1);
}
static V json_skip_whitespace(const char *src, I *pos, I end)
{
while (*pos < end) {
char c = src[*pos];
if (c != ' ' && c != '\t' && c != '\n' && c != '\r') break;
(*pos)++;
}
}
static inline J *json_append_byte(J *out, char c)
{
return (J *)charvec_append_byte((V **)out, c);
}
static J *json_append_utf8(J *out, I ucp)
{
if (ucp < K_UTF8_ASCII_MAX) return json_append_byte(out, (char)ucp);
if (ucp < 0x800) {
out = json_append_byte(out, (char)(0xc0 | (ucp >> 6)));
return json_append_byte(out, (char)(K_UTF8_CONT_HEADER | (ucp & K_TYPE_TAG_MASK)));
}
out = json_append_byte(out, (char)(0xe0 | (ucp >> 12)));
out = json_append_byte(out, (char)(K_UTF8_CONT_HEADER | ((ucp >> 6) & K_TYPE_TAG_MASK)));
return json_append_byte(out, (char)(K_UTF8_CONT_HEADER | (ucp & K_TYPE_TAG_MASK)));
}
static char json_escape_byte(char esc)
{
switch (esc) {
case 'n': return '\n';
case 't': return '\t';
case 'r': return '\r';
case '\\': return '\\';
case '"': return '"';
case '/': return '/';
default: return esc;
}
}
static J *json_append_escape(J *out, const char *src,
I *pos, I end)
{
char esc = src[*pos + 1];
if (esc == 'u') {
if (*pos + 5 < end) {
char h[5] = { src[*pos+2], src[*pos+3], src[*pos+4], src[*pos+5], 0 };
out = json_append_utf8(out, (I)strtol(h, NULL, 16));
*pos += 6;
return out;
}
*pos += 2;
return out;
}
out = json_append_byte(out, json_escape_byte(esc));
*pos += 2;
return out;
}
static J json_parse_string(const char *src, I *pos, I end)
{
if (*pos >= end || src[*pos] != '"') return 5;
(*pos)++;
J *out = allocate_typed_vector(K_TYPE_PAIR_CHAIN, 0);
while (*pos < end && src[*pos] != '"') {
char c = src[*pos];
if (c == '\\' && *pos + 1 < end) {
out = json_append_escape(out, src, pos, end);
} else {
out = json_append_byte(out, c);
(*pos)++;
}
}
if (*pos < end) (*pos)++;
return (J)out;
}
static J json_parse_number(const char *src, I *pos, I end)
{
I start = *pos;
if (*pos < end && src[*pos] == '-') (*pos)++;
while (*pos < end && is_decimal_digit((G)src[*pos])) (*pos)++;
I is_float = 0;
if (*pos < end && src[*pos] == '.') {
is_float = 1;
(*pos)++;
while (*pos < end && is_decimal_digit((G)src[*pos])) (*pos)++;
}
if (*pos < end && (src[*pos] == 'e' || src[*pos] == 'E')) {
is_float = 1;
(*pos)++;
if (*pos < end && (src[*pos] == '+' || src[*pos] == '-')) (*pos)++;
while (*pos < end && is_decimal_digit((G)src[*pos])) (*pos)++;
}
char buf[64];
I len = *pos - start;
if (len >= (I)sizeof buf) len = (I)sizeof buf - 1;
memcpy(buf, src + start, (size_t)len);
buf[len] = 0;
if (is_float) {
union { F d; J l; } u;
u.d = strtod(buf, NULL);
return (J)box_atom(K_TYPE_FLOAT, u.l);
}
return (J)box_atom(K_TYPE_LONG, (J)strtoll(buf, NULL, 10));
}
static J json_parse_array(const char *src, I *pos, I end)
{
if (*pos >= end || src[*pos] != '[') return 5;
(*pos)++;
J *out = allocate_typed_vector(K_TYPE_LIST, 0);
json_skip_whitespace(src, pos, end);
if (*pos < end && src[*pos] == ']') { (*pos)++; return (J)out; }
while (*pos < end) {
J v = json_parse_value(src, pos, end);
out = (J *)list_append_value((V **)out, (J *)v, 0);
json_skip_whitespace(src, pos, end);
if (*pos >= end || src[*pos] != ',') break;
(*pos)++;
json_skip_whitespace(src, pos, end);
}
if (*pos < end && src[*pos] == ']') (*pos)++;
return (J)out;
}
static J json_parse_object(const char *src, I *pos, I end)
{
if (*pos >= end || src[*pos] != '{') return 5;
(*pos)++;
J *keys = allocate_typed_vector(K_TYPE_LIST, 0);
J *vals = allocate_typed_vector(K_TYPE_LIST, 0);
json_skip_whitespace(src, pos, end);
if (*pos < end && src[*pos] == '}') {
(*pos)++;
return (J)pair_cell_make(K_TYPE_KEYED_PAIR, (J)keys, vals);
}
while (*pos < end) {
json_skip_whitespace(src, pos, end);
J key = json_parse_string(src, pos, end);
keys = (J *)list_append_value((V **)keys, (J *)key, 0);
json_skip_whitespace(src, pos, end);
if (*pos < end && src[*pos] == ':') (*pos)++;
json_skip_whitespace(src, pos, end);
J val = json_parse_value(src, pos, end);
vals = (J *)list_append_value((V **)vals, (J *)val, 0);
json_skip_whitespace(src, pos, end);
if (*pos >= end || src[*pos] != ',') break;
(*pos)++;
}
if (*pos < end && src[*pos] == '}') (*pos)++;
return (J)pair_cell_make(K_TYPE_KEYED_PAIR, (J)keys, vals);
}
J json_parse_value(const char *src, I *pos, I end)
{
json_skip_whitespace(src, pos, end);
if (*pos >= end) return 5;
char c = src[*pos];
if (c == '"') return json_parse_string(src, pos, end);
if (c == '[') return json_parse_array(src, pos, end);
if (c == '{') return json_parse_object(src, pos, end);
if (c == 't' && *pos + 4 <= end && memcmp(src + *pos, "true", 4) == 0) {
*pos += 4; return (J)box_atom(K_TYPE_BOOL, 1);
}
if (c == 'f' && *pos + 5 <= end && memcmp(src + *pos, "false", 5) == 0) {
*pos += 5; return (J)box_atom(K_TYPE_BOOL, 0);
}
if (c == 'n' && *pos + 4 <= end && memcmp(src + *pos, "null", 4) == 0) {
*pos += 4; return (J)box_atom(K_TYPE_LONG, INT64_MIN);
}
if (c == '-' || is_decimal_digit((G)c)) {
return json_parse_number(src, pos, end);
}
return 5;
}
J json_parse_charvec(char *charvec)
{
I end = *(I *)(charvec - 4);
I pos = 0;
J v = json_parse_value((const char *)charvec, &pos, end);
release_object((V **)charvec);
return v;
}
V symbol_table_dump_to_console(void)
{
if (runtime_root_namespace_anchor == 0) {
write_cstr_stderr("(no symbols interned)\n");
return;
}
J *root = (J *)runtime_root_namespace_anchor;
if (*(G *)((char *)root - 5) != K_TYPE_KEYED_PAIR) return;
J *names = (J *)*root;
uJ n = (uJ)*(I *)((char *)names - 4);
for (uJ i = 0; i < n; i++) {
char *name_vec = (char *)names[i];
if (((uintptr_t)name_vec & K_PTR_MASK) == 0) continue;
write(STDOUT_FILENO, name_vec, *(I *)(name_vec - 4));
write(STDOUT_FILENO, "\n", 1);
}
}
J *read_csv_file_to_table(const char *path)
{
J *content = read_file_to_charvec(path);
if (K_IS_ERR_RETURN(content)) return content;
uI n = (uI)*(I *)((char *)content - 4);
char *p = (char *)content;
J *lines = allocate_typed_vector(K_TYPE_LIST, 0);
uI start = 0;
for (uI i = 0; i <= n; i++) {
if (i == n || p[i] == '\n') {
uI L = i - start;
if (L > 0 && p[start + L - 1] == '\r') L--;
J *line = (J *)allocate_typed_vector_init(K_TYPE_PAIR_CHAIN, (I)L, p + start);
lines = (J *)list_append_value((V **)lines, line, 0);
start = i + 1;
}
}
release_object((V **)content);
uJ nlines = (uJ)*(I *)((char *)lines - 4);
if (nlines == 0) return lines;
J *header = csv_split_line((char *)((J *)lines)[0],
*(I *)((char *)((J *)lines)[0] - 4));
uJ ncols = (uJ)*(I *)((char *)header - 4);
J *cols = allocate_typed_vector(K_TYPE_LIST, (I)ncols);
for (uJ c = 0; c < ncols; c++) {
cols[c] = (J)allocate_typed_vector(K_TYPE_LIST, 0);
}
for (uJ i = 1; i < nlines; i++) {
char *line_vec = (char *)((J *)lines)[i];
J *row = csv_split_line(line_vec, *(I *)(line_vec - 4));
uJ nrow = (uJ)*(I *)((char *)row - 4);
for (uJ c = 0; c < ncols; c++) {
J cell = (c < nrow) ? row[c]
: (J)allocate_typed_vector(K_TYPE_PAIR_CHAIN, 0);
cols[c] = (J)list_append_value((V **)cols[c], (J *)cell, 0);
}
}
release_object((V **)lines);
return (J *)pair_cell_make(K_TYPE_KEYED_PAIR, (J)header, cols);
}
J *format_value_to_source(J *value)
{
if (K_IS_ERR_RETURN(value)) {
char buf[32];
I len = sprintf(buf, "(error %ld)", (long)(uintptr_t)value);
return (J *)allocate_typed_vector_init(K_TYPE_PAIR_CHAIN, len, buf);
}
uI tag = (uI)((J)value >> K_TAG_SHIFT);
if (tag != 0) {
char buf[32];
I len;
if (tag == K_TYPE_LONG) {
len = sprintf(buf, "%lld", (long long)*(J *)((uJ)value & K_PTR_MASK));
} else if (tag == K_TYPE_INT) {
len = sprintf(buf, "%di", (I)(intptr_t)value);
} else if (tag == K_TYPE_BOOL) {
len = sprintf(buf, "%db", (I)(intptr_t)value);
} else if (tag == K_TYPE_FLOAT) {
F d = *(F *)((uJ)value & K_PTR_MASK);
len = sprintf(buf, "%g", d);
} else {
len = sprintf(buf, "(tag-%x)", tag);
}
return (J *)allocate_typed_vector_init(K_TYPE_PAIR_CHAIN, len, buf);
}
G hdr = *(G *)((char *)value - 5);
if (hdr == K_TYPE_PAIR_CHAIN) {
return (J *)retain_object(value);
}
if (hdr == K_TYPE_LONG) {
J *out = allocate_typed_vector(K_TYPE_PAIR_CHAIN, 0);
uJ n = (uJ)*(I *)((char *)value - 4);
char buf[32];
for (uJ i = 0; i < n; i++) {
if (i > 0) out = (J *)charvec_append_byte((V **)out, ' ');
I len = sprintf(buf, "%lld", (long long)((J *)value)[i]);
for (I j = 0; j < len; j++) {
out = (J *)charvec_append_byte((V **)out, buf[j]);
}
}
release_object((V **)value);
return out;
}
return (J *)retain_object(value);
}
J *table_evaluate_predicate(J *table, J *pred_lambda)
{
I rows = table_row_count(table);
J *out = allocate_zero_filled_typed(K_TYPE_BOOL, rows);
for (I r = 0; r < rows; r++) {
J args[2] = { r, (J)table };
J v = apply_n_args(pred_lambda, 1, (uJ)args);
if ((uJ)((uJ)v >> K_TAG_SHIFT) == K_TYPE_BOOL && (intptr_t)v != 0) {
((char *)out)[r] = 1;
} else if (K_IS_ERR_RETURN(v)) {
release_object(out);
return (J *)v;
} else if (is_truthy_full((V **)v)) {
((char *)out)[r] = 1;
}
}
return out;
}
J *table_update_column(J *table, J name_sym, J *new_col)
{
J *keys = (J *)retain_object((V *)*table);
J *cols = (J *)retain_object((V *)table[1]);
uJ n = (uJ)*(I *)((char *)keys - 4);
for (uJ i = 0; i < n; i++) {
if (keys[i] == name_sym) {
release_object((V **)cols[i]);
cols[i] = (J)new_col;
release_object((V **)table);
return (J *)pair_cell_make(K_TYPE_KEYED_PAIR, (J)keys, cols);
}
}
keys = (J *)list_append_value((V **)keys, (J *)name_sym, 0);
cols = (J *)list_append_value((V **)cols, new_col, 0);
release_object((V **)table);
return (J *)pair_cell_make(K_TYPE_KEYED_PAIR, (J)keys, cols);
}
J *table_delete_column(J *table, J name_sym)
{
J *keys = (J *)*table;
J *cols = (J *)table[1];
uJ n = (uJ)*(I *)((char *)keys - 4);
J *new_keys = allocate_typed_vector(2, 0);
J *new_cols = allocate_typed_vector(K_TYPE_LIST, 0);
for (uJ i = 0; i < n; i++) {
if (keys[i] != name_sym) {
new_keys = (J *)list_append_value((V **)new_keys, (J *)keys[i], 0);
new_cols = (J *)list_append_value((V **)new_cols,
(J *)retain_object((V *)cols[i]), 0);
}
}
release_object((V **)table);
return (J *)pair_cell_make(K_TYPE_KEYED_PAIR, (J)new_keys, new_cols);
}
J *table_join_inner(J *left, J *right, J join_key)
{
J *l_col = table_get_column(left, join_key);
J *r_col = table_get_column(right, join_key);
if (l_col == NULL || r_col == NULL) return (J *)6;
I l_rows = table_row_count(left);
I r_rows = table_row_count(right);
J *l_idxs = allocate_typed_vector(K_TYPE_LONG, 0);
J *r_idxs = allocate_typed_vector(K_TYPE_LONG, 0);
for (I i = 0; i < l_rows; i++) {
J li = ((J *)l_col)[i];
for (I j = 0; j < r_rows; j++) {
if (((J *)r_col)[j] == li) {
l_idxs = (J *)list_append_value((V **)l_idxs, (J *)(J)i, 0);
r_idxs = (J *)list_append_value((V **)r_idxs, (J *)(J)j, 0);
}
}
}
J *l_keys = (J *)*left;
J *r_keys = (J *)*right;
J *l_cols = (J *)left[1];
J *r_cols = (J *)right[1];
J *out_keys = allocate_typed_vector(2, 0);
J *out_cols = allocate_typed_vector(K_TYPE_LIST, 0);
uJ lkn = (uJ)*(I *)((char *)l_keys - 4);
uJ rkn = (uJ)*(I *)((char *)r_keys - 4);
for (uJ i = 0; i < lkn; i++) {
out_keys = (J *)list_append_value((V **)out_keys, (J *)l_keys[i], 0);
J *gathered = (J *)index_at_vector((J *)l_cols[i], l_idxs);
out_cols = (J *)list_append_value((V **)out_cols, gathered, 0);
}
for (uJ i = 0; i < rkn; i++) {
if (r_keys[i] == join_key) continue;
out_keys = (J *)list_append_value((V **)out_keys, (J *)r_keys[i], 0);
J *gathered = (J *)index_at_vector((J *)r_cols[i], r_idxs);
out_cols = (J *)list_append_value((V **)out_cols, gathered, 0);
}
release_object((V **)l_idxs);
release_object((V **)r_idxs);
return (J *)pair_cell_make(K_TYPE_KEYED_PAIR, (J)out_keys, out_cols);
}
extern I kill(I, I);
I signal_send_to_pid(I pid, I sig) { return kill(pid, sig); }
extern I getpid(void);
I process_id_self(void) { return getpid(); }
I process_uid_self(void)
{
extern uI getuid(void);
return (I)getuid();
}
J *process_argv_to_charlist(I argc, char **argv)
{
J *out = allocate_typed_vector(K_TYPE_LIST, argc);
for (I i = 0; i < argc; i++) {
I len = (I)strlen(argv[i]);
J *cell = (J *)allocate_typed_vector_init(K_TYPE_PAIR_CHAIN, len, argv[i]);
out[i] = (J)cell;
}
return out;
}
extern char **environ;
J *environ_get_var(const char *name)
{
if (environ == NULL) return NULL;
size_t n_len = strlen(name);
for (char **e = environ; *e != NULL; e++) {
if (strncmp(*e, name, n_len) == 0 && (*e)[n_len] == '=') {
const char *val = *e + n_len + 1;
I v_len = (I)strlen(val);
return (J *)allocate_typed_vector_init(K_TYPE_PAIR_CHAIN, v_len, val);
}
}
return NULL;
}
V heap_stats_emit(void)
{
char buf[128];
I len = sprintf(buf,
"alloc=%lld used=%lld base=%p size=%lld\n",
(long long)tls_heap.bytes_alloc,
(long long)tls_heap.bytes_alloc,
(V *)runtime_heap_base,
(long long)runtime_heap_size_bytes);
write(STDOUT_FILENO, buf, (size_t)len);
}
J freelist_class_count(I cls)
{
if (cls < 0 || cls > K_CLASS_MAX) return 0;
J count = 0;
J head = tls_heap.freelist[cls];
while (head != 0 && count < 0x1000000) {
count++;
head = *(J *)head;
}
return count;
}
J freelist_total_free_bytes(void)
{
J total = 0;
for (I c = 0; c <= K_CLASS_MAX; c++) {
J cnt = freelist_class_count(c);
total += cnt * (1LL << c);
}
return total;
}
I format_double_round_trip(char *out, F d)
{
if (d != d) {
out[0] = '0'; out[1] = 'n';
return 2;
}
if (d == 1.0/0.0) {
out[0] = '0'; out[1] = 'w';
return 2;
}
if (d == -1.0/0.0) {
out[0] = '-'; out[1] = '0'; out[2] = 'w';
return 3;
}
I len = sprintf(out, "%.17g", d);
F back = strtod(out, NULL);
if (back == d) {
char short_buf[32];
I short_len = sprintf(short_buf, "%g", d);
if (strtod(short_buf, NULL) == d) {
memcpy(out, short_buf, (size_t)short_len);
return short_len;
}
}
return len;
}
I format_int64_into(char *out, J v)
{
if (v == INT64_MIN) {
out[0] = '0'; out[1] = 'N';
return 2;
}
return sprintf(out, "%lld", (long long)v);
}
I format_int32_into(char *out, I v)
{
if (v == INT32_MIN) {
out[0] = '0'; out[1] = 'N'; out[2] = 'i';
return 3;
}
return sprintf(out, "%di", v);
}
uJ murmur64_charvec(const V *vec, I len)
{
const G *p = (const G *)vec;
uJ h = 0xcbf29ce484222325ULL ^ (uJ)len;
while (len >= 8) {
uJ k = (uJ)p[0]
| ((uJ)p[1] << 8) | ((uJ)p[2] << 16)
| ((uJ)p[3] << 24) | ((uJ)p[4] << 32)
| ((uJ)p[5] << 40) | ((uJ)p[6] << 48)
| ((uJ)p[7] << K_TAG_SHIFT);
k *= 0x87c37b91114253d5ULL;
k = (k << 31) | (k >> 33);
k *= 0x4cf5ad432745937fULL;
h ^= k;
h = ((h << 27) | (h >> 37)) * 5 + 0x52dce729;
p += 8;
len -= 8;
}
uJ tail = 0;
for (I i = 0; i < len; i++) tail |= (uJ)p[i] << (i * 8);
if (tail) {
tail *= 0x87c37b91114253d5ULL;
tail = (tail << 31) | (tail >> 33);
tail *= 0x4cf5ad432745937fULL;
h ^= tail;
}
h ^= h >> 33;
h *= 0xff51afd7ed558ccdULL;
h ^= h >> 33;
h *= 0xc4ceb9fe1a85ec53ULL;
h ^= h >> 33;
return h;
}
uJ fnv1a_64_byte(uJ state, G byte)
{
state ^= byte;
state *= 0x100000001b3ULL;
return state;
}
static I u8d2(const char *s, I *p,
I e, uI *c, G b) {
if (*p + 1 >= e) return -1;
G b1 = (G)s[*p + 1];
if ((b1 & K_UTF8_2BYTE_LEAD) != K_UTF8_CONT_HEADER) return -1;
*c = ((uI)(b & 0x1f) << 6) | (b1 & K_TYPE_TAG_MASK);
*p += 2; return 0;
}
static I u8d3(const char *s, I *p,
I e, uI *c, G b) {
if (*p + 2 >= e) return -1;
G b1 = s[*p+1], b2 = s[*p+2];
if ((b1 & K_UTF8_2BYTE_LEAD) != K_UTF8_CONT_HEADER || (b2&0xc0)!=0x80) return -1;
*c = ((uI)(b&0x0f)<<12)|((uI)(b1& K_TYPE_TAG_MASK)<<6)
| (b2 & K_TYPE_TAG_MASK);
*p += 3; return 0;
}
static I u8d4(const char *s, I *p,
I e, uI *c, G b) {
if (*p + 3 >= e) return -1;
G b1 = s[*p+1], b2 = s[*p+2], b3 = s[*p+3];
if ((b1 & K_UTF8_2BYTE_LEAD) != K_UTF8_CONT_HEADER || (b2&0xc0)!=0x80 || (b3&0xc0)!=0x80)
return -1;
*c = ((uI)(b&0x07)<<18)|((uI)(b1& K_TYPE_TAG_MASK)<<12)
|((uI)(b2& K_TYPE_TAG_MASK)<<6)|(b3& K_TYPE_TAG_MASK);
*p += 4; return 0;
}
I utf8_decode_at(const char *s, I *p,
I e, uI *c) {
if (*p >= e) return -1;
G b = (G)s[*p];
if (b < K_UTF8_ASCII_MAX) { *c = b; (*p)++; return 0; }
if ((b & 0xe0) == 0xc0) return u8d2(s, p, e, c, b);
if ((b & 0xf0) == 0xe0) return u8d3(s, p, e, c, b);
if ((b & 0xf8) == 0xf0) return u8d4(s, p, e, c, b);
return -1;
}
static I u8e2(char *d, uI c) {
d[0] = (char)(0xc0 | (c >> 6));
d[1] = (char)(K_UTF8_CONT_HEADER | (c & K_TYPE_TAG_MASK));
return 2;
}
static I u8e3(char *d, uI c) {
d[0] = (char)(0xe0 | (c >> 12));
d[1] = (char)(K_UTF8_CONT_HEADER | ((c >> 6) & K_TYPE_TAG_MASK));
d[2] = (char)(K_UTF8_CONT_HEADER | (c & K_TYPE_TAG_MASK));
return 3;
}
I utf8_encode_into(char *d, uI c) {
if (c < K_UTF8_ASCII_MAX) { d[0] = (char)c; return 1; }
if (c < 0x800) return u8e2(d, c);
if (c < 0x10000) return u8e3(d, c);
d[0] = (char)(0xf0 | (c >> 18));
d[1] = (char)(K_UTF8_CONT_HEADER | ((c >> 12) & K_TYPE_TAG_MASK));
d[2] = (char)(K_UTF8_CONT_HEADER | ((c >> 6) & K_TYPE_TAG_MASK));
d[3] = (char)(K_UTF8_CONT_HEADER | (c & K_TYPE_TAG_MASK));
return 4;
}
I utf8_codepoint_count(const char *s, I n) {
I p = 0, count = 0; uI c;
while (p < n) {
if (utf8_decode_at(s, &p, n, &c) < 0) return count;
count++;
}
return count;
}
static const char base64_chars[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static V b64e_t(const char *s, I *i,
I n, uI *t, I *d) {
*t |= (uI)(G)s[(*i)++] << 16;
if (*i < n) *t |= (uI)(G)s[(*i)++] << 8;
else (*d)++;
if (*i < n) *t |= (uI)(G)s[(*i)++];
else (*d)++;
}
static V b64e_c(char *p, uI t, I d) {
p[0] = base64_chars[(t >> 18) & K_TYPE_TAG_MASK];
p[1] = base64_chars[(t >> 12) & K_TYPE_TAG_MASK];
p[2] = (d < 2) ? base64_chars[(t >> 6) & K_TYPE_TAG_MASK] : '=';
p[3] = (d < 1) ? base64_chars[t & K_TYPE_TAG_MASK] : '=';
}
J *base64_encode(const char *s, I n) {
I on = ((n + 2) / 3) * 4;
J *o = allocate_typed_vector(K_TYPE_PAIR_CHAIN, on);
char *p = (char *)o;
for (I i = 0, j = 0; i < n; j += 4) {
uI t = 0; I d = 0;
b64e_t(s, &i, n, &t, &d);
b64e_c(p + j, t, d);
}
return o;
}
static V b64d_init(int8_t *l) {
for (I i = 0; i < 256; i++) l[i] = -1;
for (I i = 0; i < 64; i++)
l[(G)base64_chars[i]] = (int8_t)i;
}
static I b64d_step(char *p, I *op,
int8_t *l, const char *s) {
int8_t a = l[(G)s[0]], b = l[(G)s[1]];
int8_t c = l[(G)s[2]], d = l[(G)s[3]];
if (a < 0 || b < 0) return 0;
p[(*op)++] = (char)((a << 2) | (b >> 4));
if (c < 0) return 0;
p[(*op)++] = (char)(((b&15)<<4) | (c>>2));
if (d < 0) return 0;
p[(*op)++] = (char)(((c&3)<<6) | d);
return 1;
}
J *base64_decode(const char *s, I n) {
I om = (n / 4) * 3;
J *o = allocate_typed_vector(K_TYPE_PAIR_CHAIN, om);
char *p = (char *)o; I op = 0;
static int8_t l[256]; static I init = 0;
if (!init) { b64d_init(l); init = 1; }
for (I i = 0; i + 3 < n; i += 4)
if (!b64d_step(p, &op, l, s + i)) break;
*(I *)((char *)o - 4) = op;
return o;
}
J *hex_encode_charvec(const char *s, I n) {
J *o = allocate_typed_vector(K_TYPE_PAIR_CHAIN, n * 2);
char *p = (char *)o;
for (I i = 0; i < n; i++)
hex_byte(p + i * 2, (G)s[i]);
return o;
}
static I hex_val(char c) {
if (c >= '0' && c <= '9') return c - '0';
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
if (c >= 'A' && c <= 'F') return c - 'A' + 10;
return -1;
}
J *hex_decode_charvec(const char *s, I n) {
J *o = allocate_typed_vector(K_TYPE_PAIR_CHAIN, n / 2);
char *p = (char *)o; I op = 0;
for (I i = 0; i + 1 < n; i += 2) {
I hv = hex_val(s[i]), lv = hex_val(s[i+1]);
if (hv < 0 || lv < 0) break;
p[op++] = (char)((hv << 4) | lv);
}
*(I *)((char *)o - 4) = op;
return o;
}
V stdout_buffer_init(StdoutBuffer *b) {
b->length = 0;
}
V stdout_buffer_flush(StdoutBuffer *b) {
if (b->length <= 0) return;
write(STDOUT_FILENO, b->bytes, (size_t)b->length);
b->length = 0;
}
V stdout_buffer_write(StdoutBuffer *b,
const char *s, I n) {
while (n > 0) {
I f = STDOUT_BUFFER_SIZE - b->length;
I p = n < f ? n : f;
memcpy(b->bytes + b->length, s, (size_t)p);
b->length += p; s += p; n -= p;
if (b->length == STDOUT_BUFFER_SIZE)
stdout_buffer_flush(b);
}
}
V stdout_buffer_write_byte(StdoutBuffer *b, char c) {
if (b->length == STDOUT_BUFFER_SIZE)
stdout_buffer_flush(b);
b->bytes[b->length++] = c;
}
static V hw_kp(J *r, HeapVisitorFn v,
V *c) {
if (*(G *)((char *)r - 5) != K_TYPE_KEYED_PAIR)
return;
v((V *)*r, c); v((V *)r[1], c);
}
V heap_walk_visit_all(HeapVisitorFn v, V *c) {
if (runtime_root_namespace_anchor == 0) return;
J *r = (J *)runtime_root_namespace_anchor;
v(r, c);
if (((J)r >> K_TAG_SHIFT) != 0) return;
hw_kp(r, v, c);
}
static V heap_count_visitor(V *o, V *c) {
(void)o; (*(J *)c)++;
}
J heap_count_allocated(void) {
J n = 0;
heap_walk_visit_all(heap_count_visitor, &n);
return n;
}
static uJ br1(uJ v) {
uJ m = 0x5555555555555555ULL;
return ((v >> 1) & m) | ((v & m) << 1);
}
static uJ br2(uJ v) {
uJ m = 0x3333333333333333ULL;
return ((v >> 2) & m) | ((v & m) << 2);
}
static uJ br4(uJ v) {
uJ m = 0x0f0f0f0f0f0f0f0fULL;
return ((v >> 4) & m) | ((v & m) << 4);
}
static uJ br8(uJ v) {
uJ m = 0x00ff00ff00ff00ffULL;
return ((v >> 8) & m) | ((v & m) << 8);
}
static uJ br16(uJ v) {
uJ m = 0x0000ffff0000ffffULL;
return ((v >> 16) & m) | ((v & m) << 16);
}
uJ bit_reverse_64(uJ v) {
v = br1(v); v = br2(v); v = br4(v);
v = br8(v); v = br16(v);
return (v >> 32) | (v << 32);
}
uJ byte_swap_64(uJ v) { return __builtin_bswap64(v); }
uI byte_swap_32(uI v) { return __builtin_bswap32(v); }
uint16_t byte_swap_16(uint16_t v) { return (uint16_t)((v >> 8) | (v << 8)); }
J popcount_long(J v) { return (J)__builtin_popcountll((uJ)v); }
J leading_zeros_long(J v) { return v == 0 ? 64 : (J)__builtin_clzll((uJ)v); }
J trailing_zeros_long(J v) { return v == 0 ? 64 : (J)__builtin_ctzll((uJ)v); }
static V ipc_8(J v, char **d) {
for (I i = 0; i < 8; i++)
(*d)[i] = (char)((v >> (i * 8)) & K_BYTE_MAX);
*d += 8;
}
static V ipc_4(I v, char **d) {
for (I i = 0; i < 4; i++)
(*d)[i] = (char)((v >> (i * 8)) & K_BYTE_MAX);
*d += 4;
}
V ipc_serialize_long_atom(J v, char **d) {
*(*d)++ = (char)K_TYPE_LONG; ipc_8(v, d);
}
V ipc_serialize_int_atom(I v, char **d) {
*(*d)++ = (char)K_TYPE_INT; ipc_4(v, d);
}
V ipc_serialize_bool_atom(I v, char **d) {
*(*d)++ = (char)K_TYPE_BOOL; *(*d)++ = (char)!!v;
}
V ipc_serialize_float_atom(F v, char **d) {
*(*d)++ = (char)K_TYPE_FLOAT;
union { F d; uJ u; } x; x.d = v;
ipc_8(x.u, d);
}
V ipc_serialize_charvec(const char *s,
I n, char **d) {
*(*d)++ = (char)K_TYPE_PAIR_CHAIN;
ipc_4(n, d); memcpy(*d, s, (size_t)n); *d += n;
}
V ipc_serialize_long_vec(J *s,
I n, char **d) {
*(*d)++ = (char)0x80 | (char)K_TYPE_LONG;
ipc_4(n, d);
for (I k = 0; k < n; k++) ipc_8(s[k], d);
}
J ipc_estimate_serialized_size(V *value)
{
if (K_IS_ERR_RETURN(value)) return 1;
uI tag = (uI)((J)value >> K_TAG_SHIFT);
if (tag == K_TYPE_LONG) return 9;
if (tag == K_TYPE_INT) return 5;
if (tag == K_TYPE_BOOL) return 2;
if (tag == K_TYPE_FLOAT) return 9;
if (tag != 0) return 9;
uJ hdr = (uJ)*(G *)((char *)value - 5);
uJ n = (uJ)*(I *)((char *)value - 4);
if (hdr == K_TYPE_PAIR_CHAIN) return (J)(5 + n);
if (hdr == K_TYPE_LONG) return (J)(5 + n * 8);
if (hdr == K_TYPE_INT) return (J)(5 + n * 4);
if (hdr == K_TYPE_SHORT) return (J)(5 + n * 2);
if (hdr == K_TYPE_FLOAT) return (J)(5 + n * 8);
if (hdr == K_TYPE_BOOL) return (J)(5 + (n + 7) / 8);
J total = 5;
for (uJ i = 0; i < n; i++) {
total += ipc_estimate_serialized_size(((V **)value)[i]);
}
return total;
}
V ipc_serialize_any(V *value, char **dst)
{
if (K_IS_ERR_RETURN(value)) {
*(*dst)++ = (char)0xff;
*(*dst)++ = (char)(uintptr_t)value;
return;
}
uI tag = (uI)((J)value >> K_TAG_SHIFT);
if (tag == K_TYPE_LONG) {
ipc_serialize_long_atom(*(J *)((uJ)value & K_PTR_MASK), dst);
return;
}
if (tag == K_TYPE_INT) {
ipc_serialize_int_atom((I)(intptr_t)value, dst);
return;
}
if (tag == K_TYPE_BOOL) {
ipc_serialize_bool_atom((I)(intptr_t)value, dst);
return;
}
if (tag == K_TYPE_FLOAT) {
ipc_serialize_float_atom(*(F *)((uJ)value & K_PTR_MASK), dst);
return;
}
if (tag != 0) { ipc_serialize_long_atom((J)value, dst); return; }
uJ hdr = (uJ)*(G *)((char *)value - 5);
uJ n = (uJ)*(I *)((char *)value - 4);
if (hdr == K_TYPE_PAIR_CHAIN) {
ipc_serialize_charvec((char *)value, (I)n, dst);
return;
}
if (hdr == K_TYPE_LONG) {
ipc_serialize_long_vec((J *)value, (I)n, dst);
return;
}
*(*dst)++ = (char)0x80;
for (I i = 0; i < 4; i++) (*dst)[i] = (char)((n >> (i * 8)) & K_BYTE_MAX);
*dst += 4;
for (uJ i = 0; i < n; i++) {
ipc_serialize_any(((V **)value)[i], dst);
}
}
J ipc_deserialize_long_atom(const char **src)
{
J v = 0;
for (I i = 0; i < 8; i++) v |= (J)(G)((*src)[i]) << (i * 8);
*src += 8;
return v;
}
I ipc_deserialize_uint32(const char **src)
{
I v = 0;
for (I i = 0; i < 4; i++) v |= (I)(G)((*src)[i]) << (i * 8);
*src += 4;
return v;
}
J *ipc_deserialize_charvec(const char **src)
{
I n = ipc_deserialize_uint32(src);
J *out = allocate_typed_vector_init(K_TYPE_PAIR_CHAIN, n, *src);
*src += n;
return out;
}
J *ipc_deserialize_long_vec(const char **src)
{
I n = ipc_deserialize_uint32(src);
J *out = allocate_typed_vector(K_TYPE_LONG, n);
for (I i = 0; i < n; i++) {
out[i] = ipc_deserialize_long_atom(src);
}
return out;
}
J ipc_deserialize_any(const char **src)
{
G tag = (G)*(*src)++;
if (tag == K_TYPE_LONG) return (J)box_atom(K_TYPE_LONG, ipc_deserialize_long_atom(src));
if (tag == K_TYPE_INT) {
I v = ipc_deserialize_uint32(src);
return (J)box_atom(K_TYPE_INT, (J)v);
}
if (tag == K_TYPE_BOOL) {
I v = (I)(G)*(*src)++;
return (J)box_atom(K_TYPE_BOOL, v);
}
if (tag == K_TYPE_FLOAT) {
J bits = ipc_deserialize_long_atom(src);
return (J)box_atom(K_TYPE_FLOAT, bits);
}
if (tag == K_TYPE_PAIR_CHAIN) return (J)ipc_deserialize_charvec(src);
if (tag == (K_UTF8_CONT_HEADER | K_TYPE_LONG)) return (J)ipc_deserialize_long_vec(src);
if (tag == K_BYTE_SIGN_BIT) {
I n = ipc_deserialize_uint32(src);
J *out = allocate_typed_vector(K_TYPE_LIST, n);
for (I i = 0; i < n; i++) {
out[i] = ipc_deserialize_any(src);
}
return (J)out;
}
return 6;
}
static J *pretty_print_atom(uI t,
V *v) {
char b[64]; I l;
if (t == K_TYPE_LONG)
l = format_int64_into(b, *(J *)((uJ)v & K_PTR_MASK));
else if (t == K_TYPE_INT)
l = format_int32_into(b, (I)(intptr_t)v);
else if (t == K_TYPE_BOOL)
l = sprintf(b, "%db", (I)(intptr_t)v);
else if (t == K_TYPE_FLOAT)
l = format_double_round_trip(b, *(F *)((uJ)v & K_PTR_MASK));
else l = sprintf(b, "<tag-0x%x:0x%lx>", t, (uintptr_t)v & K_PAYLOAD_BITS_16);
return (J *)allocate_typed_vector_init(K_TYPE_PAIR_CHAIN, l, b);
}
static J *pretty_print_long_vec(J *p,
uJ n) {
J *o = allocate_typed_vector(K_TYPE_PAIR_CHAIN, 0);
char b[24];
for (uJ i = 0; i < n; i++) {
if (i > 0) o = (J *)charvec_append_byte((V **)o, ' ');
I l = format_int64_into(b, p[i]);
for (I j = 0; j < l; j++)
o = (J *)charvec_append_byte((V **)o, b[j]);
}
return o;
}
static J *pretty_print_double_vec(F *p,
uJ n) {
J *o = allocate_typed_vector(K_TYPE_PAIR_CHAIN, 0);
char b[32];
for (uJ i = 0; i < n; i++) {
if (i > 0) o = (J *)charvec_append_byte((V **)o, ' ');
I l = format_double_round_trip(b, p[i]);
for (I j = 0; j < l; j++)
o = (J *)charvec_append_byte((V **)o, b[j]);
}
return o;
}
static J *ppc_esc(J *o, char c) {
o = (J *)charvec_append_byte((V **)o, '\\');
return (J *)charvec_append_byte((V **)o, c);
}
static J *ppc_hex(J *o, char c) {
char b[6]; I l = sprintf(b, "\\x%02x", (G)c);
for (I j = 0; j < l; j++)
o = (J *)charvec_append_byte((V **)o, b[j]);
return o;
}
static J *ppc_char(J *o, char c) {
if (c == '"' || c == '\\') return ppc_esc(o, c);
if (c == '\n') return ppc_esc(o, 'n');
if (c == '\t') return ppc_esc(o, 't');
if ((G)c >= 0x20 && (G)c < 127)
return (J *)charvec_append_byte((V **)o, c);
return ppc_hex(o, c);
}
static J *pretty_print_charvec(char *p, uI n) {
J *o = allocate_typed_vector(K_TYPE_PAIR_CHAIN, 0);
o = (J *)charvec_append_byte((V **)o, '"');
for (uI i = 0; i < n; i++) o = ppc_char(o, p[i]);
return (J *)charvec_append_byte((V **)o, '"');
}
J *pretty_print_any(V *value, I depth)
{
if (depth > 12) {
return (J *)allocate_typed_vector_init(K_TYPE_PAIR_CHAIN, 5, "<...>");
}
if (K_IS_ERR_RETURN(value)) {
char buf[16];
I len = sprintf(buf, "(err %ld)", (long)(uintptr_t)value);
return (J *)allocate_typed_vector_init(K_TYPE_PAIR_CHAIN, len, buf);
}
uI tag = (uI)((J)value >> K_TAG_SHIFT);
if (tag != 0) return pretty_print_atom(tag, value);
uJ hdr = (uJ)*(G *)((char *)value - 5);
uJ n = (uJ)*(I *)((char *)value - 4);
if (hdr == K_TYPE_PAIR_CHAIN) return pretty_print_charvec((char *)value, (uI)n);
if (hdr == K_TYPE_LONG) return pretty_print_long_vec((J *)value, n);
if (hdr == K_TYPE_FLOAT) return pretty_print_double_vec((F *)value, n);
if (hdr == K_TYPE_KEYED_PAIR) {
J *keys = pretty_print_any((V *)*(J *)value, depth + 1);
J *vals = pretty_print_any((V *)((J *)value)[1], depth + 1);
J *out = allocate_typed_vector(K_TYPE_PAIR_CHAIN, 0);
out = (J *)charvec_append_byte((V **)out, '(');
out = (J *)concat_charvecs((V **)out, (char *)keys);
out = (J *)charvec_append_byte((V **)out, ')');
out = (J *)charvec_append_byte((V **)out, '!');
out = (J *)concat_charvecs((V **)out, (char *)vals);
return out;
}
if (hdr == 0) {
J *out = allocate_typed_vector(K_TYPE_PAIR_CHAIN, 0);
out = (J *)charvec_append_byte((V **)out, '(');
for (uJ i = 0; i < n; i++) {
if (i > 0) out = (J *)charvec_append_byte((V **)out, ';');
J *part = pretty_print_any(((V **)value)[i], depth + 1);
out = (J *)concat_charvecs((V **)out, (char *)part);
}
out = (J *)charvec_append_byte((V **)out, ')');
return out;
}
char buf[24];
I len = sprintf(buf, "<type-0x%lx>", hdr);
return (J *)allocate_typed_vector_init(K_TYPE_PAIR_CHAIN, len, buf);
}
V pretty_print_to_stdout(V *value)
{
J *rendered = pretty_print_any(value, 0);
uI n = (uI)*(I *)((char *)rendered - 4);
write(STDOUT_FILENO, rendered, n);
write(STDOUT_FILENO, "\n", 1);
release_object((V **)rendered);
}
J bytecode_eval_loop(const int8_t *code, I code_len,
J *args, I n_args)
{
J stack[BYTECODE_STACK_DEPTH];
I sp = -1;
J locals[BYTECODE_LOCALS_MAX];
for (I i = 0; i < n_args && i < BYTECODE_LOCALS_MAX; i++) {
locals[i] = args[i];
}
I ip = 0;
while (ip >= 0 && ip + 1 <= code_len) {
I next = bytecode_step(code, ip, stack, &sp, locals);
if (next < 0) {
return sp >= 0 ? stack[sp] : 0;
}
ip = next;
}
return sp >= 0 ? stack[sp] : 0;
}
static ReplHistory repl_history = { {0}, 0, 0 };
V history_add(const char *line)
{
if (line[0] == 0) return;
if (repl_history.count == HISTORY_MAX) {
free(repl_history.lines[0]);
memmove(repl_history.lines, repl_history.lines + 1,
sizeof(char *) * (HISTORY_MAX - 1));
repl_history.count--;
}
repl_history.lines[repl_history.count++] = strdup(line);
repl_history.cursor = repl_history.count;
}
const char *history_get_prev(void)
{
if (repl_history.cursor > 0) {
repl_history.cursor--;
return repl_history.lines[repl_history.cursor];
}
return NULL;
}
const char *history_get_next(void)
{
if (repl_history.cursor < repl_history.count) {
repl_history.cursor++;
if (repl_history.cursor < repl_history.count) {
return repl_history.lines[repl_history.cursor];
}
}
return "";
}
extern I isatty(I fd);
I stdout_is_terminal(void) { return isatty(STDOUT_FILENO); }
V terminal_clear_screen(void)
{
static const char esc[] = "\x1b[2J\x1b[H";
write(STDOUT_FILENO, esc, sizeof esc - 1);
}
V terminal_set_color_red(void) { write(STDOUT_FILENO, "\x1b[31m", 5); }
V terminal_set_color_green(void) { write(STDOUT_FILENO, "\x1b[32m", 5); }
V terminal_set_color_yellow(void) { write(STDOUT_FILENO, "\x1b[33m", 5); }
V terminal_set_color_blue(void) { write(STDOUT_FILENO, "\x1b[34m", 5); }
V terminal_set_color_dim(void) { write(STDOUT_FILENO, "\x1b[2m", 4); }
V terminal_reset(void) { write(STDOUT_FILENO, "\x1b[0m", 4); }
V terminal_move_cursor(I row, I col)
{
char buf[24];
I len = sprintf(buf, "\x1b[%d;%dH", row, col);
write(STDOUT_FILENO, buf, (size_t)len);
}
extern I sigaction(I signum, const struct sigaction *act,
struct sigaction *oldact);
#ifndef SIGINT
# define SIGINT 2
# define SIGTERM 15
# define SIGHUP 1
# define SIGPIPE 13
# define SIGALRM 14
#endif
volatile I interrupt_pending = 0;
volatile I shutdown_pending = 0;
V signal_handler_sigint(I sig)
{
(void)sig;
interrupt_pending = 1;
}
V signal_handler_sigterm(I sig)
{
(void)sig;
shutdown_pending = 1;
}
I interrupt_was_pending(void)
{
if (interrupt_pending) {
interrupt_pending = 0;
return 1;
}
return 0;
}
I shutdown_was_pending(void) { return shutdown_pending; }
V install_signal_handlers(void)
{
typedef V (*SigHandlerT)(I);
extern SigHandlerT signal(I signum, SigHandlerT handler);
signal(SIGINT, signal_handler_sigint);
signal(SIGTERM, signal_handler_sigterm);
signal(SIGPIPE, (SigHandlerT)1);
}
CommandLineArgs parse_command_line(I argc, char **argv)
{
CommandLineArgs args = { 0, 0, NULL, NULL, 0, 0 };
I pos = 1;
while (pos < argc) {
const char *a = argv[pos];
if (a[0] == '-') {
char flag = a[1];
if (flag == 'p' && pos + 1 < argc) {
args.port = atoi(argv[++pos]);
} else if (flag == 'm' && pos + 1 < argc) {
args.memory_mb = atoi(argv[++pos]);
} else if (flag == 'v') {
args.verbose = 1;
} else if (flag == 'q') {
args.quiet = 1;
} else if (flag == 'h') {
write_cstr_stderr("usage: k10 [-p port] [-m mb] [-v|-q] [script | expr]\n");
flush_log_and_exit(0);
}
pos++;
} else {
if (args.script_path == NULL) {
args.script_path = a;
} else {
args.expression = a;
}
pos++;
}
}
return args;
}
F heap_pressure_ratio(void)
{
if (runtime_heap_size_bytes == 0) return 0.0;
J live = tls_heap.bytes_alloc;
if (live < 0) live = -live;
return (F)live / (F)runtime_heap_size_bytes;
}
I heap_should_compact(void)
{
return heap_pressure_ratio() > 0.7 ? 1 : 0;
}
J *coerce_atoms_to_typed_vector(J *list, uI target_tag)
{
uJ n = (uJ)*(I *)((char *)list - 4);
J *out = allocate_typed_vector((I)target_tag, (I)n);
for (uJ i = 0; i < n; i++) {
V *cell = ((V **)list)[i];
uI cell_tag = (uI)((J)cell >> K_TAG_SHIFT);
J payload;
if (cell_tag == K_TYPE_LONG) {
payload = *(J *)((uJ)cell & K_PTR_MASK);
} else if ((K_TAGCLASS_ATOMIC_BOX >> cell_tag) & 1) {
payload = (J)*(J *)((uJ)cell & K_PTR_MASK);
} else {
payload = (J)(uintptr_t)cell;
}
if (target_tag == K_TYPE_LONG) {
out[i] = payload;
} else if (target_tag == K_TYPE_INT) {
((I *)out)[i] = (I)payload;
} else if (target_tag == K_TYPE_SHORT) {
((I16 *)out)[i] = (I16)payload;
} else if (target_tag == K_TYPE_BOOL) {
if (payload & 1) ((char *)out)[i >> 3] |= (1 << (i & 7));
} else if (target_tag == K_TYPE_FLOAT) {
((F *)out)[i] = (F)payload;
} else {
((char *)out)[i] = (char)payload;
}
}
release_object((V **)list);
return out;
}
J *csv_emit_row_quoted(V **row, char field_sep, char quote_char)
{
J *out = allocate_typed_vector(K_TYPE_PAIR_CHAIN, 0);
uJ n = (uJ)*(I *)((char *)row - 4);
for (uJ i = 0; i < n; i++) {
if (i > 0) out = (J *)charvec_append_byte((V **)out, field_sep);
char *cell = (char *)row[i];
uI cell_n = (uI)*(I *)(cell - 4);
I needs_quote = 0;
for (uI j = 0; j < cell_n; j++) {
char c = cell[j];
if (c == field_sep || c == quote_char || c == '\n' || c == '\r') {
needs_quote = 1;
break;
}
}
if (needs_quote) {
out = (J *)charvec_append_byte((V **)out, quote_char);
for (uI j = 0; j < cell_n; j++) {
char c = cell[j];
if (c == quote_char) {
out = (J *)charvec_append_byte((V **)out, quote_char);
}
out = (J *)charvec_append_byte((V **)out, c);
}
out = (J *)charvec_append_byte((V **)out, quote_char);
} else {
for (uI j = 0; j < cell_n; j++) {
out = (J *)charvec_append_byte((V **)out, cell[j]);
}
}
}
return out;
}
F stats_correlation_long(J *x, J *y)
{
uJ n = (uJ)*(I *)((char *)x - 4);
if (n == 0) return 0.0;
F mx = aggregate_avg_long(x);
F my = aggregate_avg_long(y);
F cov = 0, vx = 0, vy = 0;
for (uJ i = 0; i < n; i++) {
F dx = (F)x[i] - mx;
F dy = (F)y[i] - my;
cov += dx * dy;
vx += dx * dx;
vy += dy * dy;
}
F denom = sqrt(vx * vy);
return denom == 0.0 ? 0.0 : cov / denom;
}
F stats_covariance_long(J *x, J *y)
{
uJ n = (uJ)*(I *)((char *)x - 4);
if (n == 0) return 0.0;
F mx = aggregate_avg_long(x);
F my = aggregate_avg_long(y);
F s = 0.0;
for (uJ i = 0; i < n; i++) {
s += ((F)x[i] - mx) * ((F)y[i] - my);
}
return s / (F)n;
}
F stats_median_long(J *vec)
{
uJ n = (uJ)*(I *)((char *)vec - 4);
if (n == 0) return 0.0;
J *copy = (J *)malloc(n * sizeof(J));
memcpy(copy, vec, n * sizeof(J));
quicksort_long(copy, (I)n);
F m = (n % 2)
? (F)copy[n / 2]
: ((F)copy[n / 2 - 1] + (F)copy[n / 2]) / 2.0;
free(copy);
return m;
}
J stats_mode_long(J *vec)
{
uJ n = (uJ)*(I *)((char *)vec - 4);
if (n == 0) return 0;
J best = vec[0];
I best_cnt = 1;
for (uJ i = 0; i < n; i++) {
I cnt = 0;
for (uJ j = 0; j < n; j++) {
if (vec[j] == vec[i]) cnt++;
}
if (cnt > best_cnt) {
best_cnt = cnt;
best = vec[i];
}
}
return best;
}
static const char REPL_PROMPT[] = "k10) ";
static const char REPL_CONTINUE_PROMPT[] = " ";
static const char REPL_BANNER_HEADER[] = " k10 1.0";
static const char REPL_NEWLINE[] = "\n";
static const char DIAGNOSTIC_BANNED[] = "ba";
static const char DIAGNOSTIC_MISSING_SORT[] = "msrt";
static const char DIAGNOSTIC_MISSING_REVERSE[] = "mrev";
static const char DIAGNOSTIC_MISSING_CONCAT[] = "mcat";
static const char DIAGNOSTIC_TYPE_BAD[] = "tcba";
static const char DIAGNOSTIC_DOMAIN_DD[] = "dd";
static const char DIAGNOSTIC_NOT_IMPL[] = "nyi";
static const char DIAGNOSTIC_NO_CAST[] = "nyc";
J *cast_to_bool_inner_helper_full(__int128 *vec, char *zmm1)
{
uJ hdr = (uJ)*(G *)((char *)vec - 5);
uJ n = (uJ)*(I *)((char *)vec - 4);
J *out = allocate_zero_filled_typed(K_TYPE_BOOL, (I)n);
if (hdr == K_TYPE_LONG) {
J *p = (J *)vec;
for (uJ i = 0; i < n; i++) {
if (p[i] != 0) ((char *)out)[i >> 3] |= (char)(1 << (i & 7));
}
} else if (hdr == K_TYPE_INT) {
I *p = (I *)vec;
for (uJ i = 0; i < n; i++) {
if (p[i] != 0) ((char *)out)[i >> 3] |= (char)(1 << (i & 7));
}
} else if (hdr == K_TYPE_SHORT) {
I16 *p = (I16 *)vec;
for (uJ i = 0; i < n; i++) {
if (p[i] != 0) ((char *)out)[i >> 3] |= (char)(1 << (i & 7));
}
} else if (hdr == K_TYPE_FLOAT) {
F *p = (F *)vec;
for (uJ i = 0; i < n; i++) {
if (p[i] != 0.0) ((char *)out)[i >> 3] |= (char)(1 << (i & 7));
}
} else {
G *p = (G *)vec;
for (uJ i = 0; i < n; i++) {
if (p[i] != 0) ((char *)out)[i >> 3] |= (char)(1 << (i & 7));
}
}
(void)zmm1;
return out;
}
static V k10_comp_i64(I v, J *a, J *b, G *o, I n) {
for (I i = 0; i < n; i++) {
I r = (v == 1) ? a[i] < b[i] :
(v == 2) ? a[i] == b[i] :
(v == 4) ? a[i] > b[i] : a[i] == b[i];
if (r) o[i >> 3] |= (G)(1 << (i & 7));
}
}
static V k10_comp_i32(I v, I *a, I *b, G *o, I n) {
for (I i = 0; i < n; i++) {
I r = (v == 1) ? a[i] < b[i] :
(v == 2) ? a[i] == b[i] :
(v == 4) ? a[i] > b[i] : a[i] == b[i];
if (r) o[i >> 3] |= (G)(1 << (i & 7));
}
}
static V k10_comp_i16(I v, I16 *a, I16 *b, G *o, I n) {
for (I i = 0; i < n; i++) {
I r = (v == 1) ? a[i] < b[i] :
(v == 2) ? a[i] == b[i] :
(v == 4) ? a[i] > b[i] : a[i] == b[i];
if (r) o[i >> 3] |= (G)(1 << (i & 7));
}
}
static V k10_comp_f64(I v, F *a, F *b, G *o, I n) {
for (I i = 0; i < n; i++) {
I r = (v == 1) ? a[i] < b[i] :
(v == 2) ? a[i] == b[i] :
(v == 4) ? a[i] > b[i] : a[i] == b[i];
if (r) o[i >> 3] |= (G)(1 << (i & 7));
}
}
static V k10_comp_u8(I v, G *a, G *b, G *o, I n) {
for (I i = 0; i < n; i++) {
I r = (v == 1) ? a[i] < b[i] :
(v == 2) ? a[i] == b[i] :
(v == 4) ? a[i] > b[i] : a[i] == b[i];
if (r) o[i >> 3] |= (G)(1 << (i & 7));
}
}
V **k10_per_tag_comp(I verb, V *a, V *b) {
I n = XN(a); G t = XT(a);
G *out = (G *)allocate_zero_filled_typed(K_TYPE_BOOL, n);
if (t == K_TYPE_LONG) k10_comp_i64(verb, (J *)a, (J *)b, out, n);
else if (t == K_TYPE_INT) k10_comp_i32(verb, (I *)a, (I *)b, out, n);
else if (t == K_TYPE_SHORT) k10_comp_i16(verb, (I16 *)a, (I16 *)b, out, n);
else if (t == K_TYPE_FLOAT) k10_comp_f64(verb, (F *)a, (F *)b, out, n);
else k10_comp_u8(verb, (G *)a, (G *)b, out, n);
return (V **)out;
}
static J k10_comp_atoms(I v, K a, K b, U32 ta, U32 tb) {
if ((ta - 8) <= 6 && (tb - 8) <= 6) {
J pa = *(J *)((uJ)a & K_PAYLOAD_BITS_48);
J pb = *(J *)((uJ)b & K_PAYLOAD_BITS_48);
I r = (v == 1) ? pa < pb : (v == 2) ? pa == pb :
(v == 4) ? pa > pb : pa == pb;
return (J)box_atom(K_TYPE_BOOL, r);
}
return (J)box_atom(K_TYPE_BOOL, (ta == tb && a == b));
}
static J k10_comp_mixed(I v, K a, K b, U32 ta, U32 tb) {
K vec = (ta == 0) ? a : b, atom = (ta == 0) ? b : a;
I n = XN(vec); G hdr = XT(vec);
J *bc = allocate_typed_vector(hdr, n);
J pl = ((uJ)atom >> 48) == K_TYPE_LONG ?
*(J *)((uJ)atom & K_PAYLOAD_BITS_48) : (J)(intptr_t)atom;
for (I i = 0; i < n; i++) {
if (hdr == K_TYPE_LONG) bc[i] = pl;
else if (hdr == K_TYPE_INT) ((I *)bc)[i] = (I)pl;
else if (hdr == K_TYPE_SHORT) ((I16 *)bc)[i] = (I16)pl;
else ((G *)bc)[i] = (G)pl;
}
V **r = k10_per_tag_comp(v, ta == 0 ? a : (V *)bc,
ta == 0 ? (V *)bc : b);
release_object((V **)bc); return (J)r;
}
J k10_gen_comp(I v, V *a, V *b) {
U32 ta = (U32)((J)a >> 48), tb = (U32)((J)b >> 48);
if (ta && tb) return k10_comp_atoms(v, (K)a, (K)b, ta, tb);
if (!ta && !tb) return (J)k10_per_tag_comp(v, a, b);
return k10_comp_mixed(v, (K)a, (K)b, ta, tb);
}
static I k10_sym_intern_match(I idx, const char *name, I len) {
K *vecs = (K *)runtime_sym_table_charvecs;
if (!vecs) return 0;
S ex = (S)vecs[idx];
if (XN(ex) != len) return 0;
return memcmp(ex, name, (size_t)len) == 0;
}
static I k10_sym_intern_new(SymbolInternEntry *e, uJ h,
const char *name, I len) {
K cv = (K)allocate_typed_vector_init(K_TYPE_PAIR_CHAIN, len, name);
I idx = symbol_intern_insert((J *)cv);
e->hash = h; e->index = idx; e->used = 1;
return idx;
}
I k10_sym_intern_or_get(const char *name, I len) {
uJ h = murmur64_charvec(name, len);
I sz = SYMBOL_INTERN_TABLE_SIZE, idx = (I)(h % (uJ)sz);
for (I i = 0; i < sz; i++) {
I p = (idx + i) % sz;
SymbolInternEntry *e = &symbol_intern_table[p];
if (!e->used) return k10_sym_intern_new(e, h, name, len);
if (e->hash == h && e->index >= 0) {
if (k10_sym_intern_match(e->index, name, len))
return e->index;
}
}
return -1;
}
J k10_sym_pack_imm(const char *name, I len) {
if (len <= 8) {
uJ v = 0;
for (I i = 0; i < len; i++) v |= (uJ)(G)name[i] << (i * 8);
return (J)box_atom(2, (J)v);
}
return (J)box_atom(2, (J)k10_sym_intern_or_get(name, len));
}
V k10_ipc_ser_keyed(V *v, char **dst) {
*(*dst)++ = (char)K_TYPE_KEYED_PAIR;
ipc_serialize_any((V *)*(J *)v, dst);
ipc_serialize_any((V *)((J *)v)[1], dst);
}
J k10_ipc_deser_keyed(const char **src) {
J k = ipc_deserialize_any(src);
J v = ipc_deserialize_any(src);
return (J)pair_cell_make(K_TYPE_KEYED_PAIR, k, (J *)v);
}
J *k10_bigint_canon(J *v) {
I n = XN(v);
while (n > 1 && v[n - 1] == 0) n--;
if (n != XN(v)) XN(v) = n;
return v;
}
J *k10_bigint_add(J *a, J *b) {
I na = XN(a), nb = XN(b), nm = na > nb ? na : nb;
J *out = allocate_typed_vector(K_TYPE_LONG, nm + 1);
__uint128_t c = 0;
for (I i = 0; i <= nm; i++) {
__uint128_t va = i < na ? (uJ)a[i] : 0;
__uint128_t vb = i < nb ? (uJ)b[i] : 0;
__uint128_t s = va + vb + c;
out[i] = (J)(uJ)s; c = s >> 64;
}
release_object((V **)a); release_object((V **)b); return k10_bigint_canon(out);
}
I k10_bigint_comp(J *a, J *b) {
J *aa = k10_bigint_canon(a), *bb = k10_bigint_canon(b);
I na = XN(aa), nb = XN(bb);
if (na != nb) return na < nb ? -1 : 1;
for (I i = na; i > 0; i--) {
uJ va = (uJ)aa[i - 1], vb = (uJ)bb[i - 1];
if (va != vb) return va < vb ? -1 : 1;
}
return 0;
}
static I k10_count_unbal(const char *ln, I n) {
I d = 0, s = 0;
for (I i = 0; i < n; i++) {
char c = ln[i];
if (s) {
if (c == '\\' && i + 1 < n) { i++; continue; }
if (c == '"') s = 0;
} else {
if (c == '"') s = 1;
else if (c == '{' || c == '[' || c == '(') d++;
else if (c == '}' || c == ']' || c == ')') d--;
}
}
return d;
}
I k10_is_cont(const char *ln, I n) {
if (n == 0) return 0;
while (n > 0 && (ln[n-1] == ' ' || ln[n-1] == '\t')) n--;
if (n == 0) return 0;
char last = ln[n-1];
if (last == '{' || last == '[' || last == '(' ||
last == ';' || last == '\\') return 1;
return k10_count_unbal(ln, n) > 0;
}
static V k10_repl_prompt(I cont) {
if (cont) write(STDOUT_FILENO, " ", 2);
else write(STDOUT_FILENO, "K10) ", 5);
}
static char *k10_repl_append(char *b, size_t *c, size_t *l,
char *ln, I n) {
if (*l + (size_t)n + 2 > *c) {
*c = (*l + (size_t)n + 2) * 2;
b = (char *)realloc(b, *c);
}
if (*l > 0) b[(*l)++] = '\n';
memcpy(b + *l, ln, (size_t)n);
*l += (size_t)n; b[*l] = 0;
return b;
}
char *k10_repl_read(void) {
size_t cap = 256, len = 0;
char *buf = (char *)malloc(cap);
if (!buf) return NULL;
buf[0] = 0; I cont = 0;
while (1) {
k10_repl_prompt(cont);
char ln[1024]; ssize_t n = read(STDIN_FILENO, ln, 1023);
if (n <= 0) { free(buf); return NULL; }
while (n > 0 && (ln[n-1] == '\n' || ln[n-1] == '\r')) n--;
ln[n] = 0;
if (n == 2 && ln[0] == '\\' && ln[1] == '\\') {
free(buf); return NULL;
}
buf = k10_repl_append(buf, &cap, &len, ln, (I)n);
if (!k10_is_cont(ln, (I)n)) break;
cont = 1;
}
return buf;
}
static J k10_atom_atom_dispatch(char v, U32 ta, U32 tb,
J a, J b, I *h) {
*h = 0;
if (!ta || !tb || (ta - 8) > 6 || (tb - 8) > 6) return 0;
J pa = ((0x7F00 >> ta) & 1) ? *(J *)((uJ)a & K_PAYLOAD_BITS_48) : (J)(intptr_t)a;
J pb = ((0x7F00 >> tb) & 1) ? *(J *)((uJ)b & K_PAYLOAD_BITS_48) : (J)(intptr_t)b;
*h = 1;
switch (v) {
case '+': return (J)box_atom(K_TYPE_LONG, pa + pb);
case '-': return (J)box_atom(K_TYPE_LONG, pa - pb);
case '*': return (J)box_atom(K_TYPE_LONG, pa * pb);
case '%': return (J)box_atom(K_TYPE_LONG, pb ? pa / pb : INT64_MIN);
case '&': return (J)box_atom(K_TYPE_LONG, pa < pb ? pa : pb);
case '|': return (J)box_atom(K_TYPE_LONG, pa > pb ? pa : pb);
case '<': return (J)box_atom(K_TYPE_BOOL, pa < pb);
case '=': return (J)box_atom(K_TYPE_BOOL, pa == pb);
case '>': return (J)box_atom(K_TYPE_BOOL, pa > pb);
case '~': return (J)box_atom(K_TYPE_BOOL, pa == pb);
case '#': return (J)reshape_to_target_tag((I)pa, (V **)b);
case '_': return (J)dyadic_drop_n((I)pa, (V *)b);
default: *h = 0; return 0;
}
}
static J k10_long_vec_dispatch(char v, J a, J b, I *h) {
*h = 1;
switch (v) {
case '+': return (J)long_vector_add((J *)a, (J *)b);
case '-': return (J)long_vector_sub((J *)a, (J *)b);
case '*': return (J)long_vector_mul((J *)a, (J *)b);
case '%': return (J)long_vector_div((J *)a, (J *)b);
case '&': return (J)long_vector_min((J *)a, (J *)b);
case '|': return (J)long_vector_max((J *)a, (J *)b);
case '<': return (J)long_vector_lt((J *)a, (J *)b);
case '=': return (J)long_vector_eq((J *)a, (J *)b);
case '?': return (J)vector_match_index((J *)a, (J *)b);
default: *h = 0; return 0;
}
}
static J k10_float_vec_dispatch(char v, J a, J b, I *h) {
*h = 1;
switch (v) {
case '+': return (J)float_vector_add((F *)a, (F *)b);
case '-': return (J)float_vector_sub((F *)a, (F *)b);
case '*': return (J)float_vector_mul((F *)a, (F *)b);
case '%': return (J)float_vector_div((F *)a, (F *)b);
default: *h = 0; return 0;
}
}
static J k10_vec_vec_dispatch(char v, J a, J b, I *h) {
G ha = XT((V *)a), hb = XT((V *)b);
if (ha == K_TYPE_LONG && hb == K_TYPE_LONG)
return k10_long_vec_dispatch(v, a, b, h);
if (ha == K_TYPE_FLOAT && hb == K_TYPE_FLOAT)
return k10_float_vec_dispatch(v, a, b, h);
if (v == '<' || v == '=' || v == '>') {
*h = 1; I cv = v == '<' ? 1 : (v == '=' ? 2 : 4);
return k10_gen_comp(cv, (V *)a, (V *)b);
}
*h = 0; return 0;
}
static J k10_bcast_l(char v, U32 ta, J a, J b) {
I n = XN((V *)b); G hb = XT((V *)b);
J *bc = allocate_typed_vector(hb, n);
J pa = ((0x7F00 >> ta) & 1) ? *(J *)((uJ)a & K_PAYLOAD_BITS_48) : (J)(intptr_t)a;
for (I i = 0; i < n; i++) {
if (hb == K_TYPE_LONG) bc[i] = pa;
else ((I *)bc)[i] = (I)pa;
}
return k10_verb_dispatch(v, (J)bc, b);
}
static J k10_bcast_r(char v, U32 tb, J a, J b) {
I n = XN((V *)a); G ha = XT((V *)a);
J *bc = allocate_typed_vector(ha, n);
J pb = ((0x7F00 >> tb) & 1) ? *(J *)((uJ)b & K_PAYLOAD_BITS_48) : (J)(intptr_t)b;
for (I i = 0; i < n; i++) {
if (ha == K_TYPE_LONG) bc[i] = pb;
else ((I *)bc)[i] = (I)pb;
}
return k10_verb_dispatch(v, a, (J)bc);
}
J k10_verb_dispatch(char v, J a, J b) {
U32 ta = (U32)((uJ)a >> 48), tb = (U32)((uJ)b >> 48);
I h = 0; J r = k10_atom_atom_dispatch(v, ta, tb, a, b, &h);
if (h) return r;
if (!ta && !tb) {
r = k10_vec_vec_dispatch(v, a, b, &h);
if (h) return r;
}
if (ta && !tb) return k10_bcast_l(v, ta, a, b);
if (!ta && tb) return k10_bcast_r(v, tb, a, b);
emit_numeric_error_diag(DIAGNOSTIC_NOT_IMPL); return 5;
}
J k_monadic_dispatch(char verb, J a)
{
uI ta = (uI)((uJ)a >> K_TAG_SHIFT);
if (ta != 0 && (ta - 8) <= 6) {
J pa = ((K_TAGCLASS_ATOMIC_BOX >> ta) & 1)
? *(J *)((uJ)a & K_PTR_MASK) : (J)(intptr_t)a;
switch (verb) {
case '-': return (J)box_atom(ta, -pa);
case '~': return (J)box_atom(K_TYPE_BOOL, pa == 0);
case '#': return (J)box_atom(K_TYPE_LONG, 1);
case '*': return a;
case ',': return (J)allocate_typed_vector_init((I)ta, 1, &pa);
}
}
if (ta == 0) {
uJ hd = (uJ)*(G *)((char *)a - 5);
switch (verb) {
case '-':
if (hd == K_TYPE_LONG) return (J)long_vector_neg((J *)a);
if (hd == K_TYPE_FLOAT) {
F *p = (F *)a;
uJ n = (uJ)*(I *)((char *)p - 4);
F *out = (F *)allocate_typed_vector(K_TYPE_FLOAT, (I)n);
for (uJ i = 0; i < n; i++) out[i] = -p[i];
release_object((V **)a);
return (J)out;
}
break;
case '~': return (J)bitwise_complement_in_place((V **)a);
case '|': return (J)monadic_reverse((V *)a);
case '#': return (J)box_atom(K_TYPE_LONG, (J)kind_or_length_walk((V *)a));
case '&': if (hd == K_TYPE_BOOL) return (J)monadic_where_indices((J *)a); break;
case '?': if (hd == K_TYPE_LONG) return (J)monadic_distinct_long((J *)a); break;
case '*': return (J)vector_first((J *)a);
case ',': return (J)apply_unary_or_singleton((J *)a, 0, 0);
}
}
emit_numeric_error_diag(DIAGNOSTIC_NOT_IMPL);
return 5;
}
J apply_function_with_args(J *fn, I n_args, J *args)
{
if (((J)fn >> K_TAG_SHIFT) != 0) {
if (n_args == 1) return k_monadic_dispatch((char)(uintptr_t)fn, args[0]);
if (n_args == 2) return k_verb_dispatch((char)(uintptr_t)fn, args[0], args[1]);
}
I expected = rank_of_function(fn);
if (n_args < expected) {
J *closure = allocate_typed_vector(K_TYPE_LIST, n_args + 2);
closure[0] = (J)retain_object(fn);
closure[1] = (J)expected;
for (I i = 0; i < n_args; i++) closure[i + 2] = args[i];
*(G *)((char *)closure - 5) = (G)K_TYPE_LITERAL_FUNC;
return (J)closure;
}
return apply_n_args(fn, n_args, (uJ)args);
}
I kalloc_alignment_check(V *slot)
{
uintptr_t addr = (uintptr_t)slot;
if (addr & 63) {
char buf[64];
I len = sprintf(buf, "ALIGN: kalloc returned %p not 64-byte\n", slot);
write(STDERR_FILENO, buf, (size_t)len);
return 0;
}
return 1;
}
I kalloc_header_layout_check(V *slot)
{
G cls = XC(slot);
uI n = (uI)XN(slot);
G type_tag = XT(slot);
uI l2 = (uI)k_type_log2_bits_table[type_tag];
uJ bytes = (((uJ)n << l2) + 7) >> 3;
uJ need_bits = bytes + K_ALLOC_ROUND;
if (need_bits == 0) return 1;
I msb = 63 - __builtin_clzll(need_bits);
uI expected_cls = (uI)(msb - 2);
return cls == (G)expected_cls;
}
I tls_heap_self_check(void)
{
for (I c = 0; c <= K_CLASS_MAX; c++) {
J count = 0;
J head = tls_heap.freelist[c];
while (head != 0 && count < 0x1000000) {
G cls = *(G *)((char *)head - 16);
if (cls != (G)c) {
char buf[80];
I len = sprintf(buf, "TLS_HEAP_BAD: class %d slot %p has cls=%d\n",
c, (V *)head, cls);
write(STDERR_FILENO, buf, (size_t)len);
return 0;
}
head = *(J *)head;
count++;
}
}
return 1;
}
J *kalloc_aligned_64(I type, I length)
{
J *p = kalloc(type, length);
if (!kalloc_alignment_check(p)) {
}
return p;
}
V runtime_integrity_summary(void)
{
char buf[256];
I len = sprintf(buf,
"Runtime: heap=%lldB free=%lldB pressure=%.2f tls_check=%s\n",
(long long)runtime_heap_size_bytes,
(long long)freelist_total_free_bytes(),
heap_pressure_ratio(),
tls_heap_self_check() ? "ok" : "FAIL");
write(STDOUT_FILENO, buf, (size_t)len);
}
V hash_dict_init(HashDict *d, I initial_cap)
{
if (initial_cap < HASH_DICT_INITIAL_CAP) initial_cap = HASH_DICT_INITIAL_CAP;
d->entries = (HashDictEntry *)calloc((size_t)initial_cap, sizeof(HashDictEntry));
d->capacity = initial_cap;
d->count = 0;
}
V hash_dict_free(HashDict *d)
{
if (d->entries) free(d->entries);
d->entries = NULL;
d->capacity = 0;
d->count = 0;
}
static I hash_dict_probe_slot(HashDict *d, J key, uJ h)
{
I mask = d->capacity - 1;
I start = (I)(h & (uJ)mask);
for (I i = 0; i < d->capacity; i++) {
I pos = (start + i) & mask;
HashDictEntry *e = &d->entries[pos];
if (!e->used) return pos;
if (e->key == key) return pos;
}
return -1;
}
static V hash_dict_grow(HashDict *d)
{
I new_cap = d->capacity * 2;
HashDictEntry *new_e = (HashDictEntry *)calloc((size_t)new_cap, sizeof(HashDictEntry));
HashDictEntry *old_e = d->entries;
I old_cap = d->capacity;
d->entries = new_e;
d->capacity = new_cap;
d->count = 0;
for (I i = 0; i < old_cap; i++) {
if (old_e[i].used) {
I slot = hash_dict_probe_slot(d, old_e[i].key, old_e[i].hash);
d->entries[slot] = old_e[i];
d->count++;
}
}
free(old_e);
}
V hash_dict_set(HashDict *d, J key, J value)
{
if (d->count * 2 >= d->capacity) hash_dict_grow(d);
uJ h = hash_long_value(key);
I slot = hash_dict_probe_slot(d, key, h);
if (!d->entries[slot].used) {
d->entries[slot].key = key;
d->entries[slot].hash = h;
d->entries[slot].used = 1;
d->count++;
}
d->entries[slot].val = value;
}
I hash_dict_get(HashDict *d, J key, J *out_value)
{
if (d->count == 0) return 0;
uJ h = hash_long_value(key);
I slot = hash_dict_probe_slot(d, key, h);
if (slot < 0 || !d->entries[slot].used) return 0;
if (out_value) *out_value = d->entries[slot].val;
return 1;
}
I hash_dict_remove(HashDict *d, J key)
{
if (d->count == 0) return 0;
uJ h = hash_long_value(key);
I slot = hash_dict_probe_slot(d, key, h);
if (slot < 0 || !d->entries[slot].used) return 0;
d->entries[slot].used = 0;
d->count--;
I mask = d->capacity - 1;
I i = (slot + 1) & mask;
while (d->entries[i].used) {
HashDictEntry e = d->entries[i];
d->entries[i].used = 0;
d->count--;
I new_slot = hash_dict_probe_slot(d, e.key, e.hash);
d->entries[new_slot] = e;
d->count++;
i = (i + 1) & mask;
}
return 1;
}
V string_builder_init(StringBuilder *sb)
{
sb->buf = (char *)malloc(64);
sb->length = 0;
sb->capacity = 64;
}
V string_builder_free(StringBuilder *sb)
{
if (sb->buf) free(sb->buf);
sb->buf = NULL;
sb->length = sb->capacity = 0;
}
V string_builder_append(StringBuilder *sb, const char *src, I n)
{
while (sb->length + n > sb->capacity) {
sb->capacity *= 2;
sb->buf = (char *)realloc(sb->buf, (size_t)sb->capacity);
}
memcpy(sb->buf + sb->length, src, (size_t)n);
sb->length += n;
}
V string_builder_append_byte(StringBuilder *sb, char c)
{
if (sb->length + 1 > sb->capacity) {
sb->capacity *= 2;
sb->buf = (char *)realloc(sb->buf, (size_t)sb->capacity);
}
sb->buf[sb->length++] = c;
}
V string_builder_append_int(StringBuilder *sb, J v)
{
char buf[24];
I len = sprintf(buf, "%lld", (long long)v);
string_builder_append(sb, buf, len);
}
V string_builder_append_double(StringBuilder *sb, F v)
{
char buf[32];
I len = format_double_round_trip(buf, v);
string_builder_append(sb, buf, len);
}
J *string_builder_to_charvec(StringBuilder *sb)
{
J *out = allocate_typed_vector_init(K_TYPE_PAIR_CHAIN,
sb->length, sb->buf);
string_builder_free(sb);
return out;
}
I compare_k_values(J a, J b)
{
uI ta = (uI)((uJ)a >> K_TAG_SHIFT);
uI tb = (uI)((uJ)b >> K_TAG_SHIFT);
if (ta != 0 && tb != 0) {
if (ta == K_TYPE_LONG && tb == K_TYPE_LONG) {
J pa = *(J *)((uJ)a & K_PTR_MASK);
J pb = *(J *)((uJ)b & K_PTR_MASK);
return pa < pb ? -1 : (pa > pb ? 1 : 0);
}
if (ta == K_TYPE_FLOAT && tb == K_TYPE_FLOAT) {
F pa = *(F *)((uJ)a & K_PTR_MASK);
F pb = *(F *)((uJ)b & K_PTR_MASK);
return pa < pb ? -1 : (pa > pb ? 1 : 0);
}
if ((ta - 8) <= 6 && (tb - 8) <= 6) {
J pa = (J)*(J *)((uJ)a & K_PTR_MASK);
J pb = (J)*(J *)((uJ)b & K_PTR_MASK);
return pa < pb ? -1 : (pa > pb ? 1 : 0);
}
return ta < tb ? -1 : (ta > tb ? 1 : 0);
}
if (ta == 0 && tb == 0) {
uJ hda = (uJ)*(G *)((char *)a - 5);
uJ hdb = (uJ)*(G *)((char *)b - 5);
if (hda != hdb) return hda < hdb ? -1 : 1;
uJ na = (uJ)*(I *)((char *)a - 4);
uJ nb = (uJ)*(I *)((char *)b - 4);
uJ nmin = na < nb ? na : nb;
if (hda == K_TYPE_LONG) {
J *pa = (J *)a, *pb = (J *)b;
for (uJ i = 0; i < nmin; i++) {
if (pa[i] != pb[i]) return pa[i] < pb[i] ? -1 : 1;
}
} else if (hda == K_TYPE_PAIR_CHAIN) {
I r = memcmp((V *)a, (V *)b, (size_t)nmin);
if (r != 0) return r < 0 ? -1 : 1;
}
return na < nb ? -1 : (na > nb ? 1 : 0);
}
return ta == 0 ? 1 : -1;
}
static I compare_k_qsort_asc(const V *a, const V *b)
{
return compare_k_values(*(J *)a, *(J *)b);
}
static I compare_k_qsort_desc(const V *a, const V *b)
{
return -compare_k_values(*(J *)a, *(J *)b);
}
J *sort_k_list_ascending(J *list)
{
uJ n = (uJ)*(I *)((char *)list - 4);
qsort(list, n, sizeof(J), compare_k_qsort_asc);
return list;
}
J *sort_k_list_descending(J *list)
{
uJ n = (uJ)*(I *)((char *)list - 4);
qsort(list, n, sizeof(J), compare_k_qsort_desc);
return list;
}
static const I days_in_month_nonleap[12] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
I is_leap_year(I year)
{
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
I days_in_month(I year, I month)
{
if (month < 1 || month > 12) return 0;
if (month == 2 && is_leap_year(year)) return 29;
return days_in_month_nonleap[month - 1];
}
I day_of_week(I year, I month, I day)
{
if (month < 3) { month += 12; year--; }
I K = year % 100;
I J = year / 100;
I h = (day + (13 * (month + 1)) / 5 + K + K / 4 + J / 4 + 5 * J) % 7;
return (h + 6) % 7;
}
I day_of_year(I year, I month, I day)
{
I doy = day;
for (I m = 1; m < month; m++) doy += days_in_month(year, m);
return doy;
}
I runtime_self_test(void)
{
if (!tls_heap_self_check()) {
write_cstr_stderr("self_test: tls_heap_self_check failed\n");
return 0;
}
J *v = allocate_typed_vector(K_TYPE_LONG, 4);
v[0] = 1; v[1] = 2; v[2] = 3; v[3] = 4;
J sum = aggregate_sum_long(v);
release_object((V **)v);
if (sum != 10) {
write_cstr_stderr("self_test: aggregate_sum_long failed\n");
return 0;
}
J *atom = (J *)box_atom(K_TYPE_LONG, 42);
J *r = pretty_print_any(atom, 0);
release_object((V **)r); release_object((V **)atom);
return 1;
}
V k10_print_version(void) {
write_cstr_stderr(REPL_BANNER_HEADER);
write_cstr_stderr("\n");
write_cstr_stderr("(k10 deobfuscated, AVX-2)\n");
}
static I k10_double_scan_dot(const char *s,
I n, I p) {
while (p < n) {
if (s[p] == '.') return p;
p++;
}
return n;
}
static I k10_double_find_dot(const char *s,
I n) {
int256_t dot_v = _mm256_set1_epi8('.');
I p = 0;
while (p + 32 <= n) {
int256_t c = _mm256_loadu_si256((const int256_t *)(s + p));
int256_t m = _mm256_cmpeq_epi8(c, dot_v);
uI mk = (uI)_mm256_movemask_epi8(m);
if (mk != 0) return p + (I)__builtin_ctz(mk);
p += 32;
}
return k10_double_scan_dot(s, n, p);
}
static F k10_double_accum_whole(const char *s,
I n) {
J res = 0;
if (n == 0) return 0.0;
res = (J)((G)s[0] - '0');
for (I i = 1; i < n; i++) {
res = res * 10 + (G)s[i] - '0';
}
return (F)res;
}
static F k10_double_accum_frac(const char *s,
I n) {
if (n >= 3) {
F v = (F)((((G)s[1]) & K_NIBBLE_MAX) +
(((G)s[0] & K_NIBBLE_MAX) * 10));
return v / 100.0;
}
if (n == 2) return (F)((G)s[0] & K_NIBBLE_MAX) / 10.0;
return 0.0;
}
__attribute__((target("avx2")))
F k10_parse_double_avx2(I n, char *s, F *fs) {
P(n == 0, 0.0);
if (s[n - 1] == 'n') return 0.0 / 0.0;
if (s[n - 1] == 'w') {
F inf = 1.0 / 0.0;
return s[0] == '-' ? -inf : inf;
}
I sign = (s[0] == '-') ? 1 : 0;
I dp = k10_double_find_dot(s + sign, n - sign);
I il = dp < 8 ? dp : 8;
F val = k10_double_accum_whole(s + sign, il);
*fs = k10_double_accum_frac(s + sign + il + 1,
n - sign - il);
val += *fs;
return sign ? -val : val;
}
static I k10_int_check_avx2(const char *s, I n) {
int256_t lo = _mm256_set1_epi8('0' - 1);
int256_t hi = _mm256_set1_epi8('9' + 1);
I p = 0;
while (p + 32 <= n) {
int256_t c = _mm256_loadu_si256((const int256_t *)(s + p));
int256_t l = _mm256_cmpgt_epi8(c, lo);
int256_t h = _mm256_cmpgt_epi8(hi, c);
if (_mm256_movemask_epi8(_mm256_and_si256(l, h)) != -1)
return 0;
p += 32;
}
while (p < n) {
if (s[p] < '0' || s[p] > '9') return 0;
p++;
}
return 1;
}
static J k10_int_accum(const char *s, I n) {
J res = 0;
for (I i = 0; i < n; i++) {
res = res * 10 + (J)((G)s[i] - '0');
}
return res;
}
__attribute__((target("avx2")))
J k10_parse_int_avx2(I n, char *s) {
P(n == 0, INT64_MIN);
if ((G)s[n - 1] == 'N') return INT64_MIN;
I sign = (s[0] == '-') ? 1 : 0;
if (!k10_int_check_avx2(s + sign, n - sign))
return parse_signed_integer(n, s);
J res = k10_int_accum(s + sign, n - sign);
return sign ? -res : res;
}
__attribute__((target("avx2")))
I k10_utf8_count_avx2(const char *src, I n) {
P(n <= 0, 0);
int256_t m = _mm256_set1_epi8((char)0xc0);
int256_t c = _mm256_set1_epi8((char)0x80);
I cc = 0, p = 0;
while (p + 32 <= n) {
int256_t ch = _mm256_loadu_si256((const int256_t *)(src + p));
int256_t is = _mm256_cmpeq_epi8(_mm256_and_si256(ch, m), c);
cc += __builtin_popcount((uI)_mm256_movemask_epi8(is));
p += 32;
}
while (p < n) {
if (((G)src[p] & 0xc0) == K_BYTE_SIGN_BIT) cc++;
p++;
}
return n - cc;
}
static I k10_memcmp_find_off(I mk, const char *a,
const char *b, I p) {
I off = __builtin_ctz((uI)~(uI)mk);
return (I)(G)a[p + off] - (I)(G)b[p + off];
}
__attribute__((target("avx2")))
static I k10_mcmp_tail(const char *pa,
const char *pb,
size_t p, size_t n) {
for (; p < n; p++)
if (pa[p] != pb[p])
return (I)(G)pa[p] - (I)(G)pb[p];
return 0;
}
__attribute__((target("avx2")))
I k10_memcmp_avx2(const V *a, const V *b,
size_t n) {
const char *pa = a, *pb = b; size_t p = 0;
for (; p + 32 <= n; p += 32) {
int256_t va =
_mm256_loadu_si256((V *)(pa+p));
int256_t vb =
_mm256_loadu_si256((V *)(pb+p));
I m = _mm256_movemask_epi8(
_mm256_cmpeq_epi8(va, vb));
if (m != -1)
return k10_memcmp_find_off(m,pa,pb,p);
} return k10_mcmp_tail(pa, pb, p, n);
}
static I k10_zero_tail(J *vec,
I p, I n) {
for (; p < n; p++) if (vec[p] != 0) return 0;
return 1;
}
__attribute__((target("avx2")))
I k10_zero_check_avx2(J *vec, I n) {
int256_t z = _mm256_setzero_si256();
I p = 0;
for (; p + 4 <= n; p += 4) {
int256_t v =
_mm256_loadu_si256((V *)(vec + p));
int256_t eq = _mm256_cmpeq_epi64(v, z);
if (_mm256_movemask_epi8(eq) != -1) return 0;
}
return k10_zero_tail(vec, p, n);
}
static FFIModule *k10_ffi_list = NULL;
static V *k10_ffi_add(const char *p, V *h) {
FFIModule *m =
(FFIModule *)malloc(sizeof(FFIModule));
m->handle = h; m->path = strdup(p);
m->next = k10_ffi_list; k10_ffi_list = m;
return h;
}
static V *k10_dl_err(void) {
fprintf(stderr, "dlopen failed: %s\n",
dlerror());
return NULL;
}
V *k10_ffi_open(const char *path) {
FFIModule *m = k10_ffi_list;
for (; m; m = m->next)
if (!strcmp(m->path, path)) return m->handle;
V *h = dlopen(path, FFI_LAZY);
return h ? k10_ffi_add(path, h) : k10_dl_err();
}
V *k10_ffi_resolve(V *h, const char *s) {
V *p = dlsym(h, s);
if (!p) fprintf(stderr, "dlsym failed: %s\n",
dlerror());
return p;
}
V k10_ffi_close_all(void) {
FFIModule *m = k10_ffi_list;
while (m) {
FFIModule *next = m->next;
if (m->handle) dlclose(m->handle);
free(m->path); free(m);
m = next;
}
k10_ffi_list = NULL;
}
J k10_ffi_call(V *fn, I n, J *args) {
if (n == 0) return ((FFI_0arg)fn)();
if (n == 1) return ((FFI_1arg)fn)(args[0]);
if (n == 2) return ((FFI_2arg)fn)(args[0], args[1]);
if (n == 3)
return ((FFI_3arg)fn)(args[0], args[1], args[2]);
if (n == 4)
return ((FFI_4arg)fn)(args[0],args[1],args[2],args[3]);
return -1;
}
J k10_ffi_call_sig(V *fn, const char *sig,
J *args, I n) {
I ns = (I)strlen(sig);
if (ns < n) n = ns;
for (I i = 0; i < n; i++) {
char s = sig[i];
if (s != FFI_SIG_INT && s != FFI_SIG_STRING &&
s != FFI_SIG_FLOAT) return -1;
}
return k10_ffi_call(fn, n, args);
}
F k10_sqrt_atom(F x) { return x < 0 ? 0.0 / 0.0 : sqrt(x); }
F k10_log_atom(F x) { return x <= 0 ? -1.0 / 0.0 : log(x); }
F k10_exp_atom(F x) { return exp(x); }
F k10_pow(F b, F e) {
return b == 0 && e == 0 ? 1.0 : pow(b, e);
}
J k10_sum_i64(J *vec) {
I n = XN(vec);
if (n == 0) return 0;
J acc = vec[0]; I i = 1;
for (; i + 4 <= n; i += 4) {
acc += vec[i] + vec[i+1];
acc += vec[i+2] + vec[i+3];
}
while (i < n) acc += vec[i++];
return acc;
}
F k10_sum_f64(F *vec) {
I n = XN(vec);
if (n == 0) return 0.0;
F acc = vec[0]; I i = 1;
for (; i + 4 <= n; i += 4) {
acc += vec[i] + vec[i+1];
acc += vec[i+2] + vec[i+3];
}
while (i < n) acc += vec[i++];
return acc;
}
I k10_is_dict(V *v) {
if (((J)v >> 48) != 0) return 0;
if (XT(v) != K_TYPE_KEYED_PAIR) return 0;
V *keys = (V *)*(J *)v;
if (((J)keys >> 48) != 0) return 0;
G kt = XT(keys);
return (kt == 2 || kt == K_TYPE_PAIR_CHAIN ||
kt == 0) ? 1 : 0;
}
I k10_is_temp_tag(uI t) { return (t & 0xfffffff0u) == 0x10; }
I k10_get_temp(I i, J v) {
return (I)((v >> (i * 8)) & K_BYTE_MAX);
}
static V k10_prime_keys(J *ks) {
ks[0] = sym_pack_immediate_full(".csv", 4);
ks[1] = sym_pack_immediate_full(".json", 5);
ks[2] = sym_pack_immediate_full(".k", 2);
ks[3] = sym_pack_immediate_full(".q", 2);
ks[4] = sym_pack_immediate_full(".ffi", 4);
}
static V k10_prime_vals(J *vs) {
vs[0] = (J)read_csv_file_to_table;
vs[1] = (J)json_parse_charvec;
vs[2] = (J)read_file_to_charvec;
vs[3] = (J)read_file_to_charvec;
vs[4] = (J)k10_ffi_open;
}
V k10_prime_extensions(void) {
if (extension_keyword_table != 0) return;
J *ks = allocate_typed_vector(2, 5), *vs = allocate_typed_vector(0, 5);
k10_prime_keys(ks); k10_prime_vals(vs);
extension_keyword_table = (J)pair_cell_make(0xfa, ks, vs);
}
static I k10_avx2_mcmp_test(void) {
char a[64], b[64];
for (I i = 0; i < 64; i++) a[i]=b[i]=(char)i;
if (k10_memcmp_avx2(a, b, 64) != 0) return 0;
b[33] = (char)0xff;
return k10_memcmp_avx2(a, b, 64) < 0;
}
I k10_avx2_test(void) {
if (!k10_avx2_mcmp_test()) return 0;
J zs[8] = {0};
if (!k10_zero_check_avx2(zs, 8)) return 0;
zs[5] = 1;
if (k10_zero_check_avx2(zs, 8)) return 0;
return k10_utf8_count_avx2("hello", 5) == 5;
}
V k10_lr_init(LineReader *r, I fd) {
r->fd = fd; r->buffer_used = 0;
r->buffer_pos = 0; r->eof_seen = 0;
}
static char *k10_lr_ln(LineReader *r, I *len,
I i) {
r->buffer[i] = 0; *len = i - r->buffer_pos;
char *line = r->buffer + r->buffer_pos;
r->buffer_pos = i + 1;
if (*len > 0 && line[*len - 1] == '\r')
line[--(*len)] = 0;
return line;
}
static char *k10_lr_find_nl(LineReader *r, I *len) {
for (I i = r->buffer_pos; i < r->buffer_used; i++)
if (r->buffer[i] == '\n')
return k10_lr_ln(r, len, i);
return NULL;
}
static V k10_lr_compact(LineReader *r) {
if (r->buffer_pos > 0) {
memmove(r->buffer, r->buffer + r->buffer_pos,
(size_t)(r->buffer_used - r->buffer_pos));
r->buffer_used -= r->buffer_pos;
r->buffer_pos = 0;
}
}
static char *k10_lr_eof(LineReader *r, I *len) {
if (r->buffer_pos < r->buffer_used) {
*len = r->buffer_used - r->buffer_pos;
char *line = r->buffer + r->buffer_pos;
line[*len] = 0; r->buffer_pos = r->buffer_used;
return line;
}
return NULL;
}
static char *k10_lr_fill(LineReader *r, I *len) {
k10_lr_compact(r);
I cap = (I)sizeof(r->buffer) - 1;
if (r->buffer_used == cap) {
*len = cap; r->buffer[cap] = 0;
r->buffer_pos = cap; return r->buffer;
}
ssize_t n = read(r->fd, r->buffer + r->buffer_used,
(size_t)(cap - r->buffer_used));
if (n <= 0) r->eof_seen = 1;
else r->buffer_used += (I)n;
return NULL;
}
char *k10_lr_get(LineReader *r, I *len) {
while (1) {
char *ln = k10_lr_find_nl(r, len);
if (ln) return ln;
if (r->eof_seen) return k10_lr_eof(r, len);
ln = k10_lr_fill(r, len);
if (ln) return ln;
}
}
static V k10_probe_mem(long *hs, long *mc) {
long p = sysconf(_SC_PHYS_PAGES);
long sz = sysconf(_SC_PAGE_SIZE);
*hs = (p * sz) / 4;
if (*hs > (16LL << 30)) *hs = 16LL << 30;
*hs = (long)round_up_to_pow2((uJ)*hs);
*mc = (sysconf(_SC_NPROCESSORS_ONLN) + 1) >> 1;
if (*mc > 16) *mc = 16;
}
V k10_runtime_warmup(void) {
long hs, mc;
k10_probe_mem(&hs, &mc);
initialize_runtime(mc, hs);
compile_bootstrap_lambdas();
initialize_verb_tables();
install_signal_handlers();
k10_prime_extensions();
if (!runtime_self_test())
fprintf(stderr, "WARN: runtime_self_test failed\n");
}
V k10_trace_dump(const char *lbl, V *v) {
if (lbl) fprintf(stderr, "%s: ", lbl);
J *r = pretty_print_any(v, 0);
I n = XN(r);
write(STDERR_FILENO, r, (size_t)n);
write(STDERR_FILENO, "\n", 1);
release_object((V **)r);
}
static I k10_trace_depth = 0;
static V k10_tr_ind(void) {
for (I i = 0; i < k10_trace_depth; i++)
write(STDERR_FILENO, " ", 2);
}
static V k10_tr_arg(J a) {
J *r = pretty_print_any((V *)a, 0);
write(STDERR_FILENO, r, (size_t)XN(r));
release_object((V **)r);
}
V k10_trace_enter(const char *name, I n,
J *args) {
if (parse_in_dyadic_context == 0) return;
k10_tr_ind(); fprintf(stderr, "> %s(", name);
for (I i = 0; i < n; i++) {
if (i > 0) fprintf(stderr, ", ");
k10_tr_arg(args[i]);
}
fprintf(stderr, ")\n"); k10_trace_depth++;
}
V k10_trace_exit(const char *name, J res) {
if (parse_in_dyadic_context == 0) return;
if (k10_trace_depth > 0) k10_trace_depth--;
k10_tr_ind(); fprintf(stderr, "< %s = ", name);
J *r = pretty_print_any((V *)res, 0);
write(STDERR_FILENO, r, (size_t)XN(r));
fprintf(stderr, "\n"); release_object((V **)r);
}
I *k10_vec_add_i32(I *a, I *b) {
I n = XN(a);
I *out = (I *)allocate_typed_vector(K_TYPE_INT, n);
for (I i = 0; i < n; i++) out[i] = a[i] + b[i];
release_object((V **)a); release_object((V **)b); return out;
}
I *k10_vec_sub_i32(I *a, I *b) {
I n = XN(a);
I *out = (I *)allocate_typed_vector(K_TYPE_INT, n);
for (I i = 0; i < n; i++) out[i] = a[i] - b[i];
release_object((V **)a); release_object((V **)b); return out;
}
I *k10_vec_mul_i32(I *a, I *b) {
I n = XN(a);
I *out = (I *)allocate_typed_vector(K_TYPE_INT, n);
for (I i = 0; i < n; i++) out[i] = a[i] * b[i];
release_object((V **)a); release_object((V **)b); return out;
}
I16 *k10_vec_add_i16(I16 *a, I16 *b) {
I n = XN(a);
I16 *out = (I16 *)allocate_typed_vector(K_TYPE_SHORT, n);
for (I i = 0; i < n; i++)
out[i] = (I16)(a[i] + b[i]);
release_object((V **)a); release_object((V **)b); return out;
}
G *k10_vec_xor_u8(G *a, G *b) {
I n = XN(a);
G *out = (G *)allocate_typed_vector(K_TYPE_PAIR_CHAIN, n);
for (I i = 0; i < n; i++)
out[i] = (G)(a[i] ^ b[i]);
release_object((V **)a); release_object((V **)b); return out;
}
I k10_vec_all_i64(J *vec) {
I n = XN(vec);
for (I i = 0; i < n; i++)
if (vec[i] == 0) return 0;
return 1;
}
I k10_vec_any_i64(J *vec) {
I n = XN(vec);
for (I i = 0; i < n; i++)
if (vec[i] != 0) return 1;
return 0;
}
J k10_vec_count_i64(J *vec) {
I n = XN(vec); J c = 0;
for (I i = 0; i < n; i++) if (vec[i] != 0) c++;
return c;
}
J *k10_rank_desc_i64(J *vec) {
I n = XN(vec);
J *out = allocate_typed_vector(K_TYPE_LONG, n);
for (I i = 0; i < n; i++) {
J rk = 0;
for (I j = 0; j < n; j++)
if (vec[j] > vec[i]) rk++;
out[i] = rk;
}
return out;
}
J *k10_rank_asc_i64(J *vec) {
I n = XN(vec);
J *out = allocate_typed_vector(K_TYPE_LONG, n);
for (I i = 0; i < n; i++) {
J rk = 0;
for (I j = 0; j < n; j++)
if (vec[j] < vec[i]) rk++;
out[i] = rk;
}
return out;
}
F k10_to_f64_tagged(J v) {
uI t = (uI)((uJ)v >> 48);
if (t == K_TYPE_FLOAT)
return *(F *)((uJ)v & K_PAYLOAD_BITS_48);
if (t == K_TYPE_LONG)
return (F)*(J *)((uJ)v & K_PAYLOAD_BITS_48);
if ((t - 8) <= 6) return (F)(J)(intptr_t)v;
return 0.0;
}
J k10_to_i64_tagged(J v) {
uI t = (uI)((uJ)v >> 48);
if (t == K_TYPE_LONG)
return *(J *)((uJ)v & K_PAYLOAD_BITS_48);
if (t == K_TYPE_FLOAT)
return (J)*(F *)((uJ)v & K_PAYLOAD_BITS_48);
if ((t - 8) <= 6) return (J)(intptr_t)v;
return 0;
}
I k10_to_bool(J v) {
uI t = (uI)((uJ)v >> 48);
if (t != 0) {
J pl = ((K_TAGCLASS_ATOMIC_BOX >> t) & 1)
? *(J *)((uJ)v & K_PAYLOAD_BITS_48)
: (J)(intptr_t)v;
return pl != 0;
}
return (v && XN(v) > 0) ? 1 : 0;
}
V k10_lock_init(SimpleSpinLock *l) { l->locked = 0; }
V k10_lock_acquire(SimpleSpinLock *l) {
while (__sync_lock_test_and_set(&l->locked, 1))
__builtin_ia32_pause();
}
V k10_lock_release(SimpleSpinLock *l) {
__sync_lock_release(&l->locked);
}
static V k10_sing_cp(J *dst, uJ cls,
uJ pl) {
if (((1ULL << cls) & K_TAGCLASS_PAIR_PAYLOAD) != 0)
*(__int128 *)dst = *(__int128 *)pl;
else if (TEST_BITQ(K_TAGCLASS_SCALAR_IMMED, cls))
*(J *)dst = (J)pl;
else
*(J *)dst = *(J *)pl;
}
J k10_singleton_coerce(J arg) {
uJ cls = (uJ)arg >> K_TAG_SHIFT;
J *out = allocate_typed_vector((I)cls, 1);
uJ pl = (uJ)arg & K_PAYLOAD_BITS_48;
k10_sing_cp(out, cls, pl);
release_object((V **)arg); return (J)out;
}
static J k10_prom_get(V *v, I i, I sw) {
if (sw == 0 || sw == 3) return ((G *)v)[i];
if (sw == 4) return ((I16 *)v)[i];
if (sw == 5) return ((I *)v)[i];
return ((J *)v)[i];
}
static V k10_prom_set(V *d, I i, I dw,
J v) {
if (dw == 0 || dw == 3) ((G *)d)[i] = (G)v;
else if (dw == 4) ((I16 *)d)[i] = (I16)v;
else if (dw == 5) ((I *)d)[i] = (I)v;
else ((J *)d)[i] = v;
}
V **k10_promote_vec(I t, __int128 *v) {
if ((I)XT(v) == t) return (V **)v;
I n = XN(v), sw, dw;
J *dst = allocate_typed_vector(t, n);
sw = k_type_log2_bits_table_alias[XT(v)];
dw = k_type_log2_bits_table_alias[t & K_BYTE_MAX];
for (I i = 0; i < n; i++)
k10_prom_set(dst, i, dw, k10_prom_get(v, i, sw));
release_object((V **)v); return (V **)dst;
}
I k10_bitvec_eq(V *a, V *b) {
if (XN(a) != XN(b)) return 0;
size_t sz = (size_t)K_VEC_BYTES(XN(a), K_TYPE_BOOL);
return memcmp(a, b, sz) == 0;
}
J *k10_bitwise_not(V *v) {
G t = XT(v); I n = XN(v);
J *out = allocate_typed_vector(t, n);
for (I i = 0; i < n; i++) {
if (t == K_TYPE_BOOL) ((G *)out)[i] = !((G *)v)[i];
else if (t == K_TYPE_CHAR) ((G *)out)[i] = ~((G *)v)[i];
else if (t == K_TYPE_SHORT)
((I16 *)out)[i] = ~((I16 *)v)[i];
else if (t == K_TYPE_INT)
((I *)out)[i] = ~((I *)v)[i];
else ((J *)out)[i] = ~((J *)v)[i];
}
release_object((V **)v); return out;
}
__int128 *k10_cast_dispatch(I sel, V *src) {
(void)sel;
return src ? (__int128 *)retain_object(src) : NULL;
}
J k10_cast_decimal(__int128 *toks, I mode) {
(void)mode;
return (toks && XN(toks) > 0) ? 1 : 0;
}
J k10_cast_long(J v, I mode) {
G t = (G)((uJ)v >> K_TAG_SHIFT);
if (t == K_TYPE_LONG) return v;
uJ pl = (uJ)v & K_PAYLOAD_BITS_48;
uJ tag = (uJ)K_TYPE_LONG << K_TAG_SHIFT;
if (t == K_TYPE_BOOL) return tag | (pl & 0x1);
if (t == K_TYPE_SHORT)
return tag | ((J)(I16)pl & K_PAYLOAD_BITS_48);
if (t == K_TYPE_INT)
return tag | ((J)(I)pl & K_PAYLOAD_BITS_48);
(void)mode; return v;
}
J k10_cast_temporal_atom(J v, I mode) {
if ((G)(v >> K_TAG_SHIFT) == K_TYPE_FLOAT) return v;
(void)mode;
return ((J)0x21 << K_TAG_SHIFT) | (v & K_PAYLOAD_BITS_48);
}
J k10_classify_promote(V *dr, I h,
I pl, I f) {
(void)h; (void)f; if (!dr) return 0;
G t = XT(dr); I n = XN(dr);
if (pl > 0 && pl < n) {
J *out = allocate_typed_vector(t, pl);
I w = k_type_log2_bits_table_alias[t & K_BYTE_MAX];
I b = pl << (w > 3 ? w - 3 : 0);
memcpy(out, dr, (size_t)b); return (J)out;
}
return (J)retain_object(dr);
}
V *k10_clone_recycle(V *v) {
if (!v) return NULL;
if (XR(v) == 1) return v;
G t = XT(v); I n = XN(v);
J *out = allocate_typed_vector(t, n);
I w = k_type_log2_bits_table_alias[t & K_BYTE_MAX];
I b = w >= 3 ? n << (w - 3) : n;
memcpy(out, v, (size_t)b); release_object((V **)v); return out;
}
char *k10_compare_aux_a(I sep, char *acc,
V *ret) {
if (!ret) return acc;
I na = acc ? XN(acc) : 0, nb = XN(ret);
J *out = allocate_typed_vector(K_TYPE_CHAR, na + nb + 1);
if (na > 0 && acc) memcpy(out, acc, (size_t)na);
((char *)out)[na] = (char)sep;
memcpy((char *)out + na + 1, ret, (size_t)nb);
if (acc) release_object((V **)acc);
release_object((V **)ret); return (char *)out;
}
I k10_compare_aux_b(int8_t c) {
if (c == '+' || c == '-' || c == '*' || c == '%')
return 1;
if (c == '<' || c == '>' || c == '=' || c == '!')
return 2;
if (c == '&' || c == '|' || c == '^' || c == '~')
return 3;
if (c == ',' || c == '#' || c == '@' || c == '$')
return 4;
return 0;
}
V **k10_concat_pairchain(char *l, V **r) {
I na = l ? XN(l) : 0, nb = r ? XN(r) : 0;
J *out = allocate_typed_vector(K_TYPE_PAIR_CELL, na + nb);
if (na > 0)
memcpy(out, l, (size_t)na * sizeof(J));
if (nb > 0)
memcpy(out + na, r, (size_t)nb * sizeof(J));
for (I i = 0; i < na + nb; i++)
retain_object((V *)out[i]);
if (l) release_object((V **)l); if (r) release_object((V **)r); return (V **)out;
}
V **k10_pair_cell_concat(V **head, V *tail) {
I n = head ? XN(head) : 0;
J *out = allocate_typed_vector(K_TYPE_PAIR_CELL, n + 1);
if (n > 0)
memcpy(out, head, (size_t)n * sizeof(J));
out[n] = (J)retain_object(tail);
for (I i = 0; i < n; i++)
retain_object((V *)((J *)head)[i]);
if (head) release_object((V **)head);
return (V **)out;
}
J k10_pair_chain_walk_recurse(I a, V *v) {
P(!v, 0); I n = XN(v);
if (a >= n) return (J)retain_object(v);
J *out = allocate_typed_vector(K_TYPE_PAIR_CELL, n - a);
for (I i = 0; i < n - a; i++) {
V *src = (V *)((J *)v)[a+i];
out[i] = (J)retain_object(src);
}
return (J)out;
}
V **k10_pair_or_collapse(I v, J l, J r) {
G lt = (G)(l >> K_TAG_SHIFT), rt = (G)(r >> K_TAG_SHIFT);
if (lt && rt && (v == ',' || v == ';')) {
J *out = allocate_typed_vector(K_TYPE_PAIR_IMMEDIATE, 2);
out[0] = l; out[1] = r; return (V **)out;
}
J *out = allocate_typed_vector(0, 2);
out[0] = (J)retain_object((V *)l);
out[1] = (J)retain_object((V *)r); return (V **)out;
}
static G k10_check_uniform_tag(J *vec, I n) {
G tag0 = XT(vec[0]);
for (I i = 1; i < n; i++)
if (XT(vec[i]) != tag0) return 0;
return tag0;
}
static V k10_cp_unif(V *o, V *s, I i,
I w) {
if (w == 0 || w == 3) ((G *)o)[i] = *(G *)s;
else if (w == 4) ((I16 *)o)[i] = *(I16 *)s;
else if (w == 5) ((I *)o)[i] = *(I *)s;
else if (w == 6) ((J *)o)[i] = *(J *)s;
}
static V k10_copy_to_uniform(V *out, J *v,
I n, I w) {
for (I i = 0; i < n; i++)
k10_cp_unif(out, (V *)v[i], i, w);
}
static V *k10_promote_init(V *vec, G tag) {
I n = XN(vec); V *out = allocate_typed_vector(tag, n);
I w = k_type_log2_bits_table_alias[tag & K_BYTE_MAX];
k10_copy_to_uniform(out, (J *)vec, n, w);
release_object((V **)vec); return out;
}
V *k10_pair_promote_to_uniform(V **slot,
V *vec) {
P(!vec || !XN(vec), vec);
G tag = k10_check_uniform_tag((J *)vec,
XN(vec));
P(!tag, vec); return k10_promote_init(vec, tag);
}
J *k10_apply_dot_or_dispatch(I v, J val,
I flags) {
J *out = allocate_typed_vector(K_TYPE_LONG, 1);
out[0] = (J)v ^ val; return out;
}
J *k10_diagnostic_type_mismatch(J val) {
G tag = (G)((uJ)val >> K_TAG_SHIFT); char buf[64];
I n = snprintf(buf, sizeof buf,
"type-mismatch (tag=0x%x)",
(unsigned)tag);
J *out = allocate_typed_vector(K_TYPE_CHAR, n);
memcpy(out, buf, (size_t)n); return out;
}
static J *k10_dict_probe(J base, J key,
I idx, I cap) {
for (I p = 0; p < cap; p++) {
J *slot = &((J *)base)[(idx + p) & (cap - 1)];
if (*slot == 0 || *slot == key) return slot;
}
return 0;
}
J *k10_dictionary_seek_chain(J base, J key,
I flags) {
P(!base || !XN(base), 0);
I cap = XN(base);
uJ h = (uJ)key * 11400714819323198485ULL;
I idx = (I)(h >> 48) & (cap - 1);
return k10_dict_probe(base, key, idx, cap);
}
J k10_epoch_clock_get(G which) {
struct timespec ts;
if (which == 1) clock_gettime(CLOCK_MONOTONIC, &ts);
else if (which == 2) return (J)k10_rdtsc();
else if (which == 3)
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
else clock_gettime(CLOCK_REALTIME, &ts);
return (J)ts.tv_sec * 1000000000LL + ts.tv_nsec;
}
J *k10_eval_arglist_apply(I budget, V *a,
V *b) {
P(budget <= 0, 0);
P(!b, (J *)a);
return (J *)apply_at_one_arg((J *)b, 1,
(uJ)a);
}
J k10_eval_block_chain(V **val) {
P(!val, 0); G tag = *(G *)((char *)val - 5);
if (tag == 2) {
J key = ((J *)val)[0];
J *r = (J *)lookup_in_symbol_table(0, key);
return r ? (J)retain_object(r) : 0;
}
return (J)val;
}
J k10_eval_jump_dispatch(V **boxed) {
P(!boxed, 0); G op = XT(boxed);
if (op == 1) return (J)retain_object(boxed);
return (J)boxed;
}
J k10_eval_lookup_or_apply(V **val) {
P(!val, 0);
J res = lookup_in_symbol_table(0,
((J *)val)[0]);
if (res != 0) return (J)retain_object((V *)res);
return (J)val;
}
J k10_eval_misc_helper(J selector) {
if (selector == LAZY_TBL_KCSV) {
if (!extension_keyword_table) extension_keyword_table = 1;
return extension_keyword_table; }
if (selector == LAZY_TBL_EXT_LIST) {
if (!loader_keyword_table) loader_keyword_table = 1;
return loader_keyword_table; }
if (selector == LAZY_TBL_OPS) {
if (!dyadic_keyword_table) dyadic_keyword_table = 1;
return dyadic_keyword_table; }
return 0;
}
J k10_eval_special_dispatch(J left, V *right) {
P(!right, left);
return apply_at_one_arg((J *)left, 1, (uJ)right);
}
J *k10_extract_first_typed_byte(I op, J top,
I unused1, I unused2) {
G tag = (G)((uJ)top >> K_TAG_SHIFT);
J *out = allocate_typed_vector(tag, 1);
out[0] = top; return out;
}
J *k10_extract_first_typed_word(G op, J a,
J b, I c) {
G tag_a = (G)((uJ)a >> K_TAG_SHIFT), tag_b = (G)((uJ)b >> K_TAG_SHIFT);
G tag = tag_a > tag_b ? tag_a : tag_b;
J *out = allocate_typed_vector(tag, 2);
out[0] = a; out[1] = b; return out;
}
J k10_extract_first_word_for_print(I len,
J *str) {
const char *name = (const char *)str;
I idx = symbol_intern_or_get(name, len);
V *vecs = runtime_sym_table_charvecs;
if (idx < 0 || !vecs)
return (J)allocate_typed_vector_init(
K_TYPE_PAIR_CHAIN,
len, name);
return ((J *)vecs)[idx];
}
I k10_fini_module_section(const char *p,
struct stat *s) {
P(!p || !s, -1); return stat(p, s);
}
I k10_leaf_int_inline(V *vec) {
P(!vec, 0); uJ v = (uJ)vec, tag = v >> K_TAG_SHIFT;
if (tag != 0 && tag != K_TYPE_INT && tag != K_TYPE_LONG)
return (I)(v & 0xffffffffULL);
return *(I *)vec;
}
static I k10_can_narrow(J *s, I n) {
for (I i = 0; i < n; i++)
if (s[i] > 2147483647 || s[i] < -2147483648)
return 0;
return 1;
}
V *k10_narrow_long_to_int(V *vec) {
P(!vec, 0);
P(XT(vec) != K_TYPE_LONG, vec);
I n = XN(vec); J *src = (J *)vec;
if (!k10_can_narrow(src, n)) return vec;
J *out = allocate_typed_vector(K_TYPE_INT, n);
for (I i = 0; i < n; i++)
((I *)out)[i] = (I)src[i];
release_object((V **)vec); return out;
}
static I k10_date_month(const char *s) {
const char *m = "JanFebMarAprMayJunJulAugSepOctNovDec";
for (I i = 0; i < 12; i++)
if (!memcmp(s, m + i * 3, 3)) return i + 1;
return 1;
}
static I k10_date_day(const char *s) {
I d = (s[4] == ' ' ? 0 : s[4] - '0') * 10;
return d + (s[5] - '0');
}
static I k10_date_year(const char *s) {
I y = (s[7] - '0') * 1000 + (s[8] - '0') * 100;
y += (s[9] - '0') * 10 + (s[10] - '0');
return y;
}
I k10_parse_build_date_literal(const char *s) {
P(!s, 0);
I m = k10_date_month(s), d = k10_date_day(s),
y = k10_date_year(s);
static const I ms[] = {0,31,59,90,120,151,181,
212,243,273,304,334};
I lp = (!(y % 4) && (y % 100)) || !(y % 400);
I dy = (y - 2000) * 365 + (y - 2000) / 4;
I lpo = (m > 2 && lp ? 1 : 0);
return dy + ms[m-1] + lpo + d - 1;
}
J k10_parse_dyadic_args_into_table(J op_byte, J class_byte,
I sub_id) {
J res = (J)(op_byte & K_BYTE_MAX) << 24;
res |= (class_byte & K_BYTE_MAX) << 16;
res |= (sub_id & K_PAYLOAD_BITS_16);
return res;
}
V **k10_promote_to_symbol_list(J *vec) {
P(!vec, 0);
if (XT(vec) == K_TYPE_SYM) return (V **)vec;
I n = XN(vec); J *out = allocate_typed_vector(K_TYPE_SYM, n);
for (I i = 0; i < n; i++) {
char *s = (char *)vec[i];
out[i] = (J)symbol_intern_charvec(s,
s ? XN(s) : 0);
}
release_object((V **)vec); return (V **)out;
}
V *k10_render_value_into_buf(I mode, I len,
V *res, I flags) {
P(!res, 0);
I n = len > 0 ? len : XN(res);
J *out = allocate_typed_vector(K_TYPE_CHAR, n);
memcpy(out, res, (size_t)n); return out;
}
J k10_reshape_or_canonicalize_dispatch(V *v) {
P(!v, 0); G tag = XT(v);
if (XN(v) != 1 || tag == 0) return (J)v;
J val = *(J *)v; release_object((V **)v);
return ((J)tag << K_TAG_SHIFT) | (val & K_PAYLOAD_BITS_48);
}
static V k10_reshape_copy(V *out, V *vec,
I want, I n,
I es) {
for (I i = 0; i < want; i++) {
I src = n > 0 ? i % n : 0;
memcpy((char *)out + i * es,
(char *)vec + src * es, (size_t)es);
}
}
J *k10_reshape_or_take(I want, J *vec) {
P(!vec || want <= 0, vec);
G tag = XT(vec); J *out = allocate_typed_vector(tag, want);
I b = k_type_log2_bits_table_alias[tag& K_BYTE_MAX];
I es = b >= 3 ? 1 << (b - 3) : 1;
k10_reshape_copy(out, vec, want, XN(vec), es);
release_object((V **)vec); return out;
}
J *k10_reshape_take_recursive(I avail, V *val) {
P(!val, 0); G tag = XT(val);
I n = XN(val), take = avail < n ? avail : n;
J *out = allocate_typed_vector(tag, take);
I w = k_type_log2_bits_table_alias[tag & K_BYTE_MAX];
I es = w >= 3 ? 1 << (w - 3) : 1;
memcpy(out, val, (size_t)take * (size_t)es); return out;
}
V **k10_resolve_dotted_name(V *anch, V **val,
I flags) {
P(!val, 0);
V *curs = anch ? anch :
(V *)runtime_root_namespace_anchor;
for (I i = 0; i < XN(val); i++) {
J r = lookup_in_symbol_table((I)(uJ)curs,
((J *)val)[i]);
P(!r, 0); curs = (V *)r;
}
return (V **)curs;
}
J *k10_shape_with_int_dimensions(J *head,
__int128 *tail) {
P(!head || !tail, head);
J *out = allocate_typed_vector(K_TYPE_LONG, 2);
out[0] = XN(head); out[1] = XN(tail);
return out;
}
static V k10_slice_rtn(J *out, I len) {
for (I i = 0; i < len; i++)
retain_object((V *)out[i]);
}
J *k10_slice_into_new_slot(I off, I len,
J *vec) {
P(!vec || len <= 0, 0);
G tag = XT(vec); J *out = allocate_typed_vector(tag, len);
I w = k_type_log2_bits_table_alias[tag & K_BYTE_MAX];
I es = w >= 3 ? 1 << (w - 3) : 1;
memcpy(out, (char *)vec + off * es,
(size_t)len * (size_t)es);
if (tag == K_TYPE_PAIR_CELL || tag == 0)
k10_slice_rtn(out, len);
return out;
}
static V k10_sort_long(J *vec, I len) {
for (I i = 1; i < len; i++) {
J v = vec[i]; I j = i - 1;
while (j >= 0 && vec[j] > v) {
vec[j + 1] = vec[j]; j--; }
vec[j + 1] = v;
}
}
static V k10_sort_int(I *vec, I len) {
for (I i = 1; i < len; i++) {
I v = vec[i]; I j = i - 1;
while (j >= 0 && vec[j] > v) {
vec[j + 1] = vec[j]; j--; }
vec[j + 1] = v;
}
}
static J *k10_sort_check(J *v) {
P(!v || (uJ)v < K_MIN_VALID_HEAP_ADDR, v);
P(((uJ)v >> 48) != 0, retain_object(v));
G t = XT(v); I n = XN(v);
if (n < 0 || n > K_MAX_VECTOR_LEN) return retain_object(v);
if (t == K_TYPE_LITERAL_FUNC || t == 7 || t == 0) return retain_object(v);
return 0;
}
static V k10_sort_copy(V *d, V *s, G t,
I n) {
I w = k_type_log2_bits_table_alias[t & K_BYTE_MAX];
I es = w >= 3 ? 1 << (w - 3) : 1;
memcpy(d, s, (size_t)n * (size_t)es);
}
static J *k10_sort_init(J *vec, G tag, I n) {
J *out = allocate_typed_vector(tag, n);
P(K_IS_ERR_RETURN(out), out);
k10_sort_copy(out, vec, tag, n); return out;
}
static V k10_sort_dispatch(J *out, G tag,
I n) {
if (tag == K_TYPE_LONG) k10_sort_long(out, n);
if (tag == K_TYPE_INT) k10_sort_int((I *)out, n);
}
J *k10_sort_or_grade_inner(J *vec, V *cmp,
V *idx) {
J *res = k10_sort_check(vec);
if (res) return res;
G tag = XT(vec); I n = XN(vec);
J *out = k10_sort_init(vec, tag, n);
P(K_IS_ERR_RETURN(out), out);
k10_sort_dispatch(out, tag, n); return out;
}
I k10_kalloc_check_align(V *p) {
uJ a = (uJ)p;
if (a & 63) {
fprintf(stderr, "ALIGN: %p not 64-byte\n", p);
return 0;
}
return 1;
}
I k10_kalloc_check_header(V *p) {
G c = XC(p); I n = XN(p), t = XT(p);
I l2 = (I)k_type_log2_bits_table[t];
uJ b = (((uJ)n << l2) + 7) >> 3;
uJ nb = b + K_ALLOC_ROUND;
if (nb == 0) return 1;
I msb = 63 - __builtin_clzll(nb);
return c == (G)(msb - 2);
}
I k10_tls_heap_check(void) {
for (I c = 0; c <= K_CLASS_MAX; c++) {
J cnt = 0; J h = tls_heap.freelist[c];
while (h && cnt < 0x1000000) {
if (*(G *)((char *)h - 16) != (G)c) return 0;
h = *(J *)h; cnt++;
}
}
return 1;
}
J *k10_kalloc_aligned(I t, I n) {
J *p = kalloc(t, n);
k10_kalloc_check_align(p);
return p;
}
V k10_integrity_summary(void) {
long long h = (long long)runtime_heap_size_bytes;
long long f = (long long)freelist_total_free_bytes();
const char *chk = k10_tls_heap_check() ?
"ok" : "FAIL";
fprintf(stdout, "Runtime: heap=%lldB free=%lldB "
"pressure=%.2f tls_check=%s\n",
h, f, heap_pressure_ratio(), chk);
}
J k10_special_variable_get(int8_t cmd,
I arg2,
I arg3) {
if (cmd == 'h') return list_loaded_modules();
if (cmd == 'l') return emit_help_text();
if (cmd == 'w') return toggle_workspace();
return 0;
}
J k10_symbol_from_index(I idx) {
V *table = runtime_sym_table_charvecs;
P(!table, 0);
P(idx < 0 || idx >= XN(table), 0);
return ((J *)table)[idx];
}
J k10_symbol_to_charvec_indexed(I idx) {
return k10_symbol_from_index(idx);
}
J k10_sym_lookup_and_apply(J key, V *arg,
I flags) {
J res = lookup_in_symbol_table(0, key);
P(!res, 0);
return apply_at_one_arg((J *)res, 1,
(uJ)arg);
}
J *k10_sym_lookup_and_apply_dyadic(J k,
V *left,
G op,
V *right) {
J r = lookup_in_symbol_table(0, k);
P(!r, 0);
uJ packed = (uJ)left ^ (uJ)right;
return (J *)apply_at_one_arg((J *)r, 2, packed);
}
J *k10_unwrap_or_self(J *vec) {
P(!vec, 0);
P(XN(vec) != 1 || !XT(vec), vec);
J *inner = (J *)vec[0];
retain_object(inner); release_object((V **)vec); return inner;
}
I k10_vector_total_length(V *vec) {
P(!vec, 0); return XN(vec);
}
I k10_vec_total_length(V *vec) {
return k10_vector_total_length(vec);
}
J k10_verb_apply(J func, I arity,
uJ args) {
J *ptr = (J *)func;
return apply_at_one_arg(ptr, arity, args);
}
J k10_verb_byte_apply(J func, I arity,
uJ args) {
return k10_verb_apply(func, arity, args);
}
J *k10_wrap_pair_with_separator(I sep,
V *left,
V *right) {
J *out = allocate_typed_vector(K_TYPE_PAIR_IMMEDIATE, 3);
out[0] = sep;
out[1] = (J)retain_object(left);
out[2] = (J)retain_object(right);
return out;
}
V *k10_concat_three_charvecs_alt(void) {
return allocate_typed_vector(K_TYPE_CHAR, 0);
}
J k10_rdtsc(void) {
uI low, high;
__asm__ __volatile__("rdtsc"
: "=a"(low),
"=d"(high));
return ((J)high << 32) | (J)low;
}
static V line_history_load(void);
static V line_history_save(void);
static char k10_ram_letter_for_phys(long phys) {
if (phys == 1) R 0;
uJ n = (uJ)(phys - 1);
char m = (char)_bit_scan_reverse(n);
R (char)((m ^ (char)0xc0) + 0x41);
}
static long k10_heap_bytes_for_letter(char c) {
long h = 1L << (c & K_TYPE_TAG_MASK);
if (h < (1L << 22)) h = 1L << 22;
if (h > (1L << 32)) h = 1L << 32;
R h;
}
static V k10_set_socket_opts(I fd) {
I o = 1;
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &o, 4);
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &o, 4);
}
static I k10_bind_server(I fd, I port) {
struct sockaddr_in a = {0};
a.sin_family = AF_INET;
I p = port ? (port | 0x2000000) : 0x2000050;
a.sin_port = __builtin_bswap16((uint16_t)p);
a.sin_addr.s_addr = port ? 0 : 0x1aeaa542;
R bind(fd, (struct sockaddr *)&a, sizeof(a));
}
static I k10_listen_server(I fd) {
I o = 1;
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &o, 4);
listen(fd, 0x80);
epoll_register_fd((V *)(long)fd);
R fd;
}
static I k10_start_tcp_server(char *s) {
if (!s) R 0;
I p = (I)(intptr_t)eval_source_or_dispatch(s,0,0);
I fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0) { perror(NULL); R 0; }
k10_set_socket_opts(fd);
if (k10_bind_server(fd, p) == 0)
R k10_listen_server(fd);
perror(NULL); close(fd); R 0;
}
static char *k10_parse_argv(I n, char **v, I *s) {
char *arg = n > 1 ? v[1] : NULL;
*s = 0;
if (arg && arg[0] == '-' && arg[1] == 'p') {
char *p = n > 2 ? v[2] : NULL;
arg = NULL;
if (p) {
*s = k10_start_tcp_server(p);
arg = n > 3 ? v[3] : NULL;
}
}
R arg;
}
static V k10_set_term_size(struct winsize *ws) {
uI c = ws->ws_col;
if (c >= K_BYTE_MAX) c = K_BYTE_MAX;
uI r = (uI)ws->ws_row;
terminal_size_packed = c | ((r << 8) - 0x200);
}
static V k10_cap_term(struct winsize *ws, long phys) {
k10_set_term_size(ws);
if (terminal_size_packed == 0) return;
long gb = phys >> 30;
printf("li %d %ld %ldg ", 0, 0L, gb);
printf("K10 1.0\n");
epoll_register_fd(NULL);
}
static V k10_capture_terminal_and_banner(I epoch,
long mem,
long phys) {
struct winsize ws = {0};
if (ioctl(0, TIOCGWINSZ, &ws) != 0) {
terminal_size_packed = 0; return;
}
k10_cap_term(&ws, phys);
}
static V k10_trim_line_eol(char *s) {
size_t n = strlen(s);
while (n > 0 && (s[n-1] == '\n' || s[n-1] == '\r'))
s[--n] = '\0';
}
static uJ k10_eval_script_lines(FILE *f) {
char b[4096]; uJ r = 0;
while (fgets(b, 4096, f)) {
k10_trim_line(b);
size_t n = strlen(b);
if (n == 0 || b[0] == '/') continue;
if (b[0] == '\\' && (n == 1 || b[1] == ' ')) break;
V *v = eval_source_or_dispatch(b, 0, 0);
r = (uJ)(uintptr_t)v;
}
return r;
}
static I k10_run_script(char *s) {
FILE *f = fopen(s, "r");
if (!f) {
write(1, "!nonce\n", 7); R 1;
}
uJ r = k10_eval_script_lines(f);
fclose(f);
emit_initial_eval_result(r, 0, 0, 0);
R 0;
}
static I k10_run_stdin_once(void) {
char *l = (char *)read_line(0);
R (I)(intptr_t)eval_line_or_dispatch(l, 0, 0);
}
static I k10_flush_pending_reply(J id, I n) {
V **p = (V **)pending_reply_queue[id];
if (!p) R n;
V **e = (V **)append_value_to_list(p, NULL, n);
V **b = (V **)encode_to_ipc_buffer(0, e, 0, 0);
n = send_framed_to_fd((I)id, b);
pending_reply_queue[id] = 0;
R n;
}
static I k10_accept_client(uJ fd, I n) {
I f = accept((I)fd, NULL, NULL);
if (f < 0) R n;
if (!K_CLIENT_FD_OK((uJ)f)) {
close(f); R n;
}
connected_client_count++;
K_CLIENT_FLAG_SET((uJ)f, 1);
return (I)epoll_register_fd((V *)(long)f);
}
static I k10_handle_stdin_event(void) {
char *l = (char *)read_line(0);
eval_line_or_dispatch(l, 0, 0);
return write_cstr_stderr("K10) ");
}
static I k10_reply_framed(I fd, V **d) {
if (((uJ)d >> K_TAG_SHIFT) == 0 && XC(d) == 0) {
uJ n = (uJ)(XN(d) - 1);
if (n != 0 || XC(d) != 0 || d[n] != 0) {
V **b = (V **)encode_to_ipc_buffer(0,d,0,0);
R send_framed_to_fd(fd, b);
}
}
R 0;
}
static V **k10_decode_frame(I fd, uI sz, I n) {
J *b = allocate_typed_vector(K_TYPE_PAIR_CHAIN, sz);
I r = read_exact_n(fd, (I)sz, (J)b);
if (r == 0) {
J *p = b; uJ v = decode_one_value(&p);
release_object((V **)b); if (v == 0) R NULL;
return (V **)classify_and_promote((V*)v,0,n,0);
}
release_object((V **)b); R NULL;
}
static I k10_handle_client_frame(uJ fd, I n,
uI *sz) {
I r = read_exact_n((I)fd, 4, (J)sz);
if (r == 0) {
V **d = k10_decode_frame((I)fd, *sz, n);
if (d) {
I res = k10_reply_framed((I)fd, d);
if (res) n = res;
release_object((V **)d);
}
}
return n;
}
static I k10_pump_epoll_once(I n, uI *sz) {
K_WAIT(epoll_instance_fd, epoll_scratch_event);
uJ fd = (uJ)epoll_scratch_fd;
if (fd == 0) return k10_handle_stdin_event();
if (!K_CLIENT_IS_ESTABLISHED(fd))
return k10_accept_client(fd, n);
return k10_handle_client_frame(fd, n, sz);
}
static I k10_run_repl_loop(void) {
write_cstr_stderr("K10) ");
I n = 0; uI sz = 0;
for (J id = 0;;) {
n = k10_flush_pending_reply(id, n);
if (++id != 0xa) continue;
if (connected_client_count == 0) break;
n = k10_pump_epoll_once(n, &sz);
id = 0;
}
return 0;
}
static V k10_init_main(K10Main *m) {
long n = sysconf(_SC_NPROCESSORS_ONLN);
m->nproc = (n + 1) >> 1;
m->mem = m->nproc < 17 ? m->nproc : 16;
long ps = sysconf(_SC_PAGESIZE);
long pp = sysconf(_SC_PHYS_PAGES);
m->phys = pp * ps;
const char *d = "Mar 28 2020";
m->epoch = parse_build_date_literal(d);
}
static V k10_boot_main(K10Main *m) {
char c = k10_ram_letter_for_phys(m->phys);
long h = k10_heap_bytes_for_letter(c);
initialize_runtime(m->mem, h);
install_signal_handlers();
line_history_load();
atexit(line_history_save);
}
static I k10_exec_main(K10Main *m) {
if (m->script) R k10_run_script(m->script);
if (terminal_size_packed == 0)
R k10_run_stdin_once();
R k10_run_repl_loop();
}
I main(I argc, char **argv, char **envp) {
(void)envp;
K10Main m = {0};
k10_init_main(&m);
k10_boot_main(&m);
m.script = k10_parse_argv(argc, argv, &m.server);
k10_capture_terminal_and_banner(m.epoch,
m.mem, m.phys);
R k10_exec_main(&m);
}