NishiLang vs the field

Measured rankings against C, Rust, Go, JavaScript and Python · the architectural choices that produce each number · where we are state of the art, where we are not, and the plan to get there. Every number below was produced by running code on this machine on 2026-07-28, against the compiler that actually ships (nx_cc sha256 d25c7a3a…, 542,168 bytes, self-hosted). Every performance arm must print the identical checksum 31447040000 or its row is invalid — the work, not the timer, is what gets compared.

The honest headline: overall grade 717‰ (safety 0.40 + performance 0.35 + toolchain 0.25, weights stated so anyone can recompute). The grade fell from 725‰ when slices landed, because adding a measured-slow axis lowers a truthful ruler. Null-safety and data-race detection are unmeasured, so they are excluded rather than credited. A scoreboard that only ever goes up is not measuring.

Ranking 1 — what happens on an out-of-bounds write

One program per language: write through a runtime index six slots into a four-slot array, then read it back. This is CWE-787, the most consequential software weakness class in the world. What each language does is its real safety ranking:

languagebehaviour on a[6] of [4]i64verdict
NishiLang (checked [N]T/[]T)refuses, names the rule, suggests the remedy, exits 71REFUSED, with a diagnostic
Rust 1.96 -Opanics, exits 101REFUSED
Go 1.22panics: index out of range, exits 2REFUSED
Python 3.12IndexErrorREFUSED (interpreted)
JavaScript (node 22, V8)write “succeeds” — the array silently grows to length 7ABSORBED — memory-safe but the bug is masked, not caught
C, gcc 13.3 -O2write and read both “succeed”, value 4242ALLOWED — silent memory corruption
C, clang 18 -O2write and read both “succeed”, value 4242ALLOWED — silent memory corruption

NishiLang sits in the refusing class with Rust and Go — and is the only compiled entry whose refusal message tells the operator what rule fired and what to do about it. This guarantee reaches stack arrays ([N]T), module statics, and heap memory through the slice type []T, a pointer that carries its length. Raw *T indexing remains available and unchecked by explicit choice — that cell is a deliberate, tested gate cell, not an oversight.

Ranking 2 — what the guarantee costs

The identical hot loop in every language: sum a 1,024-element i64 array 20,000 times (20.48M accesses), best of 3:

armtimevs Cwhat the number contains
C, gcc -O2 (unchecked)2,065 µs1.00×the no-guarantee baseline: 40 years of optimizer
Go 1.22 (checked, elided)4,146 µs2.01×bounds checks exist but its compiler proves them away in this loop
NishiLang (unchecked *T)4,271 µs2.07×our pure codegen gap — no checks in play
Rust 1.96 -O (checked [])4,346 µs2.10×LLVM + checks it could not fully elide here
NishiLang (checked [N]T)8,484 µs4.11×our codegen gap × our unelided checks — both named below
JavaScript (node 22, V8 JIT)12,487 µs6.05×dynamic array, JIT-compiled
Python 3.12785,415 µs380×the interpreter class, honestly measured
Read the middle three rows together — they are the finding. Go-with-elided-checks, NishiLang-unchecked, and Rust-checked all land within 5% of each other at ~2× C. That says two separate things about us: our raw codegen is already at the checked-language tier, and our missing rung is not “faster checks” — it is proving checks unnecessary, which Go demonstrates is worth an entire 2× on this loop. Both of our gaps are root-caused in the plan below, not guessed at.

The architectures, and why each produces its numbers

C — trust the programmer, optimize the contract

gcc and clang assume the program never breaks the rules; undefined behaviour is the license for four decades of optimization (SSA form, register allocation, vectorization). That is why C wins the cost table and loses the safety table by the same design decision. The 4242 in the safety row is the world's CVE backlog in one integer.

Rust — move the checking to compile time, buy the backend

Ownership and borrows are proven at compile time; what cannot be proven (like our runtime index) stays a runtime check inside an LLVM-optimized loop. The architecture is powerful and heavy: the toolchain is tens of millions of lines you did not write, compile times are long, and the ecosystem model (crates) makes the supply chain part of your trusted computing base.

Go — keep the checks, teach the compiler to delete them

Go ships a garbage-collected runtime and mandatory bounds checks — then its compiler's bounds-check elimination proves, per loop, when the index cannot escape the array and removes the check entirely. Its 2.01× here is the existence proof for our elision rung: same guarantee as our 4.11× row, half the price, via a compiler theorem rather than a faster branch.

JavaScript and Python — the VM classes

V8 JIT-compiles hot dynamic code to within ~6× of C, and its arrays absorb out-of-range writes instead of refusing them — memory-safe, but the defect travels onward as data. CPython interprets: perfectly serviceable glue at 380×, never a codec. These architectures trade peak performance and strictness for dynamism.

NishiLang — sovereign from byte 0, safety as a runtime theorem, gates as the discipline

