Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
7bdcd23
Add fork-local SCI runtime worlds
whilo Aug 31, 2026
e78db9f
Use dense slots for forked SCI worlds
whilo Aug 31, 2026
5e8617d
Optimize forked Var reads through dense slots
whilo Aug 31, 2026
09f1174
Add host fork capability protocol
whilo Aug 31, 2026
f692d3a
Document forkable runtime state audit
whilo Aug 31, 2026
61d063d
Convey fork worlds into async tasks
whilo Aug 31, 2026
abfcb82
Scope dynamic bindings to SCI worlds
whilo Aug 31, 2026
88e62a2
Add fork-local SCI atoms and async continuations
whilo Aug 31, 2026
8b04ce8
Release unreachable managed atom state before forks
whilo Aug 31, 2026
58963d1
Make SCI multimethods fork-local
whilo Aug 31, 2026
9b83592
Make SCI memoization caches fork-local
whilo Aug 31, 2026
d018dff
Make SCI delays and JVM promises fork-local
whilo Aug 31, 2026
8e527db
Isolate namespace and Var control state across forks
whilo Aug 31, 2026
6aa9f17
Isolate SCI type state and classify affine resources
whilo Aug 31, 2026
d31e31b
Cache active fork world selectors
whilo Aug 31, 2026
098aeff
Reject affine host resources during forks
whilo Aug 31, 2026
1eac92a
Manage mutable deftype fields across forks
whilo Aug 31, 2026
25cb294
Right-size forked world snapshots
whilo Aug 31, 2026
6020aac
Classify additional mutable host resources
whilo Aug 31, 2026
548ed89
Track mutable deftype liveness and boundaries
whilo Aug 31, 2026
6221624
Add interactive forked REPL tree demo
whilo Aug 31, 2026
50341a1
Make forkable runtime semantics opt-in
whilo Aug 31, 2026
8ef4d70
Add forkable continuation contexts
whilo Aug 31, 2026
653fe95
Release SCI 0.15.59
whilo Aug 31, 2026
a2c1137
build: prepare replikativ SCI distribution
whilo Sep 1, 2026
e3c6708
ci: register compatibility distribution workflow
whilo Sep 1, 2026
03654f7
fix forked host boundaries and concurrent state commits
whilo Sep 1, 2026
b23c453
avoid context overhead inside function recur loops
whilo Sep 1, 2026
3de07c1
preserve nested function provenance without commit lock inversion
whilo Sep 1, 2026
00f0730
close remaining contextual host boundary gaps
whilo Sep 1, 2026
c3a3b19
fix contextual functions in record extension keys
whilo Sep 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -213,15 +213,28 @@ workflows:
version: 2
ci:
jobs:
- jvm
- node
- jvm:
filters:
tags:
only: /.*/
- node:
filters:
tags:
only: /.*/
# - planck
- linux
- linux:
filters:
tags:
only: /.*/
# - mac
- deploy:
context:
- clojars-deploy
filters:
branches:
only: master
ignore: /.*/
tags:
only: /^replikativ-v0\.15\.59\.1$/
requires:
- jvm
- node
Expand Down
8 changes: 3 additions & 5 deletions .circleci/script/deploy
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
#!/usr/bin/env bash

if [ -z "$CIRCLE_PULL_REQUEST" ] && [ "$CIRCLE_BRANCH" = "master" ]
then
lein with-profiles +compile-java do clean, deploy clojars
fi
set -euo pipefail

exit 0;
test "${CIRCLE_TAG:-}" = "replikativ-v0.15.59.1"
lein with-profiles +compile-java do clean, deploy clojars
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
name: CI

on:
- push
- pull_request
push:
pull_request:
workflow_dispatch:

# TODO: Add the deploy if needed
jobs:
Expand Down Expand Up @@ -195,4 +196,3 @@ jobs:
- name: Test libsci example programs
run: |
bb libsci:test

