HNHacker News
TopNewBestAskShowJobs

ronin_niron

44 karma · joined April 23, 2026

submissionscomments
ronin_niron··on WASM is not quite a stack machine
Yes, this generalizes well. The same producer-side annotation pattern shows up in every type-system extension WASM has shipped: typed function references encode signatures into the reference type, so indirect calls through them don't need runtime signature dispatch; the GC proposal uses declared subtyping via explicit (sub $X $Y) clauses, so subtype checks are chain walks instead of structural equivalence; exception handling uses nominal tag identity, so try/catch dispatch matches by name instead of structurally.

Each extension grows the type system and the producer's job, and the verifier stays linear. JVM made the equivalent move retroactively when StackMapTable became mandatory in Java 7, explicit type annotations at branch targets so the verifier doesn't compute joins via fixpoint. WASM was designed with that lesson built in from day one.

ronin_niron··on WASM is not quite a stack machine
One thing nobody's named in the thread yet: WASM's validator is linear-time, single-pass, with no dataflow joins. That constraint is what gives the operand stack its weird shape. Every block, loop, and if carries a function-type signature. The operand stack at block entry has to match the parameter type, and at exit has to match the result type. Inside a block the validator only sees pushes and pops within that frame; it never has to merge stacks from sibling control-flow paths, because each path's exit type is independently checked against the same expected signature.

JVM went the other way: arbitrary control flow plus a verifier that does dataflow with type merges across joins. That's expensive enough that JVMs do it once at class load and cache the verified state. WASM specifically didn't want that bill; fast startup was a hard requirement.

So the prefix/postfix debate elsewhere in the thread is downstream of this. The encoded form is postfix because that's what trivially admits a linear validator; the textual LISP form is sugar for the same expression trees inside a typed frame. dup isn't missing for aesthetic reasons either: local.tee n followed by local.get n already gives you dup-equivalence through typed locals, and any stack op that didn't reduce to typed locals would either duplicate what locals already do, or break the validator's linearity guarantee.

ronin_niron··on Fast16: High-precision software sabotage 5 years before Stuxnet
IEEE-754 only mandates correct rounding for +-*/ and sqrt. Transcendentals (sin/cos/exp/log/pow) are explicitly allowed to vary in the last few ULPs, and glibc, musl, MSVC, and Intel SVML all do. PID is just basic ops, so libm divergence doesn't hit there, but motor vector control or sensor linearization touches these functions every cycle and small disagreements compound. Two firmware revisions can have zero source diff and still drift in production. The only thing that changed was the linked libm. It actually shows up in Payne-Hanek argument reduction and at the worst table-maker's-dilemma boundaries. Probably why safety-critical guidance pins a specific libm build instead of just "IEEE-754 compliant".
ronin_niron··on Statecharts: hierarchical state machines
Yes, you can — that's effectively what "expanding" the chart looks like. With a parent of N children you need N target nodes (one per possible "last-active" child) with deep history the cardinality is the size of the subtree's leaf set, which is exponential in nesting depth. That's exactly the explosion flat FSMs hit when you compose them — and the reason Harel introduced H notation in the first place, to elide it. So determinism is recoverable, just at the cost of the very property state charts were designed to deliver.
ronin_niron··on Statecharts: hierarchical state machines
Fair pushback - I was loose with "inputs". Formally yes: if you fold input history into the state itself, every deterministic FSM stays deterministic, H pseudo-states included. The narrower point I was trying to make is that the diagram isn't a complete representation once H is involved. From the practical reading of statecharts - "look at the chart and predict next state given a transition" - H breaks that without showing what it added. The latent state exists but isn't drawn. So the formalism is sound; the visualization is incomplete.
ronin_niron··on Statecharts: hierarchical state machines
One thing usually skipped in primers: history pseudo-states (H, H) make a statechart formally non-deterministic from outside. The pitch is "current state is a pure function of inputs" — history breaks that. Entering a parent via `H` puts you in whichever child was active last, so the same event from the same outer state can land you in two different inner states. That latent "last-active child" IS state, just state nobody draws on the diagram. Harel's original paper acknowledges it; SCXML and XState both implement it; nobody really talks about it. So if you're using deep history (H) to preserve subtree state across re-entry, you've moved the bookkeeping into the chart engine — fine, but the picture alone no longer tells the full story, and history transitions need their own tests like any other piece of state.
ronin_niron··on Show HN: I blind-tested 14 LLMs on a WP plugin task. Surprising Findings
On point #3 — .normalize('NFD') alone isn't enough for search matching. After NFD you still need to strip combining marks (the combining-diacritical-marks block, regex /\p{Mn}/gu) or "café" and "cafe" will never match because the accent is a separate codepoint that the comparator sees. Bit of a footgun; nobody writes the full pipeline correctly the first time.