3.6 KiB
3.6 KiB
Operator Boxes (MVP) — Stringify
Overview
- Goal: Extend “Everything is Box” to implicit operations by modeling them as explicit, observable Boxes.
- Scope (MVP): Stringify operation used by print paths.
- Status: Dev‑only; opt‑in via env flag; backward compatible.
Quick Run
- JSON only (Roundtrip + Nested):
./tools/opbox-json.sh - Quick suite (dev, light preflight):
./tools/opbox-quick.sh
Flags
- NYASH_OPERATOR_BOX_STRINGIFY=1 Enable StringifyOperator on print paths
- NYASH_OPERATOR_BOX_COMPARE=1 Enable CompareOperator (observer) on compare ops
- NYASH_OPERATOR_BOX_ADD=1 Enable AddOperator (observer) on Add binop
- NYASH_OPERATOR_BOX_ALL=1 Enable auto-prelude injection for all operator modules (runtime convenience)
- NYASH_USING_AST=1 Required to AST‑merge the operator modules automatically
Parser tokens
- Tokenizer accepts
~,<<,>>in non‑strict mode (default). In strict_12_7, shift tokens are gated. - Unary
~xparses toUnaryOp(BitNot, x); binary<< >> & | ^parse via existing bit/shift rules.
Behavior
- Stringify: When the flag is ON, VM attempts to call
StringifyOperator.apply/1before falling back to the legacyto_string(). - Compare (observer): When the flag is ON, VM calls
CompareOperator.apply/3with(op, a, b)for observability, then performs normal compare semantics (operator result is ignored for now). - Add (observer): When the flag is ON, VM calls
AddOperator.apply/2with(a, b)for observability, then performs normal add semantics (operator result is ignored for now). - The operators live under
apps/lib/std/operators/and are auto‑injected into the AST prelude (dev only) so functions are materialized without changing user sources.
Operator definitions (MVP)
- Stringify —
apps/lib/std/operators/stringify.nyash- If
valuehasstringify(), call it; else return"" + value.
- If
- Compare —
apps/lib/std/operators/compare.nyashapply(op, a, b); observer‑only for now, returnstrueand the VM performs the real compare.
- Add —
apps/lib/std/operators/add.nyashapply(a, b); observer‑only for now, VM performs the real addition.
- Sub/Mul/Div/Mod —
apps/lib/std/operators/{sub,mul,div,mod}.nyashapply(a, b); direct evaluation.
- Bitwise/Shifts —
apps/lib/std/operators/{bitand,bitor,bitxor,shl,shr}.nyashapply(a, b); direct evaluation on integers.
- Unary —
apps/lib/std/operators/{neg,not,bitnot}.nyashapply(a); negate / logical-not / bitwise-not.
Design Notes
- Backward compatible: existing programs run unchanged with the flag OFF (default).
- Observability: with
NYASH_BOX_TRACE=1, calls to the operator are visible as JSON lines (stderr), aiding diagnostics. - Rollback is trivial: remove the resolver injection and the two VM hooks; delete the operator file.
Future Work (Optional / Later)
- Elevate Compare/Add from observer to authoritative semantics behind stricter flags, once parity is verified.
- Unify lowering (sugar → operator boxes) after VM and Builder parity are green.
- Add per-operator adopt flags if needed for runtime switching; current builder call lowering already routes via operator boxes.
Builder lowering (centralized)
- Master flag:
NYASH_BUILDER_OPERATOR_BOX_ALL_CALL=1lowers all arithmetic/compare/unary ops to*Operator.applycalls in one place (src/mir/builder/ops.rs). - Reentrancy guard: when building inside
*Operator.apply, lowering is skipped to avoid recursion; falls back to direct MIR op. - Metadata: builder annotates result types (Integer/String/Bool) to preserve
value_typesso downstream analysis remains stable.