Programming Language

Nocter

A self-contained systems language built around simplicity, encapsulation, and foolproof design.

/development/reviews/v0.22.0-phase-2.md

v0.22.0 Phase 2 Review

Scope

Phase 2 implements the owning JSON Value contract and strict whole-text parsing. It includes the public enum, one explicit-stack parser, decoded duplicate-name rejection, current and recoverable allocation policies, native execution coverage, editor-surface coverage, and one general recovery inference correction exposed during qualification.

Generation remains Phase 3 work. This phase adds no JSON primitive, compiler-known declaration, floating-point conversion, token array, source tree, fixed nesting limit, or recursive parser call.

Ownership Model

One ParserState owns the active grammatical state. One Vec<Continuation> owns parent containers that are waiting for exactly one child:

  • an array continuation owns its partial Vec<Value>;
  • an object continuation owns its partial Map<String, Value> and one decoded pending name;
  • a complete child is owned by ParserState.complete until it moves into one continuation or the root result.

Container separator states remain active states and never enter the continuation stack. The model therefore cannot represent a parent that both awaits a child and awaits a separator. Every failure returns while ordinary move-only destruction owns the active state and continuation stack; there is no initialized-slot bitmap, cleanup count, parallel owner table, or caller cleanup protocol.

Parse Authority

Cursor remains the only source byte-offset authority. Number and string parsing consume it directly. The container parser reads one grammatical obligation at a time and retains no token sequence or source range after a decision. Number keeps only its exact validated spelling and normalized numeric summary; Value owns only decoded semantic data.

The parser loop never calls itself. Starting a container changes active state, and completing a child pops one continuation. Input nesting is therefore represented by allocator-owned Vec storage, not native parser stack depth. The code contains no depth constant or count-based rejection.

Duplicate and Collection Boundary

Object names are fully decoded before equality. The parser calls only Map's public semantic contains_key and try_insert contracts. It rejects a decoded duplicate before insertion and does not inspect replacement behavior, hashes, seeds, buckets, capacity policy, or dense storage.

Arrays and the continuation stack use Vec's public construction and mutation contracts. Partial containers move through parser state rather than exposing their storage to JSON.

Allocation and Failure

The recoverable core receives one TryAllocator. It routes the continuation stack, arrays, Maps, Number text, decoded strings, object names, and dynamic error detail through that allocator. Ordinary parse supplies the current-context adapter and aborts only the private allocation case; try_parse returns allocation failure. Both return input and duplicate failures normally.

Native tests return both a successful explicitly page-allocated result and an allocated input error from inside a different current region. This verifies that empty collection state, later growth, and error detail do not silently bind to the ambient context.

General Checker Correction

Qualification initially rejected Vec<Value>.try_with_capacity(...) catch and Map<String, Value>.try_with_capacity(...) catch. The recursion was not the cause. Calls whose type parameter appeared only in a fallible result received no expected payload context from a recovery expression. Propagation expressions already used the correct call-context contract.

The checker now routes direct recovery operands through the same outcome-aware call entry with an OutcomePayload context. Dedicated tests cover both catch and otherwise. The correction is general and does not name JSON, Value, Vec, Map, an allocator, or an error code. No wrapper or explicit-type workaround remains in the standard library.

Qualification

  • native standard tests cover all six root variants, whitespace, exact Number projection, nested arrays and objects, decoded names, escaped duplicates, malformed separators and boundaries, BOM rejection, deep input, partial-state failure cleanup, recoverable growth, and allocator affinity;
  • checking tests cover generic result inference under both recovery forms;
  • language-server tests cover Value hover, parse hover, variant completion during syntax recovery, and absence of private parser state;
  • discovery enforces the exact new json -> map and json -> vec dependency edges and checks every private implementation function has a semantic reference;
  • the complete authored standard unit compiles and executes its Phase 2 tests natively.

Result

Phase 2 is complete. Review found and removed the recovery-inference defect rather than adding a JSON-local constructor wrapper or ambient-allocation fallback. The remaining JSON work begins at the generator boundary defined for Phase 3.