;; Deterministic serialization for content addressing (define canonical-serialize :effects () (fn (val) (case (type-of val) "nil" "nil" "boolean" (if val "true" "false") "number" (canonical-number val) "string" (str "\"" (escape-string val) "\"") "symbol" (symbol-name val) "keyword" (str ":" (keyword-name val)) "list" (str "(" (join " " (map canonical-serialize val)) ")") "dict" (canonical-dict val) :else (str val)))) ;; Normalize number representation (no trailing zeros) (define canonical-number :effects () (fn (n) (let ((s (str n))) (if (ends-with? s ".0") (slice s 0 (- (len s) 2)) (if (contains-char? s ".") (let ((trimmed (trim-right s "0"))) (if (ends-with? trimmed ".") (str trimmed "0") trimmed)) s))))) ;; Serialize dict with sorted keys (define canonical-dict :effects () (fn (d) (let ((sorted-keys (sort (keys d)))) (str "{" (join " " (reduce (fn (acc key) (concat acc (list (str ":" key) (canonical-serialize (dict-get d key))))) (list) sorted-keys)) "}")))) ;; Compute SHA3-256 content ID from an expression (define content-id :effects () (fn (expr) (sha3-256 (canonical-serialize expr)))) ;; First 16 chars of content ID (short form) (define content-id-short :effects () (fn (expr) (slice (content-id expr) 0 16))) ;; Create a bytecode module container (define make-bytecode-module :effects () (fn (version source-hash code) (list (quote sxbc) version source-hash code))) ;; Type predicate for bytecode modules (define bytecode-module? :effects () (fn (expr) (and (list? expr) (>= (len expr) 4) (= (first expr) (quote sxbc))))) ;; Get module format version (define bytecode-module-version :effects () (fn (m) (nth m 1))) ;; Get source content hash (define bytecode-module-source-hash :effects () (fn (m) (nth m 2))) ;; Get compiled bytecode (define bytecode-module-code :effects () (fn (m) (nth m 3))) ;; Create a code object (arity + constants + bytecode) (define make-code-object :effects () (fn (arity upvalue-count bytecode constants) (let ((parts (list (quote code)))) (when (> arity 0) (set! parts (concat parts (list :arity arity)))) (when (> upvalue-count 0) (set! parts (concat parts (list :upvalue-count upvalue-count)))) (concat parts (list :bytecode bytecode :constants constants))))) ;; Create provenance record (author, timestamp, source) (define make-provenance :effects () (fn (source-cid bytecode-cid compiler-cid timestamp) (list (quote provenance) :source-cid source-cid :bytecode-cid bytecode-cid :compiler-cid compiler-cid :timestamp timestamp)))