Sakura Lang

Changes since alpha.1

Current-main behavior, migration notes and limits after the published preview.

These docs track main, including Unreleased changes. The published npm latest is 0.1.0-alpha.1; use a source build for the changes below until a newer release publishes. This page does not declare M4 complete or stabilize experimental native execution.

Sources, diagnostics and portability

  • Sources now end in .sak, with no old-extension fallback. Rename old files with git mv main.sakura main.sak. sakura.toml, the sakura language id and sakura:///std/… URIs stay unchanged.
  • CRLF and LF have the same meaning, including newlines in strings. sakura fmt writes LF; fmt --check identifies CRLF as a formatting difference. A snapshot differing only in line endings is reported as a line-ending mismatch. Scaffolding writes .gitattributes with *.sak text eol=lf and *.snap -text.
  • JSON file URIs follow RFC 8089, including file:///C:/dir/main.sak. Terminal diagnostics use OS paths, without URI escapes. MCP path filters accept equivalent file URI spellings. On Windows, Node lookup honors PATHEXT and solver lookup uses .exe. These fixes are not a claim of a supported Windows release.
  • V1002 on Type.member can suggest a unique prefix/extension match when there is no near spelling: List.lenght → len, List.fil → filter. These fixes are suggested, never automatically safe; List.size no longer suggests slice.
  • V2002 names a declared callee and its module, with expected and actual argument counts. A function-value call retains the type form. V3001 can propose the effect's unique deterministic std handler; that edit remains incomplete.
  • Syntax-error suppression follows place: diagnostics whose spans point into the broken body are suppressed, as is its cascading V3001. An error in another module used from that body remains visible. Rechecks invalidate refinement dependencies through contracts and no longer duplicate reused tests' diagnostics.
  • V4004 limits a match, catch or let pattern decision tree to 1,048,576 nodes, not a fixed arm count. Or-pattern combinations and copied wildcard rows can expand the tree. It is diagnosed during lowering (build, run, test), not check. Thousands of flat literal or guarded rows can compile and run; split combinatorial matches into one column at a time. See V4004.

Analysis cache and check latency

check, build, run, test, LSP and MCP reuse std analysis from a disk cache, one file per compiler build at <cache>/sakuralang/std. The base is SAKURA_CACHE_DIR, otherwise XDG_CACHE_HOME or ~/.cache on Unix and LOCALAPPDATA on Windows. SAKURA_NO_CACHE=1 disables it. Missing, damaged or foreign entries are recomputed; files are disposable and have no format guarantee. This is separate from the authenticated proof cache. Concurrent test jobs should set distinct SAKURA_CACHE_DIR directories.

The recorded release-build measurements on one quiet macOS host fell from about 22 to 7 ms for sakura new cli and from 54 to 39 ms for a 10k-line check. These are observations, not platform guarantees. Long-lived servers also reuse std in memory. bench/bench compile --json compile.json reproduces the compile-latency workloads; its cache lives in bench/target/cache unless overridden.

Server limits and failures

Serve.host() bounds request bodies to 1 MiB. It rejects oversized bodies with 413, closes the connection and never calls the handler. The following additional cases are distinct:

ConditionHTTP responseDiagnostic and lifecycle
Reply status or headers cannot be sent500D091; server keeps running
WASM request exceeds SAKURA_MAX_COPY_BYTES413, connection closedD091 on stderr; handler not run, server keeps running
WASM handler response exceeds that budget500D091 on stderr; server keeps running
WASM heap cannot admit a request503, retry-after: 1D096 on stderr; server keeps running
WASM runtime trap during a request500One D090 naming function and PC; server stops and program exits 70
Request still waiting when program ends500One D090 “server stopped”, unless a defect already ended the program
Request arriving on an open connection after server stops, either backend503, connection closedHandler never runs

WASM tests resume after host faults or traps on a fresh instance. Invalid host operation indices or result shapes are D090; exhausted request tables are D091 for Clock.sleep and serve_listen. Defect records now carry JS-compatible messages and source spans from sakura.debug (omitted by --strip).

HTTP, cassettes and filesystem security

SAKURA_MAX_COPY_BYTES must be decimal digits representing 1 through 2^53−1. Empty, zero, signed, fractional, exponential, hexadecimal or spaced values cause D091 at first use; unset it for the 256 MiB default. JS Http.host().send now bounds the response body too. An oversized HTTP response is HttpError with “response too large”, not a runtime defect; use streaming for larger responses. A connection lost while reading a body is also HttpError on JS and WASM.

test --record stores at most 16 MiB of a sent or streamed response; exceeding it fails with HttpError without appending the exchange. Malformed exchanges fail when the cassette opens. Recording requires JS; WASM can replay the cassette and run test --contracts. Tests without --record have empty host permissions; Test.fixtures() retains its own grants. Secret HTTP headers work on WASM and remain redacted in cassettes. Secret.map now requires an explicit trust reason, and sakura audit lists it beside Secret.expose.

Writes through dangling symlinks inside an fs.write grant are refused with “escapes the directory”, even when the link points back inside the grant. This covers Fs.write, write/append File, cassette recording and Sql.sqlite on JS and WASM. Write to the target path instead of the dangling link.

Verification and performance

sakura verify reuses authenticated verdicts, including unknown(resource_limit) at the same budget, and replays eligible i64 counterexamples. JS and WASM builds remove eligible proved checks; total predicates go with them, while predicates calling functions still execute. requires, entry checks and checked arithmetic stay in this proof-removal pass. Proof key ownership, directory permissions and location are checked; builds never create the key.

Direct WASM local-handler/callback calls, fused collection access, tag comparisons, tail-call loops and large-match lowering reduce work while preserving semantics. Core output and snapshot hashes are now independent of earlier analyses in a process; std-first file ordering can change dump IDs and hashes. Finished WASM root tasks are freed between benchmark samples.

For dense integer IDs, prefer List to Map, as the DeltaBlue benchmark now does. Both return updated values: assign the result back. Use Map for sparse keys. The benchmark guide documents bench/bench envelope wasm.json native.json --json envelope.json. Inputs must share commit and host; the native file must use the matched lane. Exit 0 means a report was produced, not that every ceiling passed. Loaded-host and CI results are advisory. The native comparison ports are Rust/Go/OCaml/Koka, not a stable Sakura native backend.

Distribution and editor tooling

See Install for the published platforms and next-release additions: Linux ARM64 (glibc) archives and npm package, coming in v0.1.0, and Windows x64 MSVC ZIP, npm and install.ps1 packaging, coming in v0.2.0. Neither is in alpha.1. New macOS tag releases require Developer ID signing (team P62B65A837) and Apple notarization before archives and packages are assembled; this does not retroactively sign alpha.1. Bare Mach-O executables cannot carry a stapled ticket. The installer checks checksums and, when gh is available, requires successful attestation verification; without it, it reports “integrity verified, not attested”. Custom prefixes must be absolute.

The tree-sitter grammar is available in the repository. The generated skill, manifest and ZIP normalize Windows separators and are byte-identical across OSes. The skill entry point retains a 7,000-byte source working target and a tested 7,500-byte limit after release metadata is filled.

Edit on GitHub

On this page