Skip to content

Releases: yinzers/yinz-lang

v0.3.1 — M5: Array-By-Value Element Storage + Auto-SoA Layout

Choose a tag to compare

@patrickrizzardi patrickrizzardi released this 04 Jul 18:01

[0.3.1] — 2026-07-04 — M5: Array-By-Value Element Storage + Auto-SoA Layout

Commit range: v0.3.0..v0.3.1.

What ships

array<Shape> (and map<K,Shape>) elements are now owned, by-value, and inline in the
heap buffer, instead of stored as pointers. This permanently fixes the array-element
stack-dangling miscompile class that the M3a ArrayShapeRuntimeFieldWithWait guard only
masked by rejecting the pattern outright — a runtime-field array<Shape> now correctly
survives crossing a wait, and the guard (plus its registry deferral) is gone.

Riding that new contiguous storage, the compiler can now automatically lay out large,
provably-safe hot-loop arrays as Struct-of-Arrays (SoA) instead of the default
Array-of-Structs layout — a pure codegen decision, zero syntax change, byte-identical
program output in both scheduling modes. The array-using-soa-layout Tier 3 lint fires
on a qualifying array's declaration with jargon-free WHAT/WHAT-INSTEAD/WHY hover text.

Honest performance note. The cache-locality win SoA promises is real — confirmed
~3.3x faster under an optimizing LLVM backend (opt-18 -O2) on the calibration
workload — but it is not realized in the binaries ynz build ships today, because
the compiler runs zero LLVM optimization passes by default (measured: net ~1.0x, no
detectable benefit, sometimes a few percent slower). SIZE_THRESHOLD ships as a
documented, provenance-recorded conservative default (workload, machine, variance, date,
revisit trigger — never a bare constant), not a crossover-calibrated number, since no
crossover exists to calibrate against in shipped O0 binaries. The correctness of the new
representation is unconditional; its measured perf payoff is conditional on future
compiler work (see Deferred, below).

Added

  • Elem_size-aware YnzArray/YnzMap ABI — hard-cut, no parallel old-signature entry
    points; a missed call site is a compile error, not a silent drift.
  • Auto-SoA layout: one authoritative layout_decisions_query (shared with M4's
    false-sharing padding transform — padding always wins over SoA for a cross-thread
    shape, byte-layout-proven), array-using-soa-layout Tier 3 lint + registry entry,
    LSP/VSCode wiring, docs graduation (IMP-collections.md).
  • contains on array<Shape> is field-wise value equality (number/int/bool fields);
    string and nested-shape/collection fields compare by identity. Field-assign is
    copy-on-persist (snapshot at assignment) across shape fields, map values, array
    elements, and spawn descriptors — a genuine, documented divergence from JS/TS
    reference semantics, spelled out in docs/reference/REF-collections.md.
  • The repo's first SoA-shaped example (examples/pirates-roster's cannonball-volley
    demo) and a committed suppression-enumeration report covering every array<Shape>
    site in the example/fixture corpus.

Fixed

  • The stack-dangling miscompile class for array<Shape>/map<K,Shape> elements
    crossing suspension points — gone by construction, not by rejection.
  • A pre-existing symmetric map<K,Shape> miscompile (a loop-arm indirection mismatch),
    caught by this milestone's own RED-fixture-first discipline.
  • .copy() on an array was a pre-existing alias no-op in both layout modes (never a
    real deep copy) — now a genuine one-level copy in both AoS and SoA.

Deferred — triaged 2026-07-04, tracked on the roadmap

Next-fix priority (real bugs, pre-existing, not introduced by this milestone):

  • A codegen crash (ICE) on a bare int literal assigned into any number-typed slot.
  • A general O0 stack-exhaustion SIGSEGV ceiling on very large hot loops (all layouts).
  • A stale cross-profile libynz_runtime.a release archive can silently miscompile by
    resolving old-ABI symbols instead of failing to link (an operational rebuild-clean
    guard is in place; the structural ABI-version-check fix is tracked, not yet built).

