v0.2.7-dev
Pre-releaseViper Compiler Platform — Release Notes
Development Status: Pre-Alpha. Viper is under active development and not ready for production use.
Version 0.2.7 — Pre-Alpha (2026-06-30)
What this release is about
A hardening cycle continuing v0.2.6, with focused new capability in 3D, tooling, and the languages.
For 3D and game code, the renderer stops flickering frame-to-frame and gains spot-light shadows, a deterministic multi-threaded software rasterizer, node animation over a rebuilt glTF/FBX importer, and open-world streaming with navmesh export. ViperIDE becomes a real workbench — syntax highlighting, context menus, two-language formatting and language services, an activity bar with git source control, multi-root workspaces, an integrated terminal, and a VM debugger that steps, inspects locals, and evaluates watch expressions. A new agent-facing CLI (viper check/eval/explain) gives editors and scripts machine-readable diagnostics. The 2D drawing surface adds bitmap text and normalized gradients, and Zia gains integer-keyed maps and header-optional modules.
Underneath, the hardening backbone matters most to your running programs: recoverable runtime and asset-loader errors now fail closed — bad or hostile input returns null or a safe value instead of crashing — and one program produces identical results across the tree-walking VM and both bytecode engines, which now also run threaded Parallel/Pool callbacks. The GUI is re-skinned through a shared anti-aliased core, a codegen performance round retires the last -O0 demo carve-outs so every demo now builds at -O2, and Linux and Windows/MSVC both return to a fully green test suite.
- Graphics3D flicker stabilized. Occlusion history with covered-streak gating, depth-fitted shadow cascades, LOD/impostor hysteresis, and terrain-horizon culling end per-frame triangle flicker; every backend validates draw-command index ranges.
- Spot-light shadow maps (new). Shadow-casting spot lights share the directional shadow budget across all four backends, sampling with a perspective divide and cone-angle suppression.
- glTF/FBX import & node animation (new).
NodeAnimation3D/NodeAnimator3Dplay node, camera, and morph-weight clips; the FBX importer gains full transforms, cubic curves, PBR routing, and async loading. - Deterministic software rasterizer. A worker-pool rasterizer reproduces the single-threaded image bit-for-bit, so headless and CI renders stay reproducible while throughput scales with cores.
- Open-world streaming & navmesh tooling (new).
WorldStream3Dcells load into a resident-byte budget,NavMesh3D.Export/Importround-trip versionedVNAVMSH2, and stream manifests resolveasset://sidecars. - Runtime fails closed (repo-wide). Every recoverable runtime error now returns a safe sentinel instead of trapping, so malformed or hostile input degrades your program rather than crashing it; the lone exception — unrecoverable entropy/DRBG failure — aborts outright, so no path ever proceeds with predictable key material.
- Asset loaders fail closed (new). Corrupt, truncated, or oversized 2D images and 3D models/scenes return
nullwith queryable diagnostics; a shared count guard rejects any element count larger than its backing bytes, and libFuzzer harnesses keep the parsers crash-free. - Game3D degradation diagnostics (new). A process-wide
Game3D.Diagnostics3Dsurface counts the rare correct-but-degraded fallbacks (brute-force broadphase, clamped CCD, evicted audio voices, navmesh-grid fallback) so smoke probes can assert a clean run. - Backend & audio telemetry (new). Opt-in
Canvas3Dbackend counters (draws, dropped draws, mesh-cache hits/misses, stream uploads, fallback binds, active presentation path) and an audio-mixer diagnostics surface (renders, partial writes, xruns, recoveries, write failures) make a degraded render or audio path measurable rather than silent. - Audio effects and consolidation. Mix groups gain low-pass, high-pass, peaking EQ, delay, and reverb insert chains; spatial audio is consolidated under one runtime home (
src/runtime/audio/). - IL & codegen invariants validate in release. The IL builder promotes debug-only invariants to release-mode validation, the verifier makes the EH
resumetoka linear handler-provenance capability (ADR 0005), and codegen and the linker surface diagnostics instead of asserting. - Codegen performance round, and every demo at
-O2. The AArch64 allocator unlocks all sixteen argument registers and caches spilled-operand reloads, and shares pre-RA copy-forwarding with x86-64 (six correctness fixes accompany the perf work); two optimizer fixes — verifier-accurate inliner type inference and SSA-reconstructing loop rotation — retire the last-O0demo carve-outs so every demo now builds and runs at-O2. - Unified scalar semantics (new). Your program now produces identical values and trap behavior whether it runs on the tree-walking VM or either bytecode engine — a VM-neutral kernel backs all three; block/instruction storage also moves to stable-address containers so references survive edits.
- Interpreted threaded callbacks (new).
Parallel.For/Parallel.Invoke/Pool.Submitrun their callbacks on the tree-walking and bytecode VMs — synchronously on the calling thread — while sequence-typed forms trap with explicit VM diagnostics rather than mis-dispatching to native; the shared default pool now drains before runtime-context teardown so a worker can't outlive the context it borrowed. - GUI refined-depth visual pass. A shared anti-aliased
vg_drawcore and new theme tokens route the whole widget set through one rounded, elevated style; ViperIDE gains vector toolbar icons and aGUI.GroupBoxsettings card, plus an IDE-facing toolkit round — general-purposeGUI.Grid/GUI.PopupListwidgets,OutputPanecell metrics, logical-unit layout helpers, and a revision-generationThreads.Schedulerdimension (ADRs 0019–0024). - ViperIDE editor & debugging (new). The code editor gains Viper/IL syntax highlighting, a compiler-driven semantic-color overlay, indentation guides, right-click context menus, and read-only preview enforcement (ADRs 0007–0008, 0011), plus Zia and new BASIC formatting; the VM-backed debug adapter (
viper run --debug-adapter) replaces v0.2.6's non-executing placeholder with pause/continue/step in-over-out, breakpoints, call stacks, locals, a current-line gutter marker, and non-blocking stop, and evaluates a selected expression or the identifier under the cursor against the stopped frame (ADR 0009) — alongside aWorkspace.FileIndex.Status-backed project index (ADR 0010), persistent UI zoom, and build-duration/error status. - ViperIDE workbench surfaces (new). An activity bar swaps the file Explorer for a full git Source Control view (stage/unstage, commit, push/pull, branch, per-file diff over
Viper.System.Exec); workspaces hold multiple roots; an integrated terminal runs a real shell over a newViper.System.Ptypseudo-terminal runtime (ConPTY on Windows,posix_openpt/forkon POSIX); and BASIC editing gains the completion, diagnostics, hover, and document symbols Zia already had via a consolidatedViper.Basic.LanguageService(ADRs 0013–0016). - Agent-facing CLI (new).
viper check,viper eval, andviper explain/--print-error-codesover a central diagnostic-code catalog, plus--dump-runtime-api/--dump-opcodesregistry dumps; the LSP/MCP servers now carry the same structured diagnostics. - 2D drawing surface (new).
Pixelsgains bitmap-font text drawing and measurement (plain, scaled, centered/right-aligned) andGradient2Dadds normalizedSample/SampleRGBAwith legacy-percent aliases — the runtime backing for a Viper Paint rebuilt around a registry-driven tool set with layers, blend modes, and an HSL picker. - Zia integer maps & header-optional modules (new).
Map[Integer, T]lowers to theIntMapruntime (string-keyedMapunchanged) with declared key-type enforcement; source files may omit the module header (defaulting toMain); and the parser, lexer, and semantic checks tighten across precedence, diagnostics, and inheritance-aware visibility. - Runtime class names disambiguated. Colliding leaf names under
Viper.*are made unique (Graphics.Scene→SceneGraph, theGame.UIwidgets that shadowedGUIones→Hud*,Sound3D→SpatialAudio3D) and duplicateParse/Convertfold intoViper.Core.*, with old names kept as aliases and a test locking the no-collision invariant. - Windows and Linux builds back to green. Windows restores the BASIC-VM, installer, ViperIDE, and x86-64 suites and closes its D3D11 sign-off gaps; Linux returns to a full green suite — 1,670 passing.
By the Numbers
| Metric | v0.2.6 | v0.2.7 | Delta |
|---|---|---|---|
| Commits | — | 191 | +191 |
| Source files | 3,096 | 3,402 | +306 |
| Production SLOC | 669K | 762K | +93K |
| Test SLOC | 278K | 304K | +26K |
| Demo SLOC | 192K | 197K | +5K |
Counts via scripts/count_sloc.sh (production 761,859 / test 304,255 / demo 196,632 / source files 3,402); commits since the v0.2.6-dev tag (2026-06-01).
Graphics3D rendering
- A sustained pass ends per-frame visible-triangle flicker: queue-order-independent occlusion history with covered-streak gating, camera-depth-fitted shadow cascades, per-camera LOD/impostor hysteresis, and conservative terrain-horizon culling.
- Every backend (software/OpenGL/Metal/D3D11) validates draw-command index ranges and shares one depth-bias scale. D3D11 closes its sign-off gaps and routes uploads and screenshot readback through shared helpers that reject oversized, unaligned, or stale GPU state, and clamps post-FX scalar/enum inputs and effect-chain capacity before indexed passes; OpenGL drains GPU errors after every upload and bounds its texture/mesh caches by age and LRU.
- The software backend rasterizes across a deterministic worker pool — parallel scanline fills that reproduce the single-threaded image bit-for-bit — so headless and CI renders stay reproducible while throughput scales with cores.
- Shadow-casting spot lights join the shared directional shadow budget: a single perspective light view-projection drives all four shader languages, which perspective-divide spot coordinates and suppress contributions outside the cone while directional paths stay orthographic and cascaded.
- Anisotropic filtering arrives as
Material3D.Anisotropy(clamped 1–16, advertised viaBackendSupports("anisotropy")), andCanvas3Dexposes per-frame submission telemetry (DrawsSubmitted,SortPasses,BackendStateChanges) with stable radix/bucket sorts over reusable scratch. Opt-in backend counters add draw/dropped-draw, mesh-cache hit/miss, stream-upload, and fallback-bind totals plus the active presentation path, and aVIPER_OPENGL_PRESENToverride compares the Linux GL direct, probe, and offscreen paths during triage.
3D assets, animation, and Canvas3D (new)
NodeAnimation3D/NodeAnimator3Dplay node, object, camera, and morph-weight clips, andSceneAsset/Assets3Dcan pull a single clip from an external file.- The FBX importer gains full model transforms (rotation order, pivots, Z-up), cubic curves, PBR texture-slot routing, and async loading; glTF accessor and skin-weight validation tightens.
- New authoring helpers:
DrawMeshWindfoliage sway,DrawImage2DHUD blits,DrawMeshSkinnedfrom anAnimController3Dpose, nativeSetFullscreen/ToggleFullscreen(Game3D.Keys.F11), andMaterial3Ddepth-bias/ShadowMode. Canvas3DaddsBackendNameandBackendFallback(true when init fell back to software), and a recoverable texture-fallback diagnostic records when a failed upload substitutes a placeholder, so a degraded frame is observable rather than silent.- Content loaders stop trapping on bad content: every 2D image and 3D model/scene loader returns
nulland records a thread-local last-error code/message (AssetDiagnostics3D.LastLoadError), reserving traps for null or invalid handles. - A shared
rt_untrusted_countguard validates every element count read from a 3D asset against its backing bytes across the glTF, FBX, OBJ/STL, SceneGraph, and Game3D loaders, and new libFuzzer harnesses keep these parsers crash-free; the FBX importer parses ASCII doubles locale-independently, the glTF loader rejects unsafe accessor strides, and compound-collider and mesh-vertex growth became transactional so a failed resize leaves no half-built geometry.
Open-world streaming, navigation, and 3D safety
WorldStream3Dcells load a binary sidecar into a resident-byte budget;NavMesh3D.Export/Importround-trip versionedVNAVMSH2assets while still reading legacyVNAVMSH1; compressedTextureAsset3Duploads drain large mips across frames.- Non-finite interpolation, playback, and bone inputs across the animation stack clamp or revert to the bind pose; scene, transform, raycast, navigation, and physics entry points reject bad handles; stored references are class-checked so a reused slot is nulled rather than dereferenced.
- Game3D async loads read worker-safe snapshots, drop stale publishes so a cancelled load can't overwrite current state, and finalize screenshot/render-target capture with no present side effect. The SceneGraph spatial index records a ~1,800× indexed-vs-flat cull speedup on a 10k-node fixture.
- A retained
Entity3Dwhose entity was despawned degrades predictably — neutral reads, no-op writes, a countedStaleEntityCallstouch — instead of trapping; genuinely invalid handles still trap. - Fallbacks that stay correct but shed fidelity are now observable: a process-wide
Viper.Game3D.Diagnostics3Dstatic exposes saturating counters (brute-force broadphase, clamped CCD, dropped animation events, evicted audio voices, navmesh-grid fallback, stale-entity touches) with a zero-omittingSummary(), andPhysics3DWorldsurfaces the same physics counts per world. Physics3DWorldadds fixed-step controls (explicit timestep and substep budget) so the simulation advances deterministically and independently of render frame rate.
2D graphics and drawing (new)
Pixelsgains a bitmap-font text surface —DrawText/DrawTextBg, scaled and centered/right-aligned variants, andTextWidth/TextHeight/TextScaledWidthmeasurement — so raster canvases can label themselves without a separate font path.Gradient2Dexposes normalizedSample/SampleRGBAover[0.0, 1.0]alongsideSamplePct/SampleRGBAPctpercent aliases, so existing integer-percent callers keep sampling the same stops as the public binding moves toNumber.
Runtime hardening (fails closed)
- A cppcheck-driven audit makes every recoverable
rt_trapreturn a safe sentinel and release its locals across core, text, crypto, network, OOP, process, media decoders, and input helpers — and routes unrecoverable entropy/DRBG failures through a non-returningrt_abort, so no path proceeds with predictable key material. Viper.Collections.F64BufferandViper.Collections.I64Bufferadd packed numeric buffers with slice/copy, scalar math, element-wise add, dot, min/max, and List/Seq conversion coverage.Viper.System.Shutdownadds a poll-based graceful shutdown bitmask so Ctrl-C/SIGTERM can be consumed by long-running loops before they become interrupt traps.Viper.Time.TimeZoneadds deterministic embedded IANA-zone lookup for UTC, Tokyo, New York, and Sydney, withDateTime.ToZoneandDateTime.FormatInZonecovering fixed offsets plus northern and southern DST transitions without host zoneinfo dependencies.- Game runtime content caps soften: Physics2D bodies/contacts/joints, quadtree result/pair buffers, ScreenFX slots, and in-game UI text/table/dropdown/modal storage now grow from documented default reservations instead of stopping at fixed internal arrays.
- BigInt gains checked size arithmetic and full arbitrary-width two's-complement bitwise/shift semantics; heap-header validation is now active in release builds (not just debug),
reallocroutes through a registry-safe move path, heap and pool allocation validate payload headers under the registry lock, and the pool freelist takes a short spinlock so a concurrent pop never reads a stale next pointer. - Text-format parsers fail closed and reach further: CSV/JSON preserve parse-failure state through trap recovery, HTML/XML grow traversal stacks under overflow checks, Markdown normalizes entity-obfuscated URL schemes, and TOML extends to escapes, inline tables, and arrays of tables.
- RSA verification goes constant-time; HTTP/2 framing, empty-body suppression, the WSS accept-vs-
Stoprace, and retry jitter tighten. Temp-file, archive, and savedata names draw their random suffixes from one centralizedrt_entropy_platform_random_u64(POSIX and Windows) and fail closed when secure entropy is unavailable; runtime-facing randomness is seeded from the RNG and counters rather than object addresses or fixed seeds; and the GIF and Theora/OGV decoders roll back per-frame so a corrupt packet leaves decoder state intact. - The sweep continues into output, process, and teardown paths: string-builder append checks across the command-line, path, date/number, relative-time, text-direction, SaveData/action-binding JSON, TOML, and XML formatters return clean sentinels instead of partial output; process launch moves to wide
CreateProcesson Windows andposix_spawnwith close-on-exec pipes on POSIX (draining captured output while waiting, never mutating process-wideSIGPIPE); TLS handshake/application secrets and AES-GCM scratch are wiped on teardown; and HTTP/HTTPS/WSS worker pools size from the runtime CPU count with thread-pool backpressure and capped active connections.
IL, codegen, and the native linker
- Debug-only IL-builder invariants — name uniqueness, operand and block-parameter bounds, branch-argument counts — promote to release-mode validation, and a new verifier dataflow catches double-release and use-after-release across the CFG.
- The EH
resumetokbecomes a linear handler-provenance capability (ADR 0005): exception dispatch is its sole producer, and newresume_token_mismatch/handler_invalid_entry/resume_token_escapediagnostics reject forged or stale tokens at verify time. Native EH lowering seeds each handler with its post-dispatch stack so a trap inside a catch/finally resolves to a concrete outer frame. - The IL error and numeric specs are promoted to active normative status, with EH metadata synced to ADR 0005 and a CTest guard preventing trap-kind drift.
- A VM-neutral
ScalarOpskernel now backs the tree-walking VM and both bytecode engines, so one IL module yields identical values and trap kinds across every execution mode (bytecode format bumped to v3).Function::blocks/BasicBlock::instructionsmove to a stable-addressStableListwith internedSymbolhandles so references survive insertion and erasure. - Shared
AllocaRootshelpers make alias analysis conservative for unknown calls, ConstFold/SCCP/Peephole normalize integer folds to fixed result widths, and CheckOpt shares one checked-range implementation with the builder — now demoting proven-safe overflow-checked i64 arithmetic to plain ops. - Selection, encoding, Win64 unwind, and AArch64 relocations surface diagnostics instead of asserting — atop the shared frame-layout fix that closes the O1 miscompiles — and the native linker hardens its four object readers, relocation ordering, trampoline-island growth, symbol resolution, and PE-image writing with checked count arithmetic and validated section bounds. Two optimizer correctness fixes accompany the linker work: the inliner now infers escaped continuation-block parameter types the way the verifier does — ending the
Void-typediadd.ovfresults that produced branch-argument/parameter mismatches — and loop rotation reconstructs SSA by threading body-used header parameters through the guard and latch edges, retiring the centipede/chess/crackman-O0demo carve-outs. - Codegen performance. AArch64 unlocks all sixteen argument registers via clobber-aware eviction and collapses N block reloads to one resident home; x86-64 eliminates duplicated end-of-block spill stores, models memory dependences precisely, and stops treating LEA as a barrier. Six correctness fixes accompany the work.
- VM↔native determinism gate, and writable globals natively. A byte-diffing differential runner over the shared IL corpus (
viper -runversuscodegen … -run-native) surfaced four native-codegen divergences from the tree-walking VM, now all fixed — including mutable scalar globals, which had no writable data section: the Mach-O, ELF, and COFF object writers now emit a.data/__datasection, sogaddron aglobal i64 @g = 41resolves intra-object on both the x86-64 and AArch64 native paths.
Bytecode VM and support libraries
- The bytecode VM validates memory ranges and indirect callees before dereference, traps instead of asserting on bad branch/switch targets, and bounds runaway programs via
BytecodeVM.setMaxInstructionsand a signal-safe interrupt. - Game3D loop helpers (
run/runFixed/overlay variants) now accept script function references from both the tree-walking and bytecode VMs, not only raw native pointers — the bytecode VM invokes these callbacks re-entrantly while a native call is suspended, so script-defined loops drive the engine under either VM. - The
Viper.Threadsparallel surface joins them:Parallel.For/Parallel.Invoke/Pool.Submitdispatch their callbacks synchronously on the calling thread under either VM (bytecode extern handlers registered, an e2e IL regression covering tree-walker, bytecode-switch, and bytecode-threaded dispatch), while sequence-callback forms trap with explicit diagnostics instead of falling through to native dispatch. A latent teardown crash is closed by draining the shared default pool before runtime-context teardown — workers unbind while their owning context is still alive — and gate, barrier, and reader-writer-lock finalization stay safe when waiters outlive the owning runtime object. - Sound gains an audio-mixer diagnostics surface (render calls, partial writes, xruns, recoveries, unrecovered failures) and a reworked ALSA backend with explicit hw/sw PCM configuration and transient wait/recovery; WASAPI shutdown joins its worker thread under a diagnostic timeout, music-stream teardown waits for in-flight refills without blocking indefinitely, and pause/resume/recovery failures surface through the backend stats; attach-state synchronizes under the context lock, and event-queue overflow drops transient motion events before close/key-up/focus-lost; glyph caches, file dialogs, and the code editor gain overflow guards.
GUI refined-depth visual pass
- A shared anti-aliased
vg_drawcore — rounded rectangles, discs, lines, soft shadows, gradients, deterministic fixed-point coverage — plus new radius/elevation/gradient/focus/motion theme tokens route buttons, inputs, dropdowns, menus, dialogs, tooltips, scrollbars, tabs, lists, and the file tree through one rounded, elevated style. - ViperIDE draws vector toolbar icons in place of Unicode glyphs, a titled
GUI.GroupBoxcard andGUI.Label.SetWordWraprebuild its settings panel, and gated hover/press/focus motion plus wheel-scrollable dialog content finish the pass.
ViperIDE — editor, debugging, workbench, and build feedback (new)
- The code editor gains real syntax highlighting (ADR 0007): widened
CodeEditortoken colors over a stable syntax-token enum, overridable function/operator/bracket classes, and Viper/IL highlighters with.ilfiles routed to the Viper one — plus toggleable indentation guides (CodeEditor.Set/GetShowIndentGuides) and tab hit-testing (TabBar.GetTabIndexAt), all added as registry-only runtime surface. - A compiler-driven semantic overlay (ADR 0008) layers classified colors over the lexical pass: a background Zia Tokens job feeds
CodeEditor.AddSemanticToken/ClearSemanticTokens, debounced off the keystroke path and cleared on every document change so stale tokens never linger. - Right-click context menus arrive for the editor and the tab bar — close/copy/reveal plus the standard edit commands routed through the existing handlers (
DocumentManager.GetDocumentbacks indexed menu actions) — and formatting reaches both languages, with the Zia formatter now ignoring braces inside strings and block comments and a new BASIC formatter handling whole-document and range formatting. - A debug adapter replaces v0.2.6's non-executing placeholder:
viper run --debug-adapterdrives pause, continue, step in/over/out, source breakpoints, call stacks, locals, and a current-line gutter marker over newline-delimited JSON, stops on unhandled traps before they unwind, and terminates without blocking the frame — force-killing the adapter only after a grace window. A watch/evaluate extension (ADR 0009) resolves a name against the current stop's frame snapshot — side-effect-free, returningok:falsefor an unresolved name — so an editor Evaluate command can inspect a selected expression or the identifier under the cursor while paused, the foundation for hover-to-inspect. - The
CodeEditorruntime gains read-only previews and an atomic gutter click (ADR 0011): preview, diagnostic, and binary buffers reject edits in the shared widget rather than in IDE command code, and breakpoint handling consumes one{clicked, line, slot}snapshot instead of racing three getters.Workspace.FileIndex.Status(ADR 0010) returns a metadata fingerprint so the IDE catches nested project-tree changes a non-recursive watcher misses, and the project tree is demand-loaded with aFileIndex-backed Quick Open cache. - Editor responsiveness and save safety tighten: semantic queries pump the workspace index to readiness before answering, hover/signature/inlay/symbol/search refreshes yield past a per-frame budget, Save As writes through a same-directory temp-and-move, external-change detection compares size and modified time, and an opt-out "save all before build/debug" default keeps project builds seeing fresh dependencies.
- ViperIDE adds persistent UI zoom (
GUI.App.SetUiScale), millisecond build-duration and error/warning status that auto-opens Problems on failure, and absolute-path resolution of thevipercompiler before each build. - An activity bar restructures the shell's left edge into an always-visible icon strip beside a swappable view stack — the file Explorer plus a new Source Control view — sitting outside the editor split so dragging the splitter never shrinks it. Workspaces now hold a primary project plus extra roots, with
AllRoots()and longest-prefixOwningProject(path)making tree population, the Quick-Open cache, and per-root ignore patterns root-aware; an Add Folder to Workspace command adds roots without closing the current project. - A git Source Control view drives
git -C <repo>throughViper.System.Exec— status, per-file unified diff, stage/unstage and stage-all, commit, push, pull, branch, and switch — capturing reads and running writes through separate calls so exit codes stay reliable. - An integrated terminal runs a real shell in a toggleable bottom panel — an ANSI-aware
OutputPane, command input, Run/Stop, and a View > Terminal entry — over a newViper.System.Ptypseudo-terminal runtime: a single merged ANSI stream with window resize, distinct from the pipe-basedProcess, built onposix_openpt/fork/setsid/execvpon POSIX and dynamically-resolved ConPTY on Windows 10 1809+ (ViperDOS unsupported; ADR 0016). The session reroots in the active project, survives restart, resizes from panel geometry, reports process exit, and exposes boundedPty.LastError()diagnostics for each unsupported-platform or setup failure. - BASIC editing gains the completion, diagnostics, hover, and document symbols ViperIDE already offered Zia, via a synchronous in-process bridge over
parseAndAnalyzeBasicwith weak runtime stubs that keep the runtime library frontend-free. It ships as a singleViper.Basic.LanguageService— consolidated from two leaf-colliding classes to hold the runtime's leaf-name-uniqueness invariant (ADR 0014) — with go-to-definition, references, rename, and signature help held back until BASIC grows a project index. A companion editor-input surface (ADR 0013) adds triple-click events and sharedCodeEditorword/line selection so interpreted and native callers observe identical mouse semantics, and themes runtime-created context menus. - An IDE-facing GUI round (ADRs 0019, 0021–0024) adds two general-purpose widgets — a
GUI.Gridauto-sizing tabular cell model and a caret-anchoredGUI.PopupListwith filtering, navigation, and consume-on-read acceptance — alongsideOutputPanecell/text metrics,FloatingPanel.CenterInParent,Applogical-unit conversion,CodeEditor.InsertAndPlaceCursor, andViper.Text.Charidentifier predicates; ViperIDE adopts them for PTY terminal sizing, logical-unit overlay centering, and identifier-keystroke classification, retiring the hand-rolled equivalents. A new generation dimension onViper.Threads.Scheduler(ScheduleGen/IsDueGen, ADR 0020) tags each debounced entry with the document revision that queued it, so a superseded diagnostics, completion, or hover pass is discarded the moment a newer revision arrives.
Frontends, language servers, and CLI
- BASIC arrays move to inclusive upper bounds with overflow-checked row-major indexing and multidimensional
REDIM/LBOUND/UBOUND, over a case-insensitive symbol table that preserves type suffixes and retain-before-release string/object reassignment; overflow-aware numeric, line-label, andSELECT CASEparsing and numberedDIMfields insideCLASSbodies round out the pass. Zia restores circular and self binds by treating an in-progress bind as a known dependency rather than a fatalV1000. - Zia gains
Map[Integer, T]over the integer-keyedIntMapruntime (string-keyedMapunchanged), enforcing declared key types and routing map literals, indexing, methods, optionals, andfor-in iteration through the right helpers; source files may now omit the module header, defaulting toMain. - The Zia parser and lexer tighten: CR/CRLF normalization, ranged diagnostics for malformed literals and unterminated strings/comments, capped numeric-literal exponents, overflow-rejected fixed-array counts, bounded lookahead, error recovery across a missing enum-variant comma and untyped lambdas, and corrected precedence for shifts, bitwise operators, coalescing, ranges, and ternaries. Semantic checks add namespace-alias and imported-symbol conflict detection, inheritance-aware private/field access, constrained-generic interface checks through base classes, scope-qualified definite initialization, underscore-prefixed unused parameters, and duplicate-local/bodyless-function rejection.
- The Text/Time/IO surface closes documented edge cases (
TextWrapat width ≤ 0, locale-independentJson.Format, embedded-NUL rejection inDateOnly/DateTime). - A new agent-facing CLI:
viper checkis a fast type-check/verify gate (exit 0/1/2),viper evalruns a snippet in one shot with JSON results,viper explain/--print-error-codesread a centraldiag_catalog, and--dump-runtime-api/--dump-opcodesemit registry inventories from the live binary;viper benchgains a default watchdog step budget so a non-terminating IL benchmark reports the budget and skips remaining strategies instead of hanging (--max-steps 0still runs unbounded). The CLI surface itself is made consistent:--help, version, and dry-run output go to stdout with a zero exit; conflicting (--debug-vmwith--debug-adapter), empty, or missing-input flags are rejected;-O3, an inline--max-steps=form, and uniform--name value/--name=valuepackage options are accepted; and every version string is sourced from the build macros rather than literals. - The BASIC/Zia LSP/MCP servers compute UTF-16 ranges, enforce a strict initialize-before-use lifecycle, and route structured diagnostics (code, stage, range, help, fix-its) so did-you-mean corrections reach editor clients; zia-server LSP now also exposes ProjectIndex-backed definition/references/rename plus signature help, workspace symbols, and semantic tokens, while vbasic-server keeps those unsupported capabilities unadvertised until BASIC has an equivalent project-index layer; the CLI rejects mismatched run/build/ABI combinations behind atomic, descriptor-safe outputs.
- Both language servers collapse onto one templated runner with stricter protocol auto-detection — a leading
{selects MCP andContent-Lengthselects LSP, any other first byte is a reported error rather than a silent MCP fallback — both report the real toolchain version, and MCP returnsstructuredContentalongside text behind argument-closed tool schemas. ViperIDE now models wired editor commands separately from external language-server support, so a server-supported feature with no IDE adapter reads as disabled-with-reason rather than missing.
Runtime class-name disambiguation
- No two runtime classes share a leaf name under
Viper.*anymore: each collision is renamed unique —Graphics.Scene→Graphics.SceneGraph,GUI.Clipboard→GUI.ClipboardText,Workspace.Watcher→Workspace.WorkspaceWatcher, theGame.UIwidgets that shadowedGUIones→HudLabel/HudTextInput/HudSlider/HudDropdown/HudTooltip, andSound3D→SpatialAudio3D— with the old fully-qualified names kept working throughRT_ALIASand a leaf-name-collision check in the qualified-surface test locking the invariant. - Duplicate
Viper.ParseandViper.Convertclasses collapse into the canonicalViper.Core.Parse/Viper.Core.Convert, with the publicViper.Parse/Viper.Convertnames preserved as function aliases.
Project loading and packaging
- Convention detection scans real BASIC/Zia tokens, rejects sources that escape the project root through symlinks, and gates install hooks behind explicit manifest opt-ins.
- Package and archive writers stage through same-directory temp files so a failed write leaves no partial artifact, hash assets with SHA-256, and detect a staged binary's OS/architecture from its object header rather than the host; ZIP archives stamp a fixed date by default for byte-identical output.
- The Windows toolchain installer becomes a native dialog wizard (license display, user-vs-machine scope) with a native ARM64 bootstrap; Linux gains a self-extracting, FUSE-less AppImage toolchain package; and macOS packaging adds a styled
.dmgwrapping the.pkg. - Packaged applications (not just the toolchain) now ship as first-class AppImage, RPM, and DMG targets: Debian and RPM builders share one FHS layout, the macOS bundle stages once for both ZIP and DMG, and every artifact is verified after creation. The Linux package builder derives its X11/ALSA/C++-runtime dependencies from the staged binary's ELF64
DT_NEEDEDentries rather than a hand-kept list, the AppImage embeds and validates a payload SHA-256 and extracts through amktempworkspace, and Linux application and toolchain packages can be GPG-signed viadpkg-sig/rpmsign.
Windows and Linux builds
- On Windows, NOMINMAX, extended MSVC atomic shims, a standard-VM bridge that no longer double-releases borrowed strings, and an 8-job MSVC parallelism cap restore the BASIC-VM, installer, ViperIDE, and x86-64 suites, while the D3D11 backend closes its sign-off gaps.
- On Linux, restored OpenGL symbol loading, X11 backing-store sizing, ELF zero-fill/
PT_LOADgrouping, native-import coverage (native-linked programs no longer pullstrtoumaxor quad-precision helpers as dynamic imports), and ARM regression fixes bring the full suite to 1,670 passing; Linux now defaults to the deterministic software backend for reproducible headless and CI renders, with the hardened OpenGL backend explicitly selectable. The Linux audio and graphics adapters serialize ALSA PCM operations, guard process-global X11 state (Xlib threading initialized before the first display open, validated atoms and display-scale parsing), bound clipboard transfers, and honorLC_MESSAGESbeforeLANGfor locale detection.
Tests
~25K new test SLOC. CTest resource locks now serialize tests that share generated codegen or VM-trace artifacts, keeping the suite parallel-safe. A new source-health audit, registered under the audit/tools CTest labels, tracks high-ownership subsystem metrics — runtime API-surface counts, duplication and unsupported-path markers, stub and fuzz-corpus coverage, packaging verification, and TODO debt — against baseline limits, giving reviewers a source-backed ledger.
- 3D rendering, assets, and animation — spot-shadow coordinate and budget-ordering coverage, vegetation sway, versioned navmesh round-trip, FBX/node-animation import, D3D11 upload/readback-helper validation, fail-closed content-loader diagnostics, untrusted-count guard and parser fuzz harnesses, and
Game3D.Diagnostics3Dfallback coverage. - IL, codegen, and cross-engine — IL release-lifetime and alias-analysis precision, VM-vs-bytecode scalar-semantics equivalence, AArch64 register-allocation regressions, duplicate-spill-store elimination, inliner escaped-type and loop-rotation SSA regressions, Game3D script-callback parity across interpreted and native runs, and interpreted
Parallel/Poolcallback dispatch across the tree-walker, bytecode-switch, and bytecode-threaded paths. - Agent CLI and diagnostics — the
agent_clisuite, the diagnostic-code catalog, and structured bridge/MCP/LSP diagnostic and hover coverage. - Runtime, frontends, and GUI — media/pixel decode and a deterministic pixel-hash baseline, BASIC parsing and a B-code-catalog drift guard, Text/Time/IO edge cases, Zia integer-map, lexer/parser-diagnostic, and inherited-initializer coverage,
Pixelstext-drawing and normalized-gradient suites, GUI overlay/font-propagation regressions, ViperIDE activity-bar/multi-root/git-SCM and PTY-terminal probes plus BASIC language-service completion/diagnostics/hover/symbol coverage, and Linux AppImage/RPM/DMG application-package verification alongside the Windows installer-wizard coverage.
Demos and docs tracked the work. Three demos grew: game3d-showcase gained F11 fullscreen, wind-swayed foliage, a render-to-image minimap, spot shadows, a renderer/audio counter HUD, and a procedural fallback forest with expanded tree/terrain/sky scenes; the paint app was rebuilt around a registry-driven tool set — an HSL color picker, menu bar, and select/gradient/curve/polygon/spray/text tools over layers with blend modes and opacity; and crackman gained a vector chomp-and-death animation, pulsing power pellets, score popups, a frightened-state vignette, a looping siren, and a board-clear celebration. On the docs side, the Graphics3D guides, man pages, and codemap now cover spot shadows, backend-fallback observability, streaming, navmesh export, the agent-facing CLI, and the canonical class names, and the Bible reference was refreshed against the current Zia/BASIC/runtime APIs — handwritten appendices give way to docs/basic-reference.md and viper --dump-runtime-api, with a new scripts/audit_bible_examples.py compile/run-checking its runnable code fences. Internally, the runtime's largest source files split into focused per-feature modules, the Zia editor/IntelliSense services moved into zia_editor_services, ViperIDE's orchestration split out of main.zia into focused helper modules under viperide/src with an architecture guide, and socket/entropy/file-dialog logic consolidated into rt_*_platform_{win,posix}.c adapters.