246 changes: 165 additions & 81 deletions API.md

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,24 @@ SCI is used in [babashka](https://github.com/babashka/babashka),

## Unreleased

## 0.15.59-replikativ.1

- Adds forkable interpreter worlds with explicit host-resource fork policies
- Adds continuation-context retargeting for forked execution
- Compatibility distribution of upstream SCI 0.15.59; published under
`org.replikativ/sci` while the changes are proposed upstream

## 0.15.59

- Caches resolved JVM instance methods per call site for performance
- Fix [babashka#2030](https://github.com/babashka/babashka/issues/2030): `aset` on a primitive array was reflective and 170x slower than `aset-double`
- Bump edamame to `1.6.43`
- Add forkable interpreter worlds for Vars, namespaces, dynamic bindings, SCI
mutable values, and application-defined host resources.
- Add explicit continuation-context capture and retargeting so an embedding can
resume a suspended computation independently in related forked worlds.
- Add `with-detached-context` for recursively constructing an independent SCI
interpreter without inheriting the caller's execution-local world.

## 0.15.58

Expand Down
78 changes: 75 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
<img src="logo/logo-300dpi.png" width="100px">

[![CircleCI](https://circleci.com/gh/babashka/sci/tree/master.svg?style=shield)](https://circleci.com/gh/babashka/sci/tree/master)
[![Clojars Project](https://img.shields.io/clojars/v/org.babashka/sci.svg)](https://clojars.org/org.babashka/sci)
[![CircleCI](https://circleci.com/gh/replikativ/sci/tree/master.svg?style=shield)](https://circleci.com/gh/replikativ/sci/tree/master)
[![Clojars Project](https://img.shields.io/clojars/v/org.replikativ/sci.svg)](https://clojars.org/org.replikativ/sci)
[![Financial Contributors on Open Collective](https://opencollective.com/babashka/all/badge.svg?label=financial+contributors)](https://opencollective.com/babashka)
[![project chat](https://img.shields.io/badge/slack-join_chat-brightgreen.svg)](https://app.slack.com/client/T03RZGPFR/C015LCR9MHD)

**Small Clojure Interpreter**

> This is the replikativ compatibility distribution of SCI. It preserves the
> `sci.*` namespaces and upstream API while adding forkable interpreter worlds,
> explicit host-resource fork policies, and continuation-context retargeting.
> The changes remain proposed upstream; this coordinate gives downstream
> replikativ libraries a stable Maven dependency in the meantime. Do not put
> `org.replikativ/sci` and `org.babashka/sci` on the same classpath.

<blockquote class="twitter-tweet" data-lang="en">
<p lang="en" dir="ltr">I want a limited dialect of Clojure for a single-purpose, scripted application. SCI will fit nicely.</p>
&mdash;
Expand Down Expand Up @@ -94,7 +101,11 @@ Are you using SCI in your company or projects? Let us know [here](https://github

Use as a dependency:

[![Clojars Project](https://img.shields.io/clojars/v/org.babashka/sci.svg)](https://clojars.org/org.babashka/sci)
[![Clojars Project](https://img.shields.io/clojars/v/org.replikativ/sci.svg)](https://clojars.org/org.replikativ/sci)

```clojure
org.replikativ/sci {:mvn/version "0.15.59-replikativ.1"}
```

## Usage

Expand Down Expand Up @@ -584,6 +595,67 @@ aren't visible to other users:
(sci/eval-string* sci-ctx "forked") ;;=> Unable to resolve symbol: forked
```

Full runtime forking is opt-in. Initialize the shared context with
`:runtime-mode :forkable`; the default `:standard` mode retains SCI's original
direct hot paths and `sci/fork` only copies the namespace environment.

Values returned across the host boundary retain their world semantics:
interpreted functions returned by the public evaluation APIs execute in the
context that returned them, including higher-order results and functions nested
in finite persistent containers. Stable SCI Vars use their creation world when
called directly by the host. Use `sci/call-with-context` to select a descendant
explicitly, and use `sci/alter-var-meta!` / `sci/reset-var-meta!` for portable
fork-aware Var metadata mutation.

Forkable mode snapshots the roots and metadata of existing SCI vars and the
values of atoms and volatiles created inside SCI. The handles keep their
identity, so aliases and functions defined before the fork resolve against the
world in which they are invoked:

``` clojure
(def sci-ctx (sci/init {:runtime-mode :forkable}))

(sci/eval-string* sci-ctx
"(def counter (atom 0))
(defn bump! [] (swap! counter inc))")

(def forked (sci/fork sci-ctx))
(sci/eval-string* forked "(bump!)") ;;=> 1
(sci/eval-string* sci-ctx "@counter") ;;=> 0
```

Values supplied by the host remain the host application's responsibility. An
application-owned type can implement `sci.fork/Forkable`; SCI invokes its
`fork-value` method once per identical value in each fork and preserves aliases
to the resulting copy. Returning the object itself explicitly shares it, while
throwing rejects the fork. For unclassified values, the optional `:fork-fn`
remains a general fallback. It should return immutable values unchanged and
preserve any aliasing that matters to the application:

``` clojure
(def sci-ctx
(sci/init {:runtime-mode :forkable
:fork-fn #(if (instance? clojure.lang.Atom %)
(atom @%)
%)}))
```

Dynamic binding frames remain scoped to their thread and evaluation, matching
the Clojure REPL model; a fork snapshots root bindings, not a running control
continuation. Stateful host objects not handled by `:fork-fn`, and mutable
facilities not owned by SCI such as Java objects, remain shared.

Runtime state is stored in dense lineage-local slots. A fork copies those
slots, favoring the expected case where ordinary reads and writes are much
more frequent than forks. On the JVM a fork waits for active forms in its
source world, so the copied state is a quiescent snapshot.

See [Forkable SCI worlds](doc/forking.md) for the lifecycle, semantic boundary,
and current limitations of this experimental model.

A small interactive tree of forked REPL worlds can be run with
`clojure -M:examples -m sci.examples.forked-repl`.

### Implementing require and load-file

SCI supports loading code via a hook that is invoked by SCI's implementation of
Expand Down
Loading
Loading