The entire pipeline is ours and self-hosted: a 15,413-line core (parser 5,451 · IR 1,581 · optimizer 3,846 · register allocator 1,110 · x86-64 backend 3,425) compiles NishiLang to its own assembly, assembled by our own assembler into ELF binaries that speak raw syscalls — no libc, no LLVM, no external linker, nothing downloaded. The same front end emits a WebAssembly lane. Safety is spatial-first: types that know their length ([N]T, []T) make every check derivable with zero annotations and zero false positives by construction. Correctness discipline is the gauntlet: 30 mutation-proven witness cells that must stay green through a two-generation self-host fixpoint before any compiler blesses — an instrument that has twice refused its own author's changes, which is the strongest evidence it works.

Where we are state of the art

axisclaimevidence
Toolchain sovereignty1000‰ — no mainstream language matches itSelf-hosted fixpoint (generation 2 = generation 3, byte-identical); zero external compiler, assembler, linker, runtime, or package registry anywhere in the chain. The public edge daemon serving this page rebuilds from source byte-identical to the live binary (md5-verified this week).
Supply-chain surfaceeffectively zero third-party codeNo crates, no npm, no pip, no vendored C. The TLS 1.3 stack, HTTP server, video codec, and this site's tooling are all NishiLang from byte 0. The trusted computing base is the 542KB compiler you can read.
Spatial safety with usable diagnosticsrefusing class, parity with Rust/Go, ahead of C — measured todaySafety table above; exit-71 refusal names the rule and the remedy. Guarantee reaches stack, static, and heap ([]T) memory; witnessed by mutation-proven gate cells, not by policy.
WebAssembly from our own compilera production codec in the field, no LLVM/Emscripten anywhereThe family video codec — SIMD wasm emitted by this toolchain — runs live calls at 60fps-class rates and holds 2.70× of x264's bitrate at equal PSNR, from 6.7× three days ago.
Whole-stack velocity in one languagecompiler, daemons, codecs, formats, sites — one substrateThe measured week: a codec closed 6.7×→2.70× vs x264 while the same language's edge daemon, health evaluator, and 3D format shipped. Monocultures compound.

Where we are not — each gap with its root cause, not a shrug

gapmeasuredroot cause (diagnosed, not guessed)
Scalar codegen vs C2.07×OP_PHI does not exist in the IR (grep count 0), so mem2reg only promotes single-store variables — every loop-carried variable lives in memory. Read straight from the emitted assembly, which is dominated by stack traffic, not by our checks.
Bounds-check cost~2× on a read-only loopNo elision pass. Go's 2.01× row proves the same guarantee can cost ~0 here when a compiler proves indexes in-range. An unsound elision is worse than none, so this waits for the blessed dominance oracle.
Slice ([]T) access3.73× vs Rust &[T] (07-25)The loop-invariant {data,len} header reloads every iteration; the hoist blocks on the same missing-phi ceiling (G9). Corpus migration deliberately waits — migrating first would ship a tree-wide regression.
Null-safety, data-race safetyunmeasuredNo probes exist yet, so the axes score zero by exclusion. Expect the headline grade to fall when they land; that is the ruler working.
Compiler robustnessopen defect classAn undefined identifier can still compile silently in some shapes (sev-9, open); string literals cap near 4.5KB; compiler stderr does not yet surface through the build API. Each has a filed debt row.
Ecosystem breadthstructuralNo package registry by design — sovereignty is the point. The cost is real: every capability is built, not imported. The measured mitigation is the velocity row above.

The plan — ordered by measured deficit, every rung gated

  1. Phi nodes + real mem2reg (the 2.07× rung). Add OP_PHI, place phis at merge points (over-approximate, then let copy-propagation and DCE clean up — dominance frontiers not required), rename via the existing dominator tree, then eliminate phis into predecessor copies so the register allocator and both backends need zero changes. Sized at 300–400 lines in the safety-critical file; runs as a dedicated session because two smaller optimizer attempts at session-tail both ended in gate-refused reverts. Gates: gauntlet 30/30, self-host fixpoint, head-to-head rerun.
  2. Sound bounds-check elision (the second 2×). Use the already-blessed exact dominance oracle to delete checks only where the index is provably in range — the Go result is the target picture. Soundness is the constraint: a wrong elision is a silent memory-safety hole, so every elided site gets a witness cell.
  3. Hoist the slice header, then migrate the corpus to []T — in that order. Adoption of the safe type is the point of having it; doing it before the 3.73× falls would push the regression tree-wide.
  4. Probes for null-safety and data-races, so the two excluded axes become measured ones. The grade will drop before it rises; published anyway.
  5. Robustness debts: hard-error on undefined identifiers everywhere, lift the literal ceiling, surface compiler diagnostics through the build API (the multiplier that makes novel-organ authoring debuggable at scale).
  6. The disabled load-forwarding pass stays disabled until it gets a dedicated session: its wrong-value bug is fixed (escape-predicate alias rule), a distinct compiler crash remains, and the gauntlet has correctly refused it twice. A gate that keeps saying no is information, not an obstacle.
The standing rule for every rung: measure the real code path before ranking it (round 3's #1 was disproved by reading the assembly), give every fix a mutation-proven gate cell before blessing, and let the public grade fall when honesty requires it. This page updates when the numbers move, not before.