Fine to defer past v1.0 (perf/process only, not bugs):

  • Phase 5's codegen doesn't yet consume the per-field hot_fields set the SoA analysis
    already computes — a real, cheap, independently-actionable win distinct from needing
    an optimizer.
  • Adding an actual LLVM optimization pass pipeline to ynz build — the single root
    cause blocking every code path the compiler emits, concurrency included, from
    approaching the language's Rust-level-performance positioning.
  • A write-time hook to mechanically catch a recurring twin-derivation bug class
    (unrelated to this milestone; carried from the M4 AAR).

v0.3.0 — Concurrency: Channels, Task Handles, Auto-Arc, Mixed CPU+I/O Overlap

Choose a tag to compare

@patrickrizzardi patrickrizzardi released this 03 Jul 17:37

Commit range: v0.3.0-m7..v0.3.0 (M3g + M4 content only — M3f and M3d, though present in this
git range because they merged after the v0.3.0-m6/v0.3.0-m7 tags were cut, are already
covered above and are NOT re-described here).

What ships

This is the final v0.3.0 release: the milestone where Yinz code genuinely runs
concurrently, safely, on one unified suspension substrate. It closes the last gap in
auto-parallelization (mixed CPU+I/O groups), and adds the concurrency-communication
surface — bounded channels, task handles, safe cross-thread sharing, and false-sharing
protection — on top of the poll-based substrate M3a/M3b/M3d already proved out. The
may-block suspension question is answered in exactly one authoritative place, threaded
into every consumer, closing a class of twin-computation-drift bug that had silently
miscompiled four prior milestones (M3a/M3d/M3e/M3g).

M3g — mixed CPU+I/O overlap

  • A function body mixing one heavy CPU call and one I/O (wait) call as independent
    operations now runs them concurrently — CPU on a worker core, I/O suspended — instead
    of sequentially. This was the last gap in "all independent operations
    auto-parallelize": M3b covered pure I/O overlap, M3d covered pure-CPU overlap; M3g
    fuses the two poll paths (one shared continuation re-drives both the CPU join-poll and
    the I/O inline-poll on every resume) so a mixed group overlaps too, without
    deadlocking — the failure mode a verify-first pass on M3d had proven genuinely
    milestone-sized, not avoidance.
  • Output remains byte-identical to --no-auto-parallel for every fixture; the flag
    self-gates the fusion exactly as it gates pure-CPU and pure-I/O promotion.

