Files
hakorune/docs/private/roadmap/phases/phase-20.27/CLAUDE_SPEC.md

5.6 KiB
Raw Blame History

Phase20.27 — Claude Spec (Core Full BringUp)

Scope

  • Complete Core mir_call semantics for ModuleFunction, Method, Constructor. Closure is explicitly unsupported in v0 (FailFast with a stable tag).
  • Implement minimal but consistent Box semantics for Array/Map/String in Core with positive/negative coverage and stable error tags.
  • Strengthen GateC (JSON→Core) parity: file/pipe and plugins ON/OFF produce the same output and exitcode mapping.
  • Converge hakorunevm handlers to delegate to Core where 1:1 parity exists.

Out of Scope (this phase)

  • Exceptions/async (try/catch/throw, async/future)
  • AOT/LLVM integration for Core results
  • Performance optimization beyond simple bounds checks

Entry Points (code)

  • Core: lang/src/vm/core/{value.hako, state.hako, extern_iface.hako, json_v0_reader.hako, dispatcher.hako}
  • Core ops: lang/src/vm/core/ops/{const,binop,compare,branch,jump,phi,ret,mir_call}.hako
  • Engines: lang/src/vm/engines/{mini/engine.hako, hakorune/engine.hako} (thin wrappers)
  • Redelegation stubs: lang/src/vm/hakorune-vm/* (delegate to Core where parity exists)

mir_call — Required Semantics (v0)

  • Callee types accepted: Global, Extern, ModuleFunction, Method, Constructor.
    • Closure is rejected with: [core/mir_call/closure_unsupported].
  • Normalization rules (apply inside Core mir_call):
    • Method(receiver, name, args) → normalized as ModuleFunction or Extern lookup using canonical name; pass receiver as first argument.
    • Support alias mapping for common names: size|length|len, indexOf|lastIndexOf, substring|substr, charAt|at.
    • Always FailFast for unknown method names with: [core/mir_call/method_unsupported].
  • Constructor
    • ArrayBox: allocate metadata (size=0) and an empty elements vector; return a BoxRef.
    • MapBox: allocate empty map structure; return a BoxRef.
    • StringBox: constructor unsupported (strings born via literals) → [core/mir_call/constructor_unsupported].

Box Semantics (Core) — Minimal, Deterministic

  • Array
    • Positive: size/0, push/1, pop/0 (empty → null), get/1, set/2, clear/0.
    • Negative: bounds and type errors must FailFast with stable tags:
      • OOB get: [core/array/oob_get]
      • OOB set: [core/array/oob_set]
      • Bad index type: [core/array/index_type]
    • Notes: elements are stored as VMValue; do not autocoerce types.
  • Map
    • Positive: size/0, has/1, get/1 (missing → null), set/2 (insert/overwrite), delete/1, keys/0, values/0.
    • Negative: unsupported iterator forms or bad key/value types FailFast:
      • Missing key for delete/get: returns null (not an error)
      • Bad key type (nonstring in v0): [core/map/key_type]
      • Bad value type (reserved forms): [core/map/value_type] (keep rare; prefer VMValue acceptance)
  • String
    • Positive: length/0, indexOf/1, lastIndexOf/1, substring/2, charAt/1, replace/2.
    • Negative: outofbounds ranges FailFast with [core/string/bounds].
    • Notes: indexOf returns -1 when not found (no error).

GateC (JSON→Core) Parity

  • Ensure file and pipe modes have identical behavior when NYASH_GATE_C_CORE=1.
  • Exit code mapping: integer return → rc=(value & 0xFF); noninteger/null/void → rc=0.
  • Plugins toggle: both HAKO_GATE_C_ENABLE_PLUGINS=0/1 must keep parity; when plugins are disabled, collection births/methods FailFast with [boxes/{array|map}_unavailable].

Redelegation (hakorunevm → Core)

  • For handlers that match Core ops 1:1 (const/binop/compare/branch/jump/phi/ret and supported mir_call forms), delegate to Core functions to avoid drift.
  • Leave TODO on handlers that intentionally diverge or are not yet covered by Core.

Stable Tags (nonexhaustive)

  • Core mir_call
    • [core/mir_call/closure_unsupported]
    • [core/mir_call/method_unsupported]
    • [core/mir_call/constructor_unsupported]
  • Array
    • [core/array/oob_get], [core/array/oob_set], [core/array/index_type]
  • Map
    • [core/map/key_type], [core/map/value_type]
  • String
    • [core/string/bounds]
  • Collections unavailable (plugins OFF)
    • [boxes/array_unavailable], [boxes/map_unavailable]

Testing (Smokes — optin quick/core)

  • Enable: SMOKES_ENABLE_CORE_CANARY=1
  • Positive canaries:
    • emit→nyvm(Core): return 7, binop, if
    • GateC(Core): file/pipe return/binop/if
    • Array: push/push/size → 2, set/get, clear/size → 0
    • Map: set/get/has/delete/size, keys/values shape
    • String: length/indexOf/lastIndexOf/substring/charAt/replace
  • Negative canaries:
    • Array: oob get/set, index type error, pop on empty → null
    • Map: key_type error (nonstring key), delete missing (no error, size unchanged)
    • String: substring bounds error
  • GateC parity:
    • file vs pipe, plugins ON/OFF; assert identical output and rc.

Environment (dev/test helpers)

  • HAKO_CORE_MAX_ITERS — Core dispatcher loop cap (default 10000)
  • HAKO_GATE_C_CORE=1 — GateC direct Core path
  • HAKO_GATE_C_ENABLE_PLUGINS — GateC with plugins ON (optin)
  • HAKO_ARRAY_FORCE_HOST=1, HAKO_ARRAY_PLUGIN_BIRTH=1 — collection migration gates

Acceptance Criteria

  • All core canaries (positive/negative) pass under quick (optin), both emit→nyvm(Core) and GateC(Core).
  • Parity tests (file/pipe × plugins ON/OFF) pass with symmetric rc.
  • hakorunevm delegates 1:1 handlers to Core where available; remaining differences are documented.

Notes for Implementation

  • Keep diffs minimal; avoid new dependencies.
  • FailFast only: no silent fallbacks. Surface stable tags or deterministic values (like null for missing map keys).
  • Document any newly introduced tags in docs and canaries.