diff --git a/.beads/interactions.jsonl b/.beads/interactions.jsonl index 8d362e0..77f6811 100644 --- a/.beads/interactions.jsonl +++ b/.beads/interactions.jsonl @@ -6,3 +6,6 @@ {"id":"int-40cd8348","kind":"field_change","created_at":"2026-06-04T18:09:15.510649Z","actor":"Yogthos","issue_id":"jolt-nte","extra":{"field":"status","new_value":"closed","old_value":"open"}} {"id":"int-57f4d2b3","kind":"field_change","created_at":"2026-06-04T18:31:23.83434Z","actor":"Yogthos","issue_id":"jolt-9sb","extra":{"field":"status","new_value":"closed","old_value":"open"}} {"id":"int-f46da620","kind":"field_change","created_at":"2026-06-04T18:33:45.099148Z","actor":"Yogthos","issue_id":"jolt-ytt","extra":{"field":"status","new_value":"closed","old_value":"open"}} +{"id":"int-677fb0a5","kind":"field_change","created_at":"2026-06-04T18:40:42.396722Z","actor":"Yogthos","issue_id":"jolt-40n","extra":{"field":"status","new_value":"closed","old_value":"open"}} +{"id":"int-10c63325","kind":"field_change","created_at":"2026-06-04T18:40:43.31635Z","actor":"Yogthos","issue_id":"jolt-4z9","extra":{"field":"status","new_value":"closed","old_value":"open"}} +{"id":"int-ba29d2c7","kind":"field_change","created_at":"2026-06-04T18:45:52.297233Z","actor":"Yogthos","issue_id":"jolt-gxr","extra":{"field":"status","new_value":"closed","old_value":"open"}} diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl index 50d79cf..0ce18a4 100644 --- a/.beads/issues.jsonl +++ b/.beads/issues.jsonl @@ -4,9 +4,9 @@ {"_type":"issue","id":"jolt-x8s","title":"CRITICAL: collections not callable as IFn (vector/map/set)","status":"closed","priority":1,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T17:46:14Z","created_by":"Yogthos","updated_at":"2026-06-04T17:50:54Z","closed_at":"2026-06-04T17:50:54Z","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"jolt-alz","title":"CRITICAL: self-referential lazy-seq/lazy-cat yields only literal prefix","status":"closed","priority":1,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T17:46:13Z","created_by":"Yogthos","updated_at":"2026-06-04T18:09:15Z","closed_at":"2026-06-04T18:09:15Z","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"jolt-wec","title":"CRITICAL: multi-collection map returns unrealized thunk","status":"closed","priority":1,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T17:46:12Z","created_by":"Yogthos","updated_at":"2026-06-04T18:06:02Z","closed_at":"2026-06-04T18:06:02Z","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-gxr","title":"HIGH: aliased namespace calls (require :as) don't resolve (s/join)","status":"open","priority":2,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T18:09:58Z","created_by":"Yogthos","updated_at":"2026-06-04T18:09:58Z","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-4z9","title":"HIGH: dispatch — multimethod :default, protocol-on-record, extend-protocol","status":"open","priority":2,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T18:09:57Z","created_by":"Yogthos","updated_at":"2026-06-04T18:09:57Z","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"jolt-40n","title":"HIGH: update/update-in/assoc-in fail on map literals (struct)","status":"open","priority":2,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T18:09:56Z","created_by":"Yogthos","updated_at":"2026-06-04T18:09:56Z","dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"jolt-gxr","title":"HIGH: aliased namespace calls (require :as) don't resolve (s/join)","status":"closed","priority":2,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T18:09:58Z","created_by":"Yogthos","updated_at":"2026-06-04T18:45:52Z","closed_at":"2026-06-04T18:45:52Z","dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"jolt-4z9","title":"HIGH: dispatch — multimethod :default, protocol-on-record, extend-protocol","status":"closed","priority":2,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T18:09:57Z","created_by":"Yogthos","updated_at":"2026-06-04T18:40:43Z","closed_at":"2026-06-04T18:40:43Z","dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"jolt-40n","title":"HIGH: update/update-in/assoc-in fail on map literals (struct)","status":"closed","priority":2,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T18:09:56Z","created_by":"Yogthos","updated_at":"2026-06-04T18:40:42Z","closed_at":"2026-06-04T18:40:42Z","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"jolt-ytt","title":"HIGH: str semantics — (str nil)='nil' should be '', (str :b)='b' should be ':b'","status":"closed","priority":2,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T18:09:56Z","created_by":"Yogthos","updated_at":"2026-06-04T18:33:45Z","closed_at":"2026-06-04T18:33:45Z","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"jolt-9sb","title":"HIGH: destructuring gaps (nested seq, :strs, nested map, fn-param)","status":"closed","priority":2,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T18:09:55Z","created_by":"Yogthos","updated_at":"2026-06-04T18:31:24Z","closed_at":"2026-06-04T18:31:24Z","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"jolt-7dy","title":"MED: compiler path lacks IFn dispatch (collections-as-fn) — only interpreter fixed","status":"open","priority":3,"issue_type":"bug","owner":"yogthos@gmail.com","created_at":"2026-06-04T18:10:00Z","created_by":"Yogthos","updated_at":"2026-06-04T18:10:00Z","dependency_count":0,"dependent_count":0,"comment_count":0} diff --git a/src/jolt/core.janet b/src/jolt/core.janet index 7b019eb..a4de998 100644 --- a/src/jolt/core.janet +++ b/src/jolt/core.janet @@ -867,6 +867,15 @@ (each x xs (array/push result (str-render-one x))) (string/join result "")))) +(defn core-str-join + "clojure.string/join: stringify each element (Clojure semantics), then join." + [coll &opt sep] + (default sep "") + (let [items (realize-for-iteration coll) + parts @[]] + (each x items (array/push parts (str-render-one x))) + (string/join parts (str-render-one sep)))) + (defn core-name "Returns the name string of a keyword, symbol, or string." [x] @@ -1975,7 +1984,7 @@ "str-replace" string/replace "str-replace-all" string/replace-all "str-reverse-b" string/reverse - "str-join" string/join + "str-join" core-str-join "str-split" string/split "str-triml" string/triml "str-trimr" string/trimr diff --git a/src/jolt/evaluator.janet b/src/jolt/evaluator.janet index 825931b..980eb8d 100644 --- a/src/jolt/evaluator.janet +++ b/src/jolt/evaluator.janet @@ -3,6 +3,7 @@ (use ./types) (use ./phm) +(use ./reader) (defn- sym-name? [sym-s name-str] @@ -129,6 +130,38 @@ [sym-s] (if (sym-s :ns) (string (sym-s :ns) "/" (sym-s :name)) (sym-s :name))) +(defn- ns->path + "Map a namespace name to its Jolt stdlib source path (dots->dirs, dashes->_)." + [ns-name] + (string "src/jolt/" + (string/replace-all "." "/" (string/replace-all "-" "_" ns-name)) + ".clj")) + +(defn- load-ns-file + "Parse and evaluate every form in a .clj file in the given context." + [ctx path] + (var s (slurp path)) + (while (> (length (string/trim s)) 0) + (def [f r] (parse-next s)) + (set s r) + (when (not (nil? f)) (eval-form ctx @{} f)))) + +(defn- maybe-require-ns + "If namespace ns-name isn't populated yet and a stdlib source file exists, + load it. Restores the current namespace afterwards (the file's `ns` form + changes it). No-op for already-loaded namespaces." + [ctx ns-name] + (let [ns (ctx-find-ns ctx ns-name)] + (when (and (= 0 (length (ns :mappings))) (not= ns-name "clojure.core")) + (let [path (ns->path ns-name)] + (when (os/stat path) + (let [saved (ctx-current-ns ctx)] + # Jolt stdlib files have no `ns` form; switch into the target ns so + # their defs intern there, then restore. + (ctx-set-current-ns ctx ns-name) + (load-ns-file ctx path) + (ctx-set-current-ns ctx saved))))))) + (defn- eval-require [ctx spec] (let [ns-sym (in spec 0) @@ -149,7 +182,7 @@ (set refer-syms (in spec (+ i 1))) (set i slen)) (++ i)))))) - (ctx-find-ns ctx ns-name) + (maybe-require-ns ctx ns-name) (when alias (let [current-ns (ctx-find-ns ctx (ctx-current-ns ctx))] (ns-import current-ns alias ns-name)))