Commit graph

1 commit

Author SHA1 Message Date
Yogthos
8cbc695f99 feat(nrepl): nREPL server + client in Clojure on a Janet interop bridge
Add a general Janet interop bridge and an nREPL implemented on top of it.

Interop bridge (evaluator):
- A qualified symbol whose namespace is `janet` or `janet.<module>` resolves
  against Janet's environment: `janet/<name>` -> root binding (janet/slurp),
  `janet.<module>/<name>` -> module binding (janet.net/server, janet.os/clock).
  The explicit `janet` segment marks every crossing into host code (where
  Clojure semantics, e.g. collection representation, no longer hold). This makes
  the whole Janet stdlib — networking included — reachable from Clojure.

jolt.nrepl (Clojure, src/jolt/jolt/nrepl.clj):
- bencode codec (encode + streaming decode), ported from nrepl.bencode.
- server: accept loop via janet.net/accept + janet.ev/call (Janet's built-in
  handler arity-checks Jolt closures, so we drive accept ourselves); ops clone/
  describe/eval/load-file/close/ls-sessions/interrupt/eldoc following
  babashka.nrepl response shapes. eval captures *out* by rebinding Janet's :out,
  reports ns, streams out, and isolates the eval namespace (current-ns is global
  ctx state) restoring it afterward. Vars are rendered as #'ns/name (pr-str
  loops on a var's cyclic ns refs).
- client: connect / request / client-eval / client-clone / client-close.

CLI: `jolt nrepl [port]` starts the server and writes .nrepl-port; the Clojure
source is embedded at build time so the binary is self-contained from any cwd.

Tests: test/spec/nrepl-spec.janet (bencode), test/integration/nrepl-test.janet
(server+client over a real TCP/bencode wire, server in a subprocess).
2026-06-05 21:25:23 -04:00