Files
rose-ash/shared/sx/ref/primitives.sx
giles 3ca89ef765 Self-hosted z3.sx translator, prove.sx prover, parser unicode, auto reader macros
- z3.sx: SX-to-SMT-LIB translator written in SX (359 lines), replaces Python translation logic
- prove.sx: SMT-LIB satisfiability checker in SX — proves all 91 primitives sat by construction
- Parser: support unicode characters (em-dash, accented letters) in symbols
- Auto-resolve reader macros: #name finds name-translate in component env, no Python registration
- Platform primitives: type-of, symbol-name, keyword-name, sx-parse registered in primitives.py
- Cond heuristic: predicates ending in ? recognized as Clojure-style tests
- Library loading: z3.sx loaded at startup with reload callbacks for hot-reload ordering
- reader_z3.py: rewritten as thin shell delegating to z3.sx
- Split monolithic .sx files: essays (22), plans (13), reactive-islands (6) into separate files

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 22:47:53 +00:00

583 lines
15 KiB
Plaintext

;; ==========================================================================
;; primitives.sx — Specification of all SX built-in pure functions
;;
;; Each entry declares: name, parameter signature, and semantics.
;; Bootstrap compilers implement these natively per target.
;;
;; This file is a SPECIFICATION, not executable code. The define-primitive
;; form is a declarative macro that bootstrap compilers consume to generate
;; native primitive registrations.
;;
;; Format:
;; (define-primitive "name"
;; :params (param1 param2 &rest rest)
;; :returns "type"
;; :doc "description"
;; :body (reference-implementation ...))
;;
;; The :body is optional — when provided, it gives a reference
;; implementation in SX that bootstrap compilers MAY use for testing
;; or as a fallback. Most targets will implement natively for performance.
;;
;; Modules: (define-module :name) scopes subsequent define-primitive
;; entries until the next define-module. Bootstrappers use this to
;; selectively include primitive groups.
;; ==========================================================================
;; --------------------------------------------------------------------------
;; Core — Arithmetic
;; --------------------------------------------------------------------------
(define-module :core.arithmetic)
(define-primitive "+"
:params (&rest args)
:returns "number"
:doc "Sum all arguments."
:body (reduce (fn (a b) (native-add a b)) 0 args))
(define-primitive "-"
:params (a &rest b)
:returns "number"
:doc "Subtract. Unary: negate. Binary: a - b."
:body (if (empty? b) (native-neg a) (native-sub a (first b))))
(define-primitive "*"
:params (&rest args)
:returns "number"
:doc "Multiply all arguments."
:body (reduce (fn (a b) (native-mul a b)) 1 args))
(define-primitive "/"
:params (a b)
:returns "number"
:doc "Divide a by b."
:body (native-div a b))
(define-primitive "mod"
:params (a b)
:returns "number"
:doc "Modulo a % b."
:body (native-mod a b))
(define-primitive "sqrt"
:params (x)
:returns "number"
:doc "Square root.")
(define-primitive "pow"
:params (x n)
:returns "number"
:doc "x raised to power n.")
(define-primitive "abs"
:params (x)
:returns "number"
:doc "Absolute value.")
(define-primitive "floor"
:params (x)
:returns "number"
:doc "Floor to integer.")
(define-primitive "ceil"
:params (x)
:returns "number"
:doc "Ceiling to integer.")
(define-primitive "round"
:params (x &rest ndigits)
:returns "number"
:doc "Round to ndigits decimal places (default 0).")
(define-primitive "min"
:params (&rest args)
:returns "number"
:doc "Minimum. Single list arg or variadic.")
(define-primitive "max"
:params (&rest args)
:returns "number"
:doc "Maximum. Single list arg or variadic.")
(define-primitive "clamp"
:params (x lo hi)
:returns "number"
:doc "Clamp x to range [lo, hi]."
:body (max lo (min hi x)))
(define-primitive "inc"
:params (n)
:returns "number"
:doc "Increment by 1."
:body (+ n 1))
(define-primitive "dec"
:params (n)
:returns "number"
:doc "Decrement by 1."
:body (- n 1))
;; --------------------------------------------------------------------------
;; Core — Comparison
;; --------------------------------------------------------------------------
(define-module :core.comparison)
(define-primitive "="
:params (a b)
:returns "boolean"
:doc "Deep structural equality. Alias for equal?.")
(define-primitive "!="
:params (a b)
:returns "boolean"
:doc "Inequality."
:body (not (= a b)))
(define-primitive "eq?"
:params (a b)
:returns "boolean"
:doc "Identity equality. True only if a and b are the exact same object.
For immutable atoms (numbers, strings, booleans, nil) this may or
may not match — use eqv? for reliable atom comparison.")
(define-primitive "eqv?"
:params (a b)
:returns "boolean"
:doc "Equivalent value for atoms, identity for compound objects.
Returns true for identical objects (eq?), and also for numbers,
strings, booleans, and nil with the same value. For lists, dicts,
lambdas, and components, only true if same identity.")
(define-primitive "equal?"
:params (a b)
:returns "boolean"
:doc "Deep structural equality. Recursively compares lists and dicts.
Same semantics as = but explicit Scheme name.")
(define-primitive "<"
:params (a b)
:returns "boolean"
:doc "Less than.")
(define-primitive ">"
:params (a b)
:returns "boolean"
:doc "Greater than.")
(define-primitive "<="
:params (a b)
:returns "boolean"
:doc "Less than or equal.")
(define-primitive ">="
:params (a b)
:returns "boolean"
:doc "Greater than or equal.")
;; --------------------------------------------------------------------------
;; Core — Predicates
;; --------------------------------------------------------------------------
(define-module :core.predicates)
(define-primitive "odd?"
:params (n)
:returns "boolean"
:doc "True if n is odd."
:body (= (mod n 2) 1))
(define-primitive "even?"
:params (n)
:returns "boolean"
:doc "True if n is even."
:body (= (mod n 2) 0))
(define-primitive "zero?"
:params (n)
:returns "boolean"
:doc "True if n is zero."
:body (= n 0))
(define-primitive "nil?"
:params (x)
:returns "boolean"
:doc "True if x is nil/null/None.")
(define-primitive "boolean?"
:params (x)
:returns "boolean"
:doc "True if x is a boolean (true or false). Must be checked before
number? on platforms where booleans are numeric subtypes.")
(define-primitive "number?"
:params (x)
:returns "boolean"
:doc "True if x is a number (int or float). Excludes booleans.")
(define-primitive "string?"
:params (x)
:returns "boolean"
:doc "True if x is a string.")
(define-primitive "list?"
:params (x)
:returns "boolean"
:doc "True if x is a list/array.")
(define-primitive "dict?"
:params (x)
:returns "boolean"
:doc "True if x is a dict/map.")
(define-primitive "continuation?"
:params (x)
:returns "boolean"
:doc "True if x is a captured continuation.")
(define-primitive "empty?"
:params (coll)
:returns "boolean"
:doc "True if coll is nil or has length 0.")
(define-primitive "contains?"
:params (coll key)
:returns "boolean"
:doc "True if coll contains key. Strings: substring check. Dicts: key check. Lists: membership.")
;; --------------------------------------------------------------------------
;; Core — Logic
;; --------------------------------------------------------------------------
(define-module :core.logic)
(define-primitive "not"
:params (x)
:returns "boolean"
:doc "Logical negation. Note: and/or are special forms (short-circuit).")
;; --------------------------------------------------------------------------
;; Core — Strings
;; --------------------------------------------------------------------------
(define-module :core.strings)
(define-primitive "str"
:params (&rest args)
:returns "string"
:doc "Concatenate all args as strings. nil → empty string, bool → true/false.")
(define-primitive "concat"
:params (&rest colls)
:returns "list"
:doc "Concatenate multiple lists into one. Skips nil values.")
(define-primitive "upper"
:params (s)
:returns "string"
:doc "Uppercase string.")
(define-primitive "upcase"
:params (s)
:returns "string"
:doc "Alias for upper. Uppercase string.")
(define-primitive "lower"
:params (s)
:returns "string"
:doc "Lowercase string.")
(define-primitive "downcase"
:params (s)
:returns "string"
:doc "Alias for lower. Lowercase string.")
(define-primitive "string-length"
:params (s)
:returns "number"
:doc "Length of string in characters.")
(define-primitive "substring"
:params (s start end)
:returns "string"
:doc "Extract substring from start (inclusive) to end (exclusive).")
(define-primitive "string-contains?"
:params (s needle)
:returns "boolean"
:doc "True if string s contains substring needle.")
(define-primitive "trim"
:params (s)
:returns "string"
:doc "Strip leading/trailing whitespace.")
(define-primitive "split"
:params (s &rest sep)
:returns "list"
:doc "Split string by separator (default space).")
(define-primitive "join"
:params (sep coll)
:returns "string"
:doc "Join collection items with separator string.")
(define-primitive "replace"
:params (s old new)
:returns "string"
:doc "Replace all occurrences of old with new in s.")
(define-primitive "slice"
:params (coll start &rest end)
:returns "any"
:doc "Slice a string or list from start to end (exclusive). End is optional.")
(define-primitive "index-of"
:params (s needle &rest from)
:returns "number"
:doc "Index of first occurrence of needle in s, or -1 if not found. Optional start index.")
(define-primitive "starts-with?"
:params (s prefix)
:returns "boolean"
:doc "True if string s starts with prefix.")
(define-primitive "ends-with?"
:params (s suffix)
:returns "boolean"
:doc "True if string s ends with suffix.")
;; --------------------------------------------------------------------------
;; Core — Collections
;; --------------------------------------------------------------------------
(define-module :core.collections)
(define-primitive "list"
:params (&rest args)
:returns "list"
:doc "Create a list from arguments.")
(define-primitive "dict"
:params (&rest pairs)
:returns "dict"
:doc "Create a dict from key/value pairs: (dict :a 1 :b 2).")
(define-primitive "range"
:params (start end &rest step)
:returns "list"
:doc "Integer range [start, end) with optional step.")
(define-primitive "get"
:params (coll key &rest default)
:returns "any"
:doc "Get value from dict by key, or list by index. Optional default.")
(define-primitive "len"
:params (coll)
:returns "number"
:doc "Length of string, list, or dict.")
(define-primitive "first"
:params (coll)
:returns "any"
:doc "First element, or nil if empty.")
(define-primitive "last"
:params (coll)
:returns "any"
:doc "Last element, or nil if empty.")
(define-primitive "rest"
:params (coll)
:returns "list"
:doc "All elements except the first.")
(define-primitive "nth"
:params (coll n)
:returns "any"
:doc "Element at index n, or nil if out of bounds.")
(define-primitive "cons"
:params (x coll)
:returns "list"
:doc "Prepend x to coll.")
(define-primitive "append"
:params (coll x)
:returns "list"
:doc "If x is a list, concatenate. Otherwise append x as single element.")
(define-primitive "append!"
:params (coll x)
:returns "list"
:doc "Mutate coll by appending x in-place. Returns coll.")
(define-primitive "reverse"
:params (coll)
:returns "list"
:doc "Return coll in reverse order.")
(define-primitive "flatten"
:params (coll)
:returns "list"
:doc "Flatten one level of nesting. Nested lists become top-level elements.")
(define-primitive "chunk-every"
:params (coll n)
:returns "list"
:doc "Split coll into sub-lists of size n.")
(define-primitive "zip-pairs"
:params (coll)
:returns "list"
:doc "Consecutive pairs: (1 2 3 4) → ((1 2) (2 3) (3 4)).")
;; --------------------------------------------------------------------------
;; Core — Dict operations
;; --------------------------------------------------------------------------
(define-module :core.dict)
(define-primitive "keys"
:params (d)
:returns "list"
:doc "List of dict keys.")
(define-primitive "vals"
:params (d)
:returns "list"
:doc "List of dict values.")
(define-primitive "merge"
:params (&rest dicts)
:returns "dict"
:doc "Merge dicts left to right. Later keys win. Skips nil.")
(define-primitive "has-key?"
:params (d key)
:returns "boolean"
:doc "True if dict d contains key.")
(define-primitive "assoc"
:params (d &rest pairs)
:returns "dict"
:doc "Return new dict with key/value pairs added/overwritten.")
(define-primitive "dissoc"
:params (d &rest keys)
:returns "dict"
:doc "Return new dict with keys removed.")
(define-primitive "dict-set!"
:params (d key val)
:returns "any"
:doc "Mutate dict d by setting key to val in-place. Returns val.")
(define-primitive "into"
:params (target coll)
:returns "any"
:doc "Pour coll into target. List target: convert to list. Dict target: convert pairs to dict.")
;; --------------------------------------------------------------------------
;; Stdlib — Format
;; --------------------------------------------------------------------------
(define-module :stdlib.format)
(define-primitive "format-date"
:params (date-str fmt)
:returns "string"
:doc "Parse ISO date string and format with strftime-style format.")
(define-primitive "format-decimal"
:params (val &rest places)
:returns "string"
:doc "Format number with fixed decimal places (default 2).")
(define-primitive "parse-int"
:params (val &rest default)
:returns "number"
:doc "Parse string to integer with optional default on failure.")
(define-primitive "parse-datetime"
:params (s)
:returns "string"
:doc "Parse datetime string — identity passthrough (returns string or nil).")
;; --------------------------------------------------------------------------
;; Stdlib — Text
;; --------------------------------------------------------------------------
(define-module :stdlib.text)
(define-primitive "pluralize"
:params (count &rest forms)
:returns "string"
:doc "Pluralize: (pluralize 1) → \"\", (pluralize 2) → \"s\". Or (pluralize n \"item\" \"items\").")
(define-primitive "escape"
:params (s)
:returns "string"
:doc "HTML-escape a string (&, <, >, \", ').")
(define-primitive "strip-tags"
:params (s)
:returns "string"
:doc "Remove HTML tags from string.")
;; --------------------------------------------------------------------------
;; Stdlib — Style
;; --------------------------------------------------------------------------
;; --------------------------------------------------------------------------
;; Stdlib — Debug
;; --------------------------------------------------------------------------
(define-module :stdlib.debug)
(define-primitive "assert"
:params (condition &rest message)
:returns "boolean"
:doc "Assert condition is truthy; raise error with message if not.")
;; --------------------------------------------------------------------------
;; Type introspection — platform primitives
;; --------------------------------------------------------------------------
(define-module :stdlib.types)
(define-primitive "type-of"
:params (x)
:returns "string"
:doc "Return type name: number, string, boolean, nil, symbol, keyword, list, dict, lambda, component, island, macro.")
(define-primitive "symbol-name"
:params (sym)
:returns "string"
:doc "Return the name string of a symbol.")
(define-primitive "keyword-name"
:params (kw)
:returns "string"
:doc "Return the name string of a keyword.")
(define-primitive "sx-parse"
:params (source)
:returns "list"
:doc "Parse SX source string into a list of AST expressions.")