import Base
import ./src/Keys.bend as Keys
import ./src/MemTable.bend as MemTable
import ./src/SortedRun.bend as SortedRun
import ./src/Sstable.bend as Sstable
import ./src/SstFile.bend as SstFile
import ./src/Wal.bend as Wal
import ./src/Manifest.bend as Manifest
import ./src/MergeIter.bend as MergeIter
import ./src/Db.bend as Db
# --- Level 2: part control (1:1 delegates) ---
def cmp(+a: String, +b: String) -> Cmp:
Keys.cmp(a, b)
def eq(+a: String, +b: String) -> Bool:
Keys.eq(a, b)
def mem_empty() -> MemTable.MemTable:
MemTable.empty()
def mem_put(t: MemTable.MemTable, k: String, v: String) -> MemTable.MemTable:
MemTable.put(t, k, v)
def mem_del(t: MemTable.MemTable, k: String) -> MemTable.MemTable:
MemTable.del(t, k)
def mem_get(t: MemTable.MemTable, +k: String) -> Maybe<&2, String>:
MemTable.get(t, k)
def mem_count(t: MemTable.MemTable) -> Nat:
MemTable.count(t)
def sort_newest(entries: List<&2, MemTable.Entry>) -> List<&2, MemTable.Entry>:
SortedRun.sort_newest(entries)
def range_scan(+merged: List<&2, MemTable.Entry>, lo: String, hi: String) -> List<&2, MemTable.Entry>:
MergeIter.scan(merged, lo, hi)
def sst_build(+entries: List<&2, MemTable.Entry>, level: Nat, est_keys: Nat) -> Sstable.Table:
Sstable.build(entries, level, est_keys)
def sst_from_sorted_unique(+entries: List<&2, MemTable.Entry>, level: Nat) -> Sstable.Table:
Sstable.from_sorted_unique(entries, level)
def sst_build_sorted(+entries: List<&2, MemTable.Entry>, level: Nat, est_keys: Nat) -> Sstable.Table:
Sstable.build_sorted(entries, level, est_keys)
def wal_encode(b: Wal.Batch) -> String:
Wal.encode(b)
def wal_decode(+s: String) -> Maybe<&2, Wal.Batch>:
Wal.decode(s)
def sst_serialize(+entries: List<&2, MemTable.Entry>, +level: Nat) -> String:
SstFile.serialize(entries, level)
def sst_parse(+encoded: String) -> Maybe<&2, Sstable.Table>:
SstFile.parse(encoded)
def mfst_serialize(m: Manifest.Manifest) -> String:
Manifest.serialize(m)
def mfst_parse(+s: String) -> Maybe<&2, Manifest.Manifest>:
Manifest.parse(s)
# --- Level 1: Sess session monad (primary API) ---
type Sess is Kind(a <&> &1):
Sess{run: Db.Db -> (Db.Db & A)}
def Sess.pure(a, -A: Kind(a), x: A) -> Sess:
Sess{db => (db, x)}
def Sess.run_go(b, -B: Kind(b), s: Sess, st: Db.Db) -> Db.Db & B:
match s:
case Sess{run}: run(st)
def Sess.apply(a, -A: Kind(a), b, -B: Kind(b), p: Db.Db & A, f: A -> Sess) -> Db.Db & B:
match p:
case (st, x): Sess.run_go(b, B, f(x), st)
def Sess.bind(a, -A: Kind(a), -B: Kind(a), m: Sess, f: A -> Sess) -> Sess:
Sess{st => Sess.apply(a, A, a, B, Sess.run_go(a, A, m, st), f)}
def open(+dir: String) -> Db.Db:
Db.open_db(dir)
def put_go(+db: Db.Db, +k: String, +v: String) -> Db.Db:
match db:
case Db.Db{dir, mem, levels, flushed, manifest_token}:
Db.Db{dir, Db.apply_batch(Con{Wal.Put{k, v}, Nil{}}, mem), levels, flushed, manifest_token}
def del_go(+db: Db.Db, +k: String) -> Db.Db:
match db:
case Db.Db{dir, mem, levels, flushed, manifest_token}:
Db.Db{dir, Db.apply_batch(Con{Wal.Del{k}, Nil{}}, mem), levels, flushed, manifest_token}
def batch_go(+db: Db.Db, +muts: List<&2, Wal.Mut>) -> Db.Db:
match db:
case Db.Db{dir, mem, levels, flushed, manifest_token}:
Db.Db{dir, Db.apply_batch(muts, mem), levels, flushed, manifest_token}
def sget_go(+db: Db.Db, +k: String) -> Db.Db & Maybe<&2, String>:
(db, Db.db_get(db, k))
def sput(+k: String, +v: String) -> Sess<&2, Unit>:
Sess{db => (put_go(db, k, v), Unit{})}
def sdel(+k: String) -> Sess<&2, Unit>:
Sess{db => (del_go(db, k), Unit{})}
def sbatch(+muts: List<&2, Wal.Mut>) -> Sess<&2, Unit>:
Sess{db => (batch_go(db, muts), Unit{})}
def sget(+k: String) -> Sess<&2, Maybe<&2, String>>:
Sess{db => sget_go(db, k)}
def run_sess(a, -A: Kind(a), st: Db.Db, s: Sess) -> Db.Db & A:
Sess.run_go(a, A, s, st)
def value_of(a, -A: Kind(a), p: Db.Db & A) -> A:
match p:
case (db, x): x
def encode_batch(b: Wal.Batch) -> String:
Wal.encode(b)