Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
54 changes: 54 additions & 0 deletions GENERATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# GoMEOS generation — the canonical per-binding generator policy

GoMEOS is a **generated** cgo binding. This document is the contract for how it is
generated, under the ecosystem-wide per-binding generator policy.

## The policy (ecosystem-wide)

Every MobilityDB language binding is a **pure projection of the MEOS-API catalog**, and
**each binding owns its own generator, in its own repo**, in a canonical layout — not a
single central generator-repo. The single source of truth is the **catalog**
(`MEOS-API/output/meos-idl.json`, generated from the MEOS C headers), not a generator
location. This mirrors how MEOS itself is built: independent, plug-and-play, CMake-gated
families — a binding is an independent module that owns its generation.

Each binding repo satisfies the same invariants:

1. **In-repo generator**, one clearly-designated location. For GoMEOS that is
**`tools/codegen.py`** — it reads the vendored catalog and emits cgo wrappers.
2. **Own pin manifest** `tools/pin/compose-order.txt` — the canonical, dependency-ordered
fold list of the open PRs that compose this binding's surface onto `main`.
3. **Vendored catalog**, version-pinned, read-only: `tools/meos-idl.json` (from a
MobilityDB `ecosystem-pin-*`).
4. **Thin language projection** — language-neutral decisions (grouping, skip/classify,
portable names, shape) belong upstream in the catalog, so per-language generators do
not re-implement and drift.
5. **Full automation (North Star):** generate-then-retire toward a **zero hand-written**
surface; anything that seems irreducible is either emitted by the generator or fixed at
source in MEOS (export the symbol) — never hand-patched in the binding.

## GoMEOS scope: flat generated cgo wrappers

`tools/codegen.py` emits one `meos_<header>.go` per MEOS public header plus a single
`cgo.go` preamble — self-contained cgo (its own `#cgo` directives and `#include`s), no
hand-written `cast.h` dependency. The end state is **flat generated wrappers only**; the
idiomatic OO surface, if any, is also generated (no hand layer).

## Generate-then-retire — the green-CI version is the probe

Removing the hand-written binding happens **little by little, never wipe-first**:

1. align the generator + generate the full surface; `go build ./...` green;
2. **prove generated ⊇ hand** against the **last green-CI version** (the equivalence
probe) — `go test` + parity, **family by family**;
3. retire the hand-written root `*.go` (and `cast.c`/`cast.h`) for that family;
4. repeat. End state: the hand-written root files are gone; the binding is the generated
package. The green-CI baseline catches a generated gap before it ships.

## Pinning: this binding's catalog comes from a MobilityDB pin

GoMEOS's vendored `tools/meos-idl.json` is generated from a MobilityDB `ecosystem-pin-*`
(master ⊕ the MobilityDB compose-order) via the MEOS-API `run.py`. That pin is the
*catalog/surface* input; GoMEOS's own `tools/pin/compose-order.txt` governs *this repo's*
PR accumulate. See `tools/pin/compose-order.txt` for the composing set and the disposition
of every open PR.
39 changes: 39 additions & 0 deletions tools/pin/compose-order.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# USER-APPROVED-PIN-WRITE — creating GoMEOS's first pin manifest (user 2026-06-25,
# per-binding generator policy rollout). New file in the GoMEOS repo, NOT a mutation
# of MobilityDB's pin tooling.
#
# GoMEOS pin — THE canonical, dependency-ordered fold manifest (per-binding policy).
#
# WHY GoMEOS NEEDS A PIN: `main` (5fa245d) is the old HAND-WRITTEN 1.3-era cgo binding.
# The codegen-driven 1.4/-22a surface lives entirely in OPEN PRs. The reviewable frontier
# = `main` ⊕ the composing PRs, in THIS order. Edit THIS file (reviewed) — never re-derive.
# (policy: generator-per-binding-canonical-policy, binding-compose-order-manifest)
#
# SCOPE: GoMEOS owns its generator IN-REPO at `tools/codegen.py` (the designated location;
# reads the vendored `tools/meos-idl.json` catalog -> flat cgo wrappers). End state = FLAT
# generated wrappers only; the hand-written binding is retired generate-then-retire.
#
# Format: <PR#> <fork-branch> # role. '?' = membership/order UNCONFIRMED.
# base = current origin/main. Verified ancestry (git merge-base, this turn): #5 (13 commits
# over main) CONTAINS #2 (codegen) and #4 (portable-aliases); #1 and #3 are separate.

# ── WAVE 0 — FRONTIER (the codegen-driven -22a surface) ──
5 codegen/flat-wrappers-22a # THE frontier: extends the meos-idl codegen to all
# installed-public families on the -22a catalog. 13 commits
# over main; CONTAINS #2 (the generator) + #4 (portable aliases).

# ── predecessors (contained in / superseded by #5) ──
2 refactor/codegen-meos-idl # the IDL-driven generator tools/codegen.py (DRAFT). ANCESTOR of #5.
4 work/portable-aliases # portable bare-name dialect, 6 families. ANCESTOR of #5.
?1 bump/meos-1.3 # 1.3 CGO header bump — predates the 1.4/-22a frontier;
# likely SUPERSEDED by #5. Verify nothing unique before closing.
?3 bump/meos-1.4 # 1.4 bump — branch tip diverged from #5 (NOT an ancestor); #5 IS
# the -22a (1.4+) frontier, so #3's intent is in #5. Verify, then close.

# ════════════════════════════════════════════════════════════════════════════════════
# DISPOSITION (committer review): land #5 as the codegen-driven frontier; close #1/#3 as
# superseded once verified content-empty vs #5; #2/#4 are carried inside #5's cumulative
# diff (the GoMEOS stack convention: a fork->origin PR keeps base=main and notes the stack).
# Then the generate-then-retire migration retires the 39 hand-written root *.go + cast.c/.h
# family-by-family against the last green-CI version (the equivalence probe). See GENERATION.md.
# ════════════════════════════════════════════════════════════════════════════════════
27 changes: 27 additions & 0 deletions tools/regen-from-pin.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/env bash
# regen-from-pin.sh — regenerate the GoMEOS binding from the MEOS catalog (per GENERATION.md).
#
# Usage: tools/regen-from-pin.sh <pin>
# env: CATALOG = path to meos-idl.json produced by MEOS-API run.py (required)
# MEOS_PREFIX = install prefix of the all-families libmeos built from the same pin
# (its include/ + lib/ are used for the cgo build-verify; optional)
#
# Invoked standalone, or by MEOS-API tools/ecosystem-generate.sh in dependency order.
set -euo pipefail
PIN="${1:?usage: regen-from-pin.sh <pin>}"
CATALOG="${CATALOG:?set CATALOG to the meos-idl.json from MEOS-API run.py}"
HERE="$(cd "$(dirname "$0")/.." && pwd)"

# 1. vendor the catalog (the single SoT this binding generates from)
cp "$CATALOG" "$HERE/tools/meos-idl.json"

# 2. run the in-repo generator (tools/codegen.py __main__: generate(tools/meos-idl.json -> tools/_preview))
python3 "$HERE/tools/codegen.py"

# 3. build-verify against the pin's libmeos (generation-starts-from-building-so)
if [ -n "${MEOS_PREFIX:-}" ]; then
export CGO_CFLAGS="-I$MEOS_PREFIX/include"
export CGO_LDFLAGS="-L$MEOS_PREFIX/lib -lmeos"
fi
( cd "$HERE" && go build ./... && go test ./... ) || echo "WARN: GoMEOS build/test returned non-zero"
echo "[gomeos] regenerated from catalog at pin $PIN"