feat: build-time mutable/immutable collection toggle + fix list mutation

Add src/jolt/config.janet exposing a build-time `mutable?` constant read from
JOLT_MUTABLE at compile time (jpm build). Default is immutable.

Fix correctness bug: conj on a list (Janet array) mutated the original in
place. In immutable mode conj now copies first; in mutable mode it mutates.

Round 1 of persistent-collections work.
This commit is contained in:
Yogthos 2026-06-04 18:15:48 -04:00
parent 96e23c5235
commit 1ca93d61c6
3 changed files with 19 additions and 1 deletions

15
src/jolt/config.janet Normal file
View file

@ -0,0 +1,15 @@
# Build-time collection mode.
#
# Jolt can be built with either immutable (persistent) collections — proper
# Clojure value semantics — or fast Janet-native mutable collections.
#
# jpm build # immutable (default)
# JOLT_MUTABLE=1 jpm build # mutable
#
# This reads the environment at module-load time, so for a jpm-compiled
# executable the value is fixed when the binary is built (a true compile flag).
# `mutable?` is a constant, so the type-mode branches throughout core fold away.
(def mutable? (= "1" (os/getenv "JOLT_MUTABLE")))
# Convenience: immutable? is the default.
(def immutable? (not mutable?))

View file

@ -4,6 +4,7 @@
(use ./types)
(use ./phm)
(use ./regex)
(use ./config)
# ============================================================
# Predicates
@ -195,7 +196,8 @@
(tuple/slice (tuple ;(array/concat (array/slice coll) xs)))
(if (array? coll)
(do
(var result coll)
# lists prepend; copy first unless built in mutable mode
(var result (if mutable? coll (array/slice coll)))
(var i 0)
(while (< i (length xs))
(set result (array/insert result 0 (xs i)))