M4 — channels, task handles, auto-Arc, false-sharing padding

  • channel<T>() bounded channels — construction, send()/recv(), default capacity
    64 (channel<T>(N) to override; no unbounded constructor by design). send() on a
    full channel suspends the caller through the same poll-yield substrate as wait
    "a suspended producer is backpressure working correctly, not a deadlock," documented
    as such in docs/reference/REF-concurrency.md.
    Channel operations join the unified may-block source like any other suspension point.
  • Background task handleslet h = background worker(...) yields a handle
    supporting .send() into the running task and repeated .receive(), covering both
    message replies from a long-running task and a plain suspending function's own
    completion value. A collected result's ok-value is copied to a handle-owned buffer
    before the frame frees (compile-time spawn-form-keyed — no runtime "was this
    collected?" tracking anywhere); the bare fire-and-forget spawn path is unchanged.
  • Cross-thread auto-Arc — boundary exactness. The share/lend-across-background
    reject is now exact in both directions, including previously-silent unresolvable/
    non-ident-callee call sites. The acquire-release runtime substrate ships; the codegen
    EMISSION that would make cross-thread sharing atomic is deferred to v0.4+ (a
    documented, tracked deferral — today's cross-thread read access is already safe via
    the existing independent-copy path).
  • False-sharing auto-padding. Shapes with fields touched by different background
    tasks get automatic 64-byte cache-line padding — codegen-only, no source change
    required. The cross-thread-fields-not-padded Tier 3 lint fires when the compiler
    can't safely auto-pad (cross-module-visible layout). This is the first layout
    transform gated by --no-auto-parallel, and the gating is proven, not assumed.
  • [[lint_rule]] registry mechanism — built from scratch (schema, parser, build.rs
    constants, LSP seam), generic enough for future lint domains (M5's auto-SoA lint
    reuses it with zero rework). Carries cross-thread-fields-not-padded and
    prefer-yielding-sleep (suggests the yielding wait sleep(ms) over the
    thread-parking sleepBlocking(ms) in schedulable programs).
  • Teaching surface — a channel_capacity muted inlay hint (shows the default 64,
    click-to-make-explicit); auto_arc is registered with its full cautionary hover text
    (fires once the v0.4+ emission lands); docs/reference/REF-concurrency.md gained the
    full channel/handle-form user spec including the backpressure teaching text; the VSCode
    extension bumped to 0.3.0.

Tests

The R6 may-block unification parity test (build-blocking — the fifth touch of the
twin-derivation class, now closed with one authoritative source); the R5 composed
deadlock-safety hostile fixture (child suspends on a full channel while the parent
polls .receive() — proven safe through the real compiler, not asserted); R1/R2
hostile fixtures (never-received channels, pool exhaustion); the R8 collection matrix
including the composed R5×R8 cell (a collected background child that both suspends on
send() and is collected at completion); the R3 cross-thread boundary-exactness matrix;
a full --no-auto-parallel cross-impl sweep across every new fixture, including the
false-sharing padding transform and the composed-suspension case, byte-identical in
both modes. Full workspace suite, clippy, and fmt green.

v0.3.0-m7 — M3d: Pure-CPU Statement Parallelization

Choose a tag to compare

@patrickrizzardi patrickrizzardi released this 20 Jun 02:20

M3d — Pure-CPU Statement Parallelization

Independent heavy pure-CPU calls now run on separate cores automatically — zero new syntax, output byte-identical to --no-auto-parallel. The CPU counterpart to M3b's I/O overlap; promotion is conservative (declining to sequential is always safe) and gated off in kernel mode and under --no-auto-parallel.

Highlights

  • ynz-typeck cpu_admission: single authority deciding CPU groups (consumed by both the IDE hint and codegen) + does_real_work worth-it fixpoint.
  • ynz-codegen: state-machine promotion lowering, group-poll join; reads the admission authority, cross-pinned to the IDE hint by a spawn-count parity test.
  • ynz-runtime: joinable CPU spawn/poll/free C-ABI, panic re-raise, drop-detach — poll-based throughout (no synchronous join).
  • ynz-abi (new crate): single-sourced spike-frame offsets, const-asserted cross-crate.
  • Teaching: parallel_groups inlay hint.

Tests

15 danger-matrix + 8 hostile fixtures + corpus-wide cross-impl byte-identical sweep + spawn-count cross-pin parity tests. Full workspace suite green.

VSCode extension: install yinz-latest.vsix (stable URL) or the versioned yinz-0.3.0-m7.vsix below.

v0.3.0-m6 — M3f: Pre-Existing Codegen Correctness Fixes

Choose a tag to compare

@patrickrizzardi patrickrizzardi released this 10 Jun 02:19

Closes two confirmed silent miscompiles in the state-machine / auto-parallelization codegen — both wrong-answer-at-runtime bugs that v0.3.0-m5 shipped with. No new language surface: programs that were already correct are byte-identical; only programs that were silently producing wrong values change (now correct). This unblocks the final v0.3.0 release.

Fixes (M3f)

  • Wide-errors same-callee value aliasing — two let bindings of the same -> number errors function (e.g. let p1 = fetchPrice(0); let p2 = fetchPrice(1)) no longer collapse to the same value. A number (decimal128) ok-value too wide for the result word used to live in the callee's shared staging slot, and a second same-callee call clobbered the first binding before it was read. Each binding now copies its value into its own storage at bind time. (Was: 31.75 / 31.75; now: 24.50 / 31.75.)
  • Parallel-group boolean sibling corruption — when independent suspending statements auto-parallelize and a boolean result is live across a later wait, a sibling integer result no longer reads back 0. The boolean's frame store was an 8-byte write into a 1-byte slot, overrunning the adjacent result. Restores the cross-implementation consistency oracle (--no-auto-parallel produces byte-identical output to the default). (Was: default 0 vs --no-auto-parallel 42; now: 42 in both.)

Tests

12 new regression fixtures + 12 integration tests covering the full trigger matrix (mixed result types — int, boolean, decimal128, and wide-errors — in parallel groups crossing a later wait), each asserting --no-auto-parallel byte-identity. The pirates-roster demo exercises both fixed patterns. Full workspace suite green.

Full diff: v0.3.0-m5...v0.3.0-m6

v0.3.0-m5 — M3e + M3b: Cross-Module Frame Serialization + Auto-Parallelization

Choose a tag to compare

@patrickrizzardi patrickrizzardi released this 09 Jun 03:27

[0.3.0-m5] — 2026-06-09 — M3e + M3b: Cross-Module Frame Serialization + Auto-Parallelization

Commit range: v0.3.0-m4..v0.3.0-m5

What changed

v0.3.0-m5 bundles two concurrency milestones. M3e lets a suspending function be
called across module boundaries — the M2/M3a substrate could only suspend within one
module. M3b makes independent suspending statements overlap automatically: write
straight-line code, get concurrent I/O for free, with no async/await and no spawn
syntax. Programs that compiled before are byte-identical; the new --no-auto-parallel
build flag is a permanent escape hatch and the cross-implementation consistency oracle.

Features (M3e — cross-module frame serialization)

  • Cross-module wait — a function in one module can now wait on a suspending
    function defined in another module. The callee's full task-frame layout is serialized
    through the export table so the state-machine codegen can rebuild it on the caller's
    side. The universal-reject floor M3b shipped as an honest partial is lifted.
  • Conservative cross-boundary safety — an unresolvable edge (dynamic dispatch, FFI)
    still produces a clean teaching error, never a silent non-suspension.

Features (M3b — auto-parallelization)

  • Independent suspending statements overlap — two statements that each suspend and
    don't depend on each other run concurrently via a single-threaded interleaved poll
    (default ≈ the slower of the two, vs --no-auto-parallel ≈ the sum). Zero new runtime
    symbols — no thread spawn.
  • wait is the ordering barrierwait foo() completes (and joins all in-flight
    overlapped work) before the next statement starts. Loop iterations stay sequential.
  • background give/copy figured out for you — a value handed to a background task
    is automatically given (move) when unused after, or deep-copied when still used. Heap
    values get a real deep copy, freed when the task completes — no use-after-free, no leak.
  • Two new IDE hintswait_points (where the compiler suspends on I/O) and
    background_routing (which pool a background task lands in) render as muted inlay
    hints that read the effective suspend set, so they can't drift from actual behavior.

Soundness (M3b)

Auto-parallelization is sound by a type-based conservative floor: any argument whose
type is mutable-heap (a shape, array, map, maybe, union, or dynamic) is treated
as a potential aliased write, so a statement pair touching one runs sequentially. Golden
Rule 5 (compile-time safety) outranks Golden Rule 10 (efficiency) — the compiler forfeits
read-only-heap overlap rather than risk a data race. Primitive and string arguments
still overlap.

Known limitations / deferrals

  • background-handle result collection (ec-wrapper-collect-on-completion) — moved to
    v0.3-M4. Collecting a background-spawned -> T errors task's result via a handle needs
    the handle-collection syntax (.send/.receive), which ships separately. The inline-poll
    path for -> T errors works today.
  • Read-only-heap overlap forfeited — the conservative floor sequentializes mutable-heap
    arguments even when the callee only reads them. Reversal path: a type+alias-aware ownership
    analysis. Documented in design/concurrency.md.

Pre-existing bugs surfaced (not introduced by this release)

Two silent-wrong-output bugs were found during M3b adversarial review and confirmed to
pre-date auto-parallelization (identical wrong output with and without --no-auto-parallel).
Tracked on the roadmap as milestone M3f (blocks the v0.3.0 final release) and in
.claude/todos.md: (1) same-callee wide-errors (-> number errors) result slot reuse;
(2) a crossing local inside control flow after a wait. Neither is a regression.

Tests

1929 passing across the workspace (0 failed, 6 ignored). Cross-implementation oracle:
--no-auto-parallel equals default output on 196 + 31 fixtures, zero real divergence.
M3b passed a 5-reviewer cumulative review; M3e passed its own at close-out.

v0.3.0-m4 — M3a: wait in Loops + Frame-Backed Crossing Locals

Choose a tag to compare

@patrickrizzardi patrickrizzardi released this 04 Jun 22:42

[0.3.0-m4] — 2026-06-04 — M3a: wait in Loops + Frame-Backed Crossing Locals

Commit range: v0.3.0-m3..v0.3.0-m4

What changed

v0.3.0-m4 lifts the two harshest M2 compile-error guards (LocalCrossesWait and WaitInsideLoop) by completing the state-machine codegen substrate: frame-backed mutable locals and loop suspension. Every program that previously errored with one of these guards now compiles and produces correct output. Programs that compiled before are byte-identical.

This is v0.3-M3a — the first half of the original M3 plan, split out as its own shippable slice. M3b (statement-level auto-parallelization) builds on this substrate.

Features

  • Frame-backed crossing locals — a let local declared before a wait and used after now compiles correctly. The compiler flushes the local's value into the task frame before suspension and reloads it on resume. Every Yinz type is handled: int, bool (i1 zero-extended), float (bitcast), number (decimal128, 2 i64 slots), string (pointer via ptr_to_int), Shape (direct struct), array<T> (heap pointer), map<K,V> (heap pointer), and options (int-encoded). ONE ynz_alloc per task tree even for local-heavy functions — no per-crossing-local allocation.
  • wait inside while loops — the loop counter and any loop-carried locals are frame-backed; each wait suspension preserves them. Resume re-enters the loop body for the current iteration. Iterations run sequentially (design/concurrency.md "Loop Iterations — Sequential by Default") — NOT parallelized. M3b handles auto-parallelization of independent statements.
  • wait inside for loopsfor (x in array<T>) and for (entry in map<K,V>) loops with wait in the body. The array index and heap pointer are frame-backed; resume re-enters for the current index. Iteration order is preserved; output matches the hand-unrolled sequential form.
  • wait inside match arms — a wait in any match arm resumes into the correct arm. Any bindings live across the suspension are frame-backed via the P1 mechanism.
  • sleepAsyncsleep / sleepMssleepBlocking rename (P0) — the two sleep intrinsics now have their final names. sleep(ms) is the yielding form (suspends the function, OS thread freed). sleepBlocking(ms) blocks the OS thread (use only where thread-blocking is correct, e.g., background analytics). wait sleepBlocking(...) still emits the "wait has no effect" warning — intentional.

New diagnostics (WHAT/WHAT-INSTEAD/WHY format)

Kept-guard diagnostics reworded (P0) — no more false "ships in v0.3-M3":

  • SubExprSuspendViolation — reworded WHY states the step-by-step design rationale (Golden Rule 7) and notes M3b auto-parallelization of independent statements.
  • MutualSuspensionCycle — reworded WHY states that self-recursion works and mutual cycles are always restructurable.

New P3 deferral diagnostics (clean compile errors, never silent wrong output):

  • FixedArrayIterWithWaitfixed<T> array as a for-iterator with a wait; stack pointer dangles after suspension. Use array<T>.
  • StoredRangeWithWait — a range local iterated by a for with wait; inline the range expression.
  • ExpressionIterWithWait — a call-expression collection (for (x in makeArray())) with wait; bind to a local first.
  • UnsupportedCrossingLocalType (fixed) — a fixed<T> local crossing a wait; use array<T>.
  • MapEntryFieldAfterWaitentry.key/entry.value read after a wait in a for (entry in map) body; read fields before the wait.
  • RangeCrossingLocalWithWait — a range local crossing a top-level wait; inline the range.
  • ArrayShapeRuntimeFieldWithWaitarray<Shape> crossing a wait with runtime-computed element fields; use all-literal field values. Conservative interim guard; lifts entirely when the m3c-array-by-value milestone ships.

Known limitations (seven P3 deferrals — compile errors, not silent wrong output)

All seven are loud compile errors with WHAT/WHAT-INSTEAD/WHY diagnostics pointing to design/concurrency.md sections and named future milestones. None produce silent wrong output or crashes:

  1. fixed<T> as for-iterator with a wait — stack pointer dangles; use array<T>
  2. Stored range local then iterated with a wait — inline the range
  3. Call-expression collection with a wait — bind to a local first
  4. fixed<T> crossing local with a wait — use array<T>
  5. Map entry.key/entry.value after a wait — read before wait or use an outer accumulator
  6. range crossing local with a wait — inline the range
  7. array<Shape> with runtime-computed element fields crossing a wait (conservative guard) — lifted by m3c-array-by-value

IDE surface

M3a adds NO new muted-hint domain and NO new lint rule. The wait_points muted-hint domain and background_routing fire in M3b. The prefer-yielding-sleep Tier-3 lint rides M4's [[lint_rule]] infra (not yet built). sleep/sleepBlocking hover docs updated with their renamed names and per-stdlib-design-rule danger annotation for sleepBlocking.

Demo / gallery

  • examples/pirates-roster/entrypoint.ynz extended with v0.3-M3a Phase 4 section (m3a_p4_demo): a roster scouting loop that wait sleeps per item, with a crossing-local total accumulator updated across 5 suspensions. Demonstrates for+wait+crossing-local in realistic context (85+92+78+95+88=438).
  • examples/primantis-orders/v0_3_m3a_errors.ynz updated: removed the WaitInsideLoop trigger for for loops (P3 lifted it); added SubExprSuspendViolation and MutualSuspensionCycle triggers for the two permanent kept guards; added triggers for four representative P3 deferrals (FixedArrayIterWithWait, StoredRangeWithWait, MapEntryFieldAfterWait, ArrayShapeRuntimeFieldWithWait).
  • Two cross-impl consistency tests added (v03_m3a_p4_no_auto_parallel_*): assert --no-auto-parallel produces byte-identical output to default on a crossing-local fixture and a for-loop fixture. Gate wired for M3b.

v0.3.0-m2 — Teaching-Surface Bug Hunt

Choose a tag to compare

@patrickrizzardi patrickrizzardi released this 31 May 02:36

Fixes every bug from the four-agent teaching-surface audit — 14 cataloged bugs + 3 same-class siblings across unused-import diagnostics, inlay-hint walkers, hover, completion, and the banned-jargon quick-fix (merged from v0.2.1-M10, PR #68).

Two behavior changes worth noting:

  • let → const hints now fire far more often (the over-suppression bug meant the flagship hint almost never appeared in real code).
  • Inlay hints render in Pittsburgh gold (#ffd23f) and anchor at end-of-line.

Full notes: see CHANGELOG.md [0.3.0-m2].

VSCode extension: install yinz-0.3.0-m2.vsix, or pin to the stable latest URL:
https://github.com/yinzers/yinz-lang/releases/latest/download/yinz-latest.vsix

v0.3.0-m1 — Runtime Bootstrap + Working `background`

Choose a tag to compare

@patrickrizzardi patrickrizzardi released this 22 May 00:37

What's new

background fn(args) now actually runs on a separate thread. Previously (v0.1, v0.2), background parsed and type-checked but ran sequentially. M1 ends that: background tasks spawn on a thread-pool runtime; main continues immediately.

Features

  • Working background — fire-and-forget on a separate thread. background fn(value.give) and background fn(value.copy()) both work.
  • sleepMs(ms) intrinsic — synchronous sleep for testing and demos.
  • Large-copy warningbackground fn(largeStruct.copy()) where the copy exceeds 64 bytes warns and suggests .give.
  • .give inlay hint — VSCode shows .give (transfers ownership; no copy) inline when the large-copy warning fires.

Safety errors

  • Lend-cross-threadbackground fn(lend-param) is now a compile error.
  • Kernel-mode rejectionsbackground and wait in --kernel mode are compile errors.

Improvements

  • Parser forward-progress guarantee (was hanging on certain error-recovery inputs).
  • Cross-impl corpus determinism harness (69 fixtures, all deterministic).

VSCode extension

Hover over background to see updated WHAT/WHAT-INSTEAD/WHY docs. Bump to v0.3.0-m1.

Install: code --install-extension yinz-latest.vsix

Note: screenshots/background-concurrent.png is a placeholder — replace with a real screenshot before the v0.3.0 final release.

v0.2.0 — LSP Full Experience + Compiler Bug Fixes

Choose a tag to compare

@patrickrizzardi patrickrizzardi released this 21 May 15:03

v0.2.0 — LSP Full Experience + Compiler Bug Fixes

This release closes out the v0.2 dev-loop series and ships the full editor experience.

8 new LSP capabilities

  • Go-to-definition — Cmd+click any identifier → jumps to declaration (cross-file)
  • Find All References — lists every use-site across the project
  • Rename — F2 atomic rename; validates against Yinz keywords and banned jargon
  • Format on save — delegates to ynz-fmt; normalizes to LF line endings
  • Inlay hints — type annotations, ownership modifiers, auto-promotion hints
  • Code actions — quick-fix for every diagnostic with a WHAT-INSTEAD
  • Semantic tokens — richer color differentiation (keywords / types / functions / variables)
  • Structured diagnosticscode + data fields on every LSP diagnostic

Other improvements

  • Doc-comment hover: /// doc comments appear in hover popups
  • Completion narrowing: score. shows only int methods when score: int
  • ynz build --json: NDJSON diagnostic output for CI/tooling. Schema stable at "v0.2.0".

3 compiler correctness fixes

  • Hidden-field default eval: hidden bar: string = "default" now evaluates to "default" instead of null
  • Dynamic-dispatch coercion: passing a ConcreteFoo to dynamic Foo params now compiles when ConcreteFoo follows Foo
  • UFCS const-lend parity: const p; p.heal(20) now errors identically to heal(p, 20) when heal requires lend

Install

curl -L https://github.com/yinzers/yinz-lang/releases/latest/download/yinz-latest.vsix -o yinz-latest.vsix
code --install-extension yinz-latest.vsix

v0.2.0-m4 — ynz watch

Choose a tag to compare

@patrickrizzardi patrickrizzardi released this 20 May 19:52

ynz watch — rebuild-on-save daemon

ynz watch is now live. Save a .ynz file; it recompiles and re-runs within a second.

Quick start

ynz watch examples/basics/               # build + run on every save
ynz watch --check foo.ynz               # build only (CI gate)
ynz watch --json foo.ynz | jq .         # NDJSON event stream

What ships

  • Sub-second incremental rebuild via a long-lived salsa CompilerDb daemon — file events mutate SourceFile.text inputs; salsa invalidates downstream queries automatically.
  • Child process lifecycle — compiled binary spawned in its own process group (setsid); SIGTERM → 2s grace → SIGKILL on each rebuild cycle; unconditional Drop prevents zombies.
  • --json event streamwatch-ready, build-start, diagnostic (one per compile error with WHAT/WHAT-INSTEAD/WHY), build-end, child-spawn, watch-shutdown. Schema version: v0.2-m4-unstable (semver-stable at v0.2.0 final).
  • EPIPE handlingynz watch --json | head -1 exits cleanly with watch-shutdown { reason: "pipe-closed" }.
  • 3-layer memory defense for 24h+ continuous use:
    • Salsa LRU caps: lex(128) parse(128) signatures(128) check(64) codegen(32)
    • Periodic DB rebuild every 500 cycles or 4h (monotonic; shadow HashMap preserves source state — zero data loss)
    • RSS polling via memory-stats; soft-warn at 1GB, hard-stop at 4GB with WHAT/WHAT-INSTEAD/WHY exit message

Demo

examples/watch_demo/   — minimal project; edit the print message and save

Deferred

  • YNZ_WATCH_LRU_* runtime tuning env vars (documented, not yet wired)
  • Windows full validation pass
  • Interactive commands (r to rebuild, q to quit) — v0.3+