~ober/jerboa-compat

Imported from ~/mine/jerboa-compat

download snapshot

about

# jerboa-compat

Gerbil-only compatibility shims providing the parts of Jerboa's standard library
that **Gerbil Scheme lacks**, so Jerboa `.ss` sources (e.g. from `jerboa-emacs`)
can be ported to Gerbil (e.g. `gerbil-emacs`) with mechanical import renames
instead of rewrites.

> Repo routing: this is a Gerbil library, so it lives on **git.cons.io** as
> `gerbil-jerboa-compat` (Gerbil package name: `jerboa-compat`). The on-disk dir
> is `~/mine/jerboa-compat`.

## Why

`jerboa-emacs` and `gerbil-emacs` are forks of one ancestor and share almost the
same surface syntax (`def`, `defstruct`, `:std/sugar`, `[...]`, `(export …)`).
The friction when porting Jerboa → Gerbil is a handful of stdlib modules Jerboa
exposes that Gerbil does not — concentrated in `jerboa-emacs`'s `chez-powers.ss`.
This package reproduces that surface on stock Gerbil.

## Modules

| Module | Backing | Notes |
|---|---|---|
| `:jerboa-compat/atom` | native | Clojure-style atoms; was already portable Gerbil. |
| `:jerboa-compat/lru-cache` | native | Gerbil has `:std/misc/lru` with a different API; this gives Jerboa's `lru-cache-*` surface, thread-safe. |
| `:jerboa-compat/stm` | native | Gerbil has **no** `:std/stm`. STM on Gambit threads + condition variables (the fiber path is dropped). |
| `:jerboa-compat/engine` | native | Gerbil has **no** `:std/engine` (Chez `make-engine` has no Gambit analog). Arbitrary-thunk engines and `timed-eval` fail closed because lexical closures cannot cross exec safely; `timed-eval/cooperative` is available for trusted cleanup-aware work. |

`timed-eval/cooperative` thunks can poll `(engine-cancelled?)` and unwind
normally when their budget expires; the helper performs a mandatory join so
`dynamic-wind` cleanup completes. The default `timed-eval`, `fuel-eval`, and
engine APIs reject arbitrary thunks. Production callers needing hostile-code
isolation must define a bounded data protocol and launch a fresh executable;
raw-fork callbacks are not a supported substitute.
| `:jerboa-compat/powers` | umbrella | Mirrors `chez-powers.ss`: re-exports the four above plus `:std/amb`, `:std/misc/{completion,rwlock,pqueue,wg,channel,rbtree,barrier}`, with Jerboa-named adapters where Gerbil's names differ. |

## Porting import map

When converting a `jerboa-emacs` source to `gerbil-emacs`:

| Jerboa import | Gerbil import |
|---|---|
| `:jerboa-emacs/chez-powers` | `:jerboa-compat/powers` |
| `:jerboa-emacs/atom` | `:jerboa-compat/atom` |
| `:jerboa-emacs/<other>` | `:gemacs/<other>` |
| `:jerboa-scintilla/…` | `:gerbil-scintilla/…` |
| `:jerboa-qt/…` | `:gerbil-qt/…` |

(The `jerboa-gerbil` converter applies these automatically.)

## Residual gaps

A few Jerboa symbols can't be backed by Gerbil's primitive without a native
rewrite; they are **not** yet exported by `powers.ss`:

- `channel-length`, `channel-empty?`, `channel-select` — Gerbil's `:std/misc/channel`
  is otherwise re-exported (put/get/try/close/closed?).
- `barrier-parties`, `barrier-waiting`, `barrier-reset!` — Gerbil's barrier is
  one-shot (post/error/wait), not the cyclic N-party barrier Jerboa ships.
- `amb` is re-exported from `:std/amb`; confirm call sites (its dynamic-state
  macros differ subtly from Jerboa's).

Each is a small follow-up (a native ring-buffer channel and a cyclic barrier).

## Build & test

```bash
gerbil build          # or ./build.ss
```

Modules are developed and tested through the `gerbil-mcp` toolchain
(`gerbil_compile_check`, `gerbil_eval`) against `/opt/gerbil/bin/gxi`.

recent commits