{"name":"chaotic-showcase.nu","source":"// ============================================================\n// chaotic-showcase.nu — an ADVERSARIAL grammar stress test.\n//\n// Purpose (pre-1.0 grammar lock): the existing example/stdlib corpus is\n// broad but structurally narrow — systems/byte-codec code, cellular\n// automata, emulators, agents. None of it pushes three corners of the\n// language at once. This single file deliberately combines all three to\n// see whether Grammar v2.2 is genuinely complete or whether something\n// needs to change before the v1.0 lock:\n//\n//   (A) FLOAT / VECTOR prefix-arithmetic DENSITY — deeply nested\n//       prefix `+ * - / .` over a Vec3 type. This is the worst case for\n//       fixed prefix arity with no closing token (the open A3 question).\n//   (B) DEEP RECURSIVE ADT + multi-payload PATTERN MATCHING — a symbolic\n//       expression tree (`Expr`) with `*Expr` children, differentiated\n//       and simplified by recursive `??` match. No recursive enum exists\n//       anywhere else in the tree.\n//   (C) HIGHER-ORDER PARSER COMBINATORS — a parser is a closure\n//       `(@ ?*Expr *PState)`; `p_chainl` RETURNS a closure that CAPTURES\n//       two other closures + a scalar. Closures-capturing-closures is the\n//       hardest case for type-dependent capture + escape analysis.\n//\n// The pipeline: parse a formula string into an Expr tree (C), symbolically\n// differentiate + simplify it (B), then evaluate both over Vec3 math (A).\n//\n// RAW POINTERS HERE ARE A DELIBERATE EXCEPTION, NOT HOW NURL CODE IS WRITTEN.\n// Ordinary NURL holds String, Vec, HashMap, Rc and structs of them, which\n// drop themselves when their owner goes out of scope. This file stresses\n// the raw `*T` path on purpose — the expression DAG is linked by `*Expr`\n// pointers — and even so nothing is freed by hand: every node lives in a\n// `Box` the node arena (an owned module global) keeps, and the parser\n// state is a `Box` main holds.\n// ============================================================\n\n$ `stdlib/core/mem.nu`\n$ `stdlib/core/string.nu`\n$ `stdlib/core/box.nu`\n$ `stdlib/core/vec.nu`\n$ `stdlib/std/float.nu`\n\n// ── Axis A: Vec3 + dense prefix float arithmetic ────────────────────\n\n: Vec3 { f x f y f z }\n\n@ v3 f x f y f z → Vec3 { ^ @ Vec3 { x y z } }\n\n@ v3_add Vec3 a Vec3 b → Vec3 {\n    ^ @ Vec3 { + . a x . b x + . a y . b y + . a z . b z }\n}\n\n@ v3_scale Vec3 a f s → Vec3 {\n    ^ @ Vec3 { * . a x s * . a y s * . a z s }\n}\n\n@ v3_dot Vec3 a Vec3 b → f {\n    // + (+ (ax*bx) (ay*by)) (az*bz) — fully nested, no grouping tokens.\n    ^ + + * . a x . b x * . a y . b y * . a z . b z\n}\n\n@ v3_cross Vec3 a Vec3 b → Vec3 {\n    ^ @ Vec3 {\n        - * . a y . b z * . a z . b y\n        - * . a z . b x * . a x . b z\n        - * . a x . b y * . a y . b x\n    }\n}\n\n@ v3_len Vec3 a → f { ^ ( float_sqrt ( v3_dot a a ) ) }\n\n@ v3_norm Vec3 a → Vec3 { : f l ( v3_len a ) ^ ( v3_scale a / 1.0 l ) }\n\n// ── Axis B: a recursive symbolic-expression ADT ─────────────────────\n//\n// Children are boxed as `*Expr` (raw pointer payloads) on purpose — the\n// raw-memory exception described at the top — so the trees are freed by\n// hand at the end of main. This is the only recursive enum in the codebase.\n\n: | Expr {\n    Num f\n    Var\n    Add * Expr * Expr\n    Mul * Expr * Expr\n    Neg * Expr\n    Sin * Expr\n    Cos * Expr\n}\n\n// Every node of every tree, owned here and released when the program\n// ends: the trees share subtrees (they are DAGs), so no tree owns its\n// nodes.\n: ~ ( Vec ( Box Expr ) ) g_nodes 0\n: ~ b g_nodes_made F\n\nunsafe @ ebox Expr e → *Expr {\n    ? ! g_nodes_made { = g_nodes ( vec_new [( Box Expr )] ) = g_nodes_made T } {}\n    : ( Box Expr ) b ( box_new [Expr] e )\n    : *Expr p # *Expr ( box_ptr [Expr] b )\n    ( vec_push [( Box Expr )] g_nodes b )\n    ^ p\n}\n\nunsafe @ e_num f x → *Expr { ^ ( ebox @ Expr { Num x } ) }\n\nunsafe @ e_var → *Expr { ^ ( ebox @ Expr { Var } ) }\n\nunsafe @ e_add * Expr a * Expr b → *Expr { ^ ( ebox @ Expr { Add a b } ) }\n\nunsafe @ e_mul * Expr a * Expr b → *Expr { ^ ( ebox @ Expr { Mul a b } ) }\n\nunsafe @ e_neg * Expr a → *Expr { ^ ( ebox @ Expr { Neg a } ) }\n\nunsafe @ e_sin * Expr a → *Expr { ^ ( ebox @ Expr { Sin a } ) }\n\nunsafe @ e_cos * Expr a → *Expr { ^ ( ebox @ Expr { Cos a } ) }\n\n// Evaluate the tree at x = xv. Recursive match with 2-payload binding.\nunsafe @ e_eval * Expr p f xv → f {\n    : Expr e . p 0\n    ?? e {\n        Num c → c\n        Var → xv\n        Add a b → + ( e_eval a xv ) ( e_eval b xv )\n        Mul a b → * ( e_eval a xv ) ( e_eval b xv )\n        Neg a → - 0.0 ( e_eval a xv )\n        Sin a → ( float_sin ( e_eval a xv ) )\n        Cos a → ( float_cos ( e_eval a xv ) )\n    }\n}\n\n// Symbolic differentiation d/dx — the autodiff core. Each arm rebuilds a\n// fresh subtree from the recursive results.\nunsafe @ e_diff * Expr p → *Expr {\n    : Expr e . p 0\n    ?? e {\n        Num c → ( e_num 0.0 )\n        Var → ( e_num 1.0 )\n        Add a b → ( e_add ( e_diff a ) ( e_diff b ) )\n        Mul a b → ( e_add ( e_mul ( e_diff a ) b ) ( e_mul a ( e_diff b ) ) )\n        Neg a → ( e_neg ( e_diff a ) )\n        Sin a → ( e_mul ( e_cos a ) ( e_diff a ) )\n        Cos a → ( e_neg ( e_mul ( e_sin a ) ( e_diff a ) ) )\n    }\n}\n\n// Constant-folding + identity simplification. Nested `??` inside arms —\n// pattern-matching depth stress.\nunsafe @ e_simplify * Expr p → *Expr {\n    : Expr e . p 0\n    ?? e {\n        Add a b → {\n            : *Expr sa ( e_simplify a )\n            : *Expr sb ( e_simplify b )\n            : Expr ea . sa 0\n            : Expr eb . sb 0\n            ?? ea {\n                Num x → ?? eb {\n                    Num y → ( e_num + x y )\n                    _ → ( e_add sa sb )\n                }\n                _ → ( e_add sa sb )\n            }\n        }\n        Mul a b → {\n            : *Expr sa ( e_simplify a )\n            : *Expr sb ( e_simplify b )\n            : Expr ea . sa 0\n            : Expr eb . sb 0\n            ?? ea {\n                Num x → ?? eb {\n                    Num y → ( e_num * x y )\n                    _ → ( e_mul sa sb )\n                }\n                _ → ( e_mul sa sb )\n            }\n        }\n        _ → ( ebox e )\n    }\n}\n\n// ── Axis C: parser combinators (closures returning closures) ────────\n\n: PState { s text i len i pos }\n\nunsafe @ ps_new s input → ( Box PState ) {\n    ^ ( box_new [PState] @ PState { input ( nurl_str_len input ) 0 } )\n}\n\nunsafe @ p_peek * PState ps i ch → b {\n    ? >= . ps pos . ps len { ^ F } {}\n    ^ == ( nurl_str_get . ps text . ps pos ) ch\n}\n\nunsafe @ p_advance * PState ps → v { = . ps pos + . ps pos 1 }\n\nunsafe @ p_skip_ws * PState ps → v { ~ ( p_peek ps 32 ) { ( p_advance ps ) } }\n\nunsafe @ p_digit * PState ps → b {\n    ? >= . ps pos . ps len { ^ F } {}\n    : i c ( nurl_str_get . ps text . ps pos )\n    ^ & >= c 48 <= c 57\n}\n\nunsafe @ p_number * PState ps → ?*Expr {\n    : ~ f val 0.0\n    : ~ i any 0\n    ~ ( p_digit ps ) {\n        : i d - ( nurl_str_get . ps text . ps pos ) 48\n        = val + * val 10.0 # f d\n        ( p_advance ps )\n        = any 1\n    }\n    ? == any 0 { ^ @ ?*Expr { F } } {}\n    ? ( p_peek ps 46 ) {\n        ( p_advance ps )\n        : ~ f scale 0.1\n        ~ ( p_digit ps ) {\n            : i d - ( nurl_str_get . ps text . ps pos ) 48\n            = val + val * scale # f d\n            = scale * scale 0.1\n            ( p_advance ps )\n        }\n    } {}\n    ^ @ ?*Expr { T ( e_num val ) }\n}\n\n// atom := 'x' | number | '(' expr ')' | '-' atom | 's' atom | 'c' atom\nunsafe @ p_atom * PState ps → ?*Expr {\n    ( p_skip_ws ps )\n    ? ( p_peek ps 120 ) { ( p_advance ps ) ^ @ ?*Expr { T ( e_var ) } } {}\n    ? ( p_peek ps 40 ) {\n        ( p_advance ps )\n        : ?*Expr inner ( p_expr ps )\n        ( p_skip_ws ps )\n        ? ( p_peek ps 41 ) { ( p_advance ps ) } {}\n        ^ inner\n    } {}\n    ? ( p_peek ps 45 ) {\n        ( p_advance ps )\n        : ?*Expr a ( p_atom ps )\n        ^ ?? a { T e → @ ?*Expr { T ( e_neg e ) } F → @ ?*Expr { F } }\n    } {}\n    ? ( p_peek ps 115 ) {\n        ( p_advance ps )\n        : ?*Expr a ( p_atom ps )\n        ^ ?? a { T e → @ ?*Expr { T ( e_sin e ) } F → @ ?*Expr { F } }\n    } {}\n    ? ( p_peek ps 99 ) {\n        ( p_advance ps )\n        : ?*Expr a ( p_atom ps )\n        ^ ?? a { T e → @ ?*Expr { T ( e_cos e ) } F → @ ?*Expr { F } }\n    } {}\n    ^ ( p_number ps )\n}\n\n// The combinator: left-associative chain of `sub` separated by `opch`,\n// folded with `build`. RETURNS a closure that CAPTURES sub, opch, build.\nunsafe @ p_chainl ( @ ?*Expr * PState ) sub i opch ( @ *Expr * Expr * Expr ) build → ( @ ?*Expr * PState ) {\n    ^ \\ * PState ps → ?*Expr {\n        : ?*Expr first ( sub ps )\n        ?? first {\n            F → @ ?*Expr { F }\n            T lhs → {\n                : ~ * Expr acc lhs\n                ( p_skip_ws ps )\n                ~ ( p_peek ps opch ) {\n                    ( p_advance ps )\n                    : ?*Expr r ( sub ps )\n                    ?? r { T rhs → { = acc ( build acc rhs ) } F → {} }\n                    ( p_skip_ws ps )\n                }\n                @ ?*Expr { T acc }\n            }\n        }\n    }\n}\n\n// term := atom (('*') atom)*   — built via the combinator.\nunsafe @ p_term * PState ps → ?*Expr {\n    : ( @ ?*Expr * PState ) mulp ( p_chainl\n    \\ * PState s → ?*Expr { ( p_atom s ) }\n    42\n    \\ * Expr a * Expr b → *Expr { ( e_mul a b ) } )\n    ^ ( mulp ps )\n}\n\n// expr := term (('+') term)*   — also via the combinator.\nunsafe @ p_expr * PState ps → ?*Expr {\n    : ( @ ?*Expr * PState ) addp ( p_chainl\n    \\ * PState s → ?*Expr { ( p_term s ) }\n    43\n    \\ * Expr a * Expr b → *Expr { ( e_add a b ) } )\n    ^ ( addp ps )\n}\n\n@ pf f x → v { ( nurl_print ( float_to_string x ) ) }\n\nunsafe @ main → i {\n    // ── Axis A: dense vector math ──────────────────────────────\n    : Vec3 a ( v3 1.0 2.0 3.0 )\n    : Vec3 b ( v3 4.0 5.0 6.0 )\n    ( nurl_print `dot=` ) ( pf ( v3_dot a b ) ) ( nurl_print `\\n` )\n    ( nurl_print `len=` ) ( pf ( v3_len a ) ) ( nurl_print `\\n` )\n    : Vec3 c ( v3_cross a b )\n    ( nurl_print `cross=` ) ( pf . c x ) ( nurl_print ` ` ) ( pf . c y ) ( nurl_print ` ` ) ( pf . c z ) ( nurl_print `\\n` )\n    : Vec3 d ( v3_add a ( v3_scale b 2.0 ) )\n    ( nurl_print `a+2b.x=` ) ( pf . d x ) ( nurl_print `\\n` )\n\n    // ── Axis C: parse a formula ───────────────────────────────\n    : s formula `x*x + 3.0*x + s(x)`\n    : ( Box PState ) psb ( ps_new formula )\n    : *PState ps # *PState ( box_ptr [PState] psb )\n    : ?*Expr parsed ( p_expr ps )\n    ?? parsed {\n        F → { ( nurl_print `parse failed\\n` ) ^ 1 }\n        T tree → {\n            // ── Axis B: differentiate + simplify + eval ───────\n            : *Expr deriv ( e_diff tree )\n            : *Expr dtree ( e_simplify deriv )\n            ( nurl_print `f(2)=` ) ( pf ( e_eval tree 2.0 ) ) ( nurl_print `\\n` )\n            ( nurl_print `f'(2)=` ) ( pf ( e_eval dtree 2.0 ) ) ( nurl_print `\\n` )\n            ( nurl_print `f(0)=` ) ( pf ( e_eval tree 0.0 ) ) ( nurl_print `\\n` )\n        }\n    }\n    ^ 0\n}\n","bytes":11347}