Bend 2 vs. TypeScript: Structural Duck Typing on V8 vs. Affine Dependent Proofs and 16,384 GPU Lanes
Why HigherOrderCO wrote the Bend 2 compiler in TypeScript, how
TypeScript matches up against Bend 2 on 16 Apple M4 Max benchmarks, and
how to embed Bend 2 as a .mjs oracle.
Executive Summary: Bottom Line Up Front
TypeScript and Bend 2 share a deep operational bond.
HigherOrderCO wrote the Bend 2 compiler frontend
(bend2/bend.ts, bend2/comp.ts,
bend2/main.ts) in TypeScript, and Bend 2 compiles natively
to zero-dependency ES modules (bend -o oracle.mjs), C,
Metal, and CUDA (bendlang/bend).
- Choose TypeScript (Node.js, Bun, Deno, Browser) for
web applications, SaaS backends, API orchestration, UI components, and
developer tooling where npm ecosystem breadth, asynchronous I/O, and
structural typing (
interface, union types) drive engineering velocity. - Choose Bend 2 (compiled to native C/GPU via
bend -oor imported as.mjs) when your TypeScript application hits two hard ceilings:- The Compute Ceiling: Across all 16 official Apple
M4 Max benchmarks, multi-core Bend 2 (
PAR-CPU) beats TypeScript (ts_sec) by 3.75x to 65.13x. GPU-accelerated Bend 2 (PAR-GPU) beats TypeScript by up to 297.68x (0.063 svs.18.754 son Conway’s Game of Life) (benchmark dataset). - The Soundness & Verification Ceiling:
TypeScript’s type system is erased at compile time, permits unsound
escapes (
any,as unknown as T), and cannot prove termination or domain equations. Bend 2 enforces an affine dependent type theory (BendTT) that checks 3,200 generic proof instantiations in 0.38 s. It then compiles directly to an ES module that your Vitest or Bun test suite can call in-process as a verified differential reference oracle (benchmark dataset).
- The Compute Ceiling: Across all 16 official Apple
M4 Max benchmarks, multi-core Bend 2 (
1. The Compiler Paradox: Why Bend 2 Is Written in TypeScript
When engineers inspect bendlang/bend,
they often notice a surprising architectural fact: while legacy Bend 1
(HigherOrderCO/HVM) was written in Rust and CUDA, the Bend
2 toolchain consists of roughly 10,700 lines of clean TypeScript (bendlang/bend):
bend2/bend.ts(~3,765 lines): The core parser, AST desugaring pass, dependent evaluator, and affine Usage Wall type checker.bend2/comp.ts(~6,308 lines): The compiler pipeline performing layout synthesis, A-Normal Form (ANF) conversion, share/borrow insertion, the unified C/CUDA/Metal emitter, and the standalone JavaScript emitter (bend -o prog.js).bend2/main.ts(~626 lines): The CLI runner, BendHub package client, and Bun/Node module loader.
HigherOrderCO chose TypeScript for the compiler host because AST
transformations iterate quickly in TypeScript, while the
mathematical soundness of the type theory is mechanized
separately in 20,981 lines of Lean 4
(bend2/bendtt.lean) (bendtt.lean).
Hosting the compiler in TypeScript also allows any Bun or Node.js
project to import .bend files or compile them to
.mjs with zero native toolchain friction (bendlang/bend).
2. Apple M4 Max Benchmark Suite: TypeScript (V8/Bun) vs. Bend 2 (All 16 Workloads)
The official Apple M4 Max benchmark dataset
(/data/bend-ecosystem.json) measures TypeScript
(ts_sec) head-to-head against Bend 2 sequential CPU
(SEQ-CPU), 16-core parallel CPU (PAR-CPU), and
Metal GPU (PAR-GPU) across 16 algorithmic workloads (benchmark dataset):
| Workload | Category | TypeScript (ts_sec) |
Bend SEQ-CPU |
Bend PAR-CPU (16c) |
Bend PAR-GPU (Metal) |
PAR-CPU vs. TS | PAR-GPU vs. TS |
|---|---|---|---|---|---|---|---|
| Conway’s Game of Life | Cellular Automata | 18.754 s |
7.803 s |
0.647 s |
0.063 s |
28.99x faster |
297.68x faster (source) |
| 3D Raytracer | Computer Graphics | 23.039 s |
4.616 s |
0.396 s |
0.151 s |
58.18x faster |
152.58x faster (source) |
| Merkle Tree | Cryptographic Trees | 7.227 s |
4.222 s |
0.422 s |
0.071 s |
17.13x faster |
101.79x faster (source) |
| K-Means Clustering | Machine Learning | 17.455 s |
2.069 s |
0.268 s |
0.191 s |
65.13x faster |
91.39x faster (source) |
| N-Body Physics | Particle Gravity | 5.332 s |
5.758 s |
0.516 s |
0.059 s |
10.33x faster |
90.37x faster (source) |
| Tree Bitonic Sort | Sorting Networks | 33.910 s |
6.043 s |
0.799 s |
0.450 s |
42.44x faster |
75.36x faster (source) |
| Mandelbrot Fractal | Complex Plane | 3.837 s |
4.473 s |
0.395 s |
0.057 s |
9.71x faster |
67.32x faster (source) |
| Procedural Terrain | Simplex Noise | 5.746 s |
2.225 s |
0.197 s |
0.106 s |
29.17x faster |
54.21x faster (source) |
| Tree Matrix Multiply | Quadtree Algebra | 11.379 s |
2.064 s |
0.226 s |
0.231 s |
50.35x faster |
49.26x faster (source) |
| Levenshtein Edit Dist | Dynamic Prog. | 5.290 s |
2.559 s |
0.236 s |
0.144 s |
22.42x faster |
36.74x faster (source) |
| Breadth-First Search | Graph Traversal | 6.534 s |
3.918 s |
0.343 s |
0.207 s |
19.05x faster |
31.57x faster (source) |
| Parallel Radix Sort | Sorting Networks | 6.244 s |
4.083 s |
0.445 s |
0.314 s |
14.03x faster |
19.89x faster (source) |
| Symbolic Regression | Genetic AST Search | 5.924 s |
3.014 s |
0.266 s |
0.529 s |
22.27x faster |
11.20x faster (source) |
| N-Queens Solver | Combinatorics | 6.979 s |
5.406 s |
0.455 s |
0.933 s |
15.34x faster |
7.48x faster (source) |
| Regex Parallel Lexer | Text Processing | 3.543 s |
2.144 s |
0.198 s |
1.075 s |
17.89x faster |
3.30x faster (source) |
| HAMT Hashmap | Data Structures | 0.892 s |
2.741 s |
0.238 s |
0.521 s |
3.75x faster |
1.71x faster (source) |
Why
TypeScript Loses 42x to 65x on Tree Workloads
(tree-bitonic, kmeans, raytrace)
and Wins Sequentially on hashmap
- Heap Allocation & Garbage Collection Pressure on
Recursive Trees: In
tree-bitonic(33.910 sTS vs.0.799 sBendPAR-CPUand0.450 sPAR-GPU), allocating millions of short-lived{ left, right }JavaScript objects floods V8’s nursery heap and triggers stop-the-world garbage collection cycles. Bend 2 represents tree nodes as single 64-bit tagged words ([rfc | tag | aux | loc]) and reclaims consumed affine nodes immediately without GC tracing (benchmark dataset). - Where V8’s JIT Wins Sequentially (
hashmap:0.892 sTS vs.2.741 sBendSEQ-CPU): On a single CPU thread, V8’s hidden classes (Shapes) and inline caches optimizehashmaplookups to0.892 s, beating sequential Bend (2.741 s). However, as soon as Bend 2 runs across 16 CPU cores (0.238 s), it overtakes single-threaded TypeScript by 3.75x without requiringworker_threadsorstructuredCloneserialization (benchmark dataset).
3.
Type System Comparison: TypeScript (tsc) vs. BendTT
(bend --verdict)
TypeScript’s type checker is designed for gradual structural productivity over untyped JavaScript, whereas BendTT is designed for mechanized mathematical proof and lock-free memory layout (bendtt.lean):
| Dimension | TypeScript (tsc) |
Bend 2 (BendTT / bend --verdict) |
|---|---|---|
| Type Discipline | Structural subtyping with gradual escape hatches | Nominal affine dependent type theory (Type : Type with
Usage Wall) (source) |
| Runtime Representation | Erased completely (tsc emits untyped
JS; requires zod at boundaries) |
Drives native codegen: unboxes
U32/F32 and inserts deterministic
heap_free (source) |
| Type Soundness | Intentionally unsound (any,
as, bivariant method parameters, unindexed array
reads) |
Formally sound: 20,981 lines of Lean 4 prove subject reduction and progress (source) |
| Termination Guarantee | None (while (true) and infinite
recursion type-check cleanly) |
Guaranteed via strict syntactic subterm descent on recursive calls (source) |
| Equational Proofs | None (type-level template literals cannot prove runtime value laws) | First-class law claims and inductive proof
blocks checked in 0.38 s (source) |
4.
Production Pattern: Using Bend 2 (bend -o oracle.mjs) as a
Formal Test Engine for TypeScript
One of the highest-leverage ways to adopt Bend 2 in a TypeScript
codebase requires zero changes to your production deployment
runtime. Because bend prog.bend -o oracle.mjs
emits a standalone, zero-dependency ECMAScript module, you can use Bend
2 as a mathematically verified reference oracle inside your
existing Vitest or Bun test suite (bendlang/bend):
┌─────────────────────────────────────────────────────────────────────────┐
│ 1. Formal Specification (`LAWS.bend`) & Proof (`PROOF.bend`) │
│ - Prove conservation, idempotence, and state-machine invariants │
│ - Verified in 0.38 s via `bend PROOF.bend --verdict` │
└────────────────────────────────────┬────────────────────────────────────┘
│
▼ `bend model.bend -o oracle.mjs`
┌─────────────────────────────────────────────────────────────────────────┐
│ 2. Zero-Dependency ES Module (`oracle.mjs`) │
│ - Constructors map to `{$: "Tag", ...}`, `Nat` to native `BigInt` │
└────────────────────────────────────┬────────────────────────────────────┘
│
▼ `import Oracle from "./oracle.mjs"`
┌─────────────────────────────────────────────────────────────────────────┐
│ 3. Vitest / Bun Differential Property Suite (`fast-check`) │
│ - Generates 100,000 adversarial action sequences │
│ - Asserts `expect(runProdTS(state, cmd)).toEqual(Oracle.step(...))` │
└─────────────────────────────────────────────────────────────────────────┘
Real-World Precedents in the Bend 2 Ecosystem
- Order-Independent State Reducers
(
pareto-frontier,oauth2-fsm): Full-stack TypeScript applications (such as multiplayer strategy engines, e-commerce cart pricing engines, or OAuth2 state machines) pair complex TypeScript reducers with aLAWS.bend+PROOF.bendtwin. The Bend 2 twin proves that resource conservation holds for all possible inputs, whilebend -o oracle.mjsruns inside CI withfast-checkto catch any production reducer divergence (OAuth2 FSM package). - Token-Efficient LLM Serialization
(
Dicklesworthstone/toon_bend): Enforces 368 machine-checked laws across both native and JavaScript executor lanes to guarantee byte-for-byte parity with reference TOON implementations (toon_bend).