File System

pub struct EnvVariable {
  name: text,
  value: text
}

Types and functions for reading and writing files. A File value is obtained via file() and carries the path, format, and an internal reference. An environment variable as a name/value pair.

pub enum Format {
  TextFile,
  LittleEndian,
  BigEndian,
  Directory,
  NotExists
}
pub enum FileResult {
  Ok,
  NotFound,
  PermissionDenied,
  IsDirectory,
  NotDirectory,
  Other
}
pub fn ok(self: FileResult) -> boolean
pub struct File {
  path: text,

  size: integer,

  format: Format,

  ref: i32,

  current: integer,

  next: integer
}
pub fn content(self: File) -> text
pub fn lines(self: File) -> vector < text >

Returns the platform path separator character: '\' on Windows, '/' elsewhere. Detected once at startup from the runtime filesystem.

pub fn path_sep() -> character
pub fn file(path: text) -> File
pub fn exists(path: text) -> boolean
pub fn exists(both: File) -> boolean

Plan-06 phase 5a: #impure(io) — calls file() (filesystem stat). Method form: f = file("path"); if f.exists() { ... } Also callable as exists(file_obj) via the 'both' parameter name.

pub fn delete(path: text) -> FileResult
pub fn move(from: text, to: text) -> FileResult
pub fn mkdir(path: text) -> FileResult
pub fn mkdir_all(path: text) -> FileResult
pub fn mtime(path: text) -> integer

Modification time of `path` as Unix epoch SECONDS (integer — same i64 representation as file.size). Returns 0 on missing file / IO error / pre-epoch dates — caller treats 0 as "unknown" (matches scan.sh's `stat -c %Y || echo 0` fallback). Takes a path string rather than a File handle so the native + interp dispatch both use the same `n_mtime` registration. Use for date-window filters like @PLAN37 phase 07's `plans_recent` 60-day cutoff: pass the path, convert the returned seconds back to YYYY-MM-DD, and compare lexicographically against `ymd_days_ago(60)`.

pub fn store_durable_check(path: text) -> boolean

@PLAN38 phase 01b — durable-store integrity check. Returns true iff the `.dmeta` sidecar at `<path>.dmeta` validates against the main file at `<path>` (signature, header CRC, payload length, payload CRC, tier_id all OK). Returns false on any failure or missing file. Pair with `store_durable_seal` after a clean write session to record the new state.

pub fn store_durable_seal(path: text) -> boolean

@PLAN38 phase 01b — write a fresh `.dmeta` sidecar capturing the current main-file's byte length + CRC32 + a clean-close timestamp. Returns true on success, false on any I/O error. Call this after finishing a write session; if the program crashes between the last write and the seal, the sidecar stays stale and the next `store_durable_check` returns false → caller rebuilds.

pub fn store_persist_bind(r: hash, path: text) -> boolean

@PLAN38 — "the hash IS the file." Re-root the Store backing the given reference at a file path so mutations are durable via mmap without any explicit save/load loop.

First call on a path that does NOT yet exist: serialises the current in-memory Store at the reference's slot to disk (padded to a valid ≥1024-word image with a tail free block), then mmaps it back. Caller's existing DbRefs into that slot remain valid.

Call on a path that DOES exist: opens the file via mmap; the caller's prior in-memory contents at that slot are dropped in favour of the on-disk image. This is the load-on-startup path, assumes the on-disk layout matches the declared type.

Both modes return `true` on success, `false` on any I/O / format error (no panic — the binding is fail-soft, callers fall back to JSON or rebuild-from-source).

Typical dryopea-style pattern: pw = PaintedWorld { painted: hash<PaintedHex[q, r]>::new() } store_persist_bind(pw.painted, "dryopea_world.store") // …mutations to pw.painted now hit mmap'd bytes…

pub fn set_file_size(self: File, size: integer) -> FileResult
pub fn sync(self: File) -> boolean
pub fn files(self: File) -> vector < File >
pub fn write(self: File, v: text)