<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="color-scheme" content="dark light">
<meta name="description" content="strykelang — Engineering report. Parallel Perl 5 interpreter in Rust: 309k Rust lines + 110k stryke lines, 6.1k tests, 8.5k builtins (9.1k spellings), 436 VM opcodes, 20k parity cases.">
<title>strykelang — Engineering Report</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;600;700;900&family=Share+Tech+Mono&display=swap" rel="stylesheet">
<link rel="stylesheet" href="hud-static.css">
<link rel="stylesheet" href="tutorial.css">
<style>
.tutorial-main { max-width: 76rem; }
.bar-wrap { background:var(--bg-primary);border:1px solid var(--border);border-radius:2px;height:18px;position:relative;overflow:hidden; }
.bar-fill { height:100%;border-radius:1px;transition:width 1.2s cubic-bezier(.22,1,.36,1); }
.bar-fill.green { background:linear-gradient(90deg,#39ff14,#20c00a);box-shadow:0 0 8px rgba(57,255,20,.4); }
.bar-fill.cyan { background:linear-gradient(90deg,#05d9e8,#0891b2);box-shadow:0 0 8px rgba(5,217,232,.4); }
.bar-fill.yellow { background:linear-gradient(90deg,#ffb800,#e8a000);box-shadow:0 0 8px rgba(255,184,0,.35); }
.bar-fill.magenta{ background:linear-gradient(90deg,#d300c5,#a000a0);box-shadow:0 0 8px rgba(211,0,197,.35); }
.bar-pct { position:absolute;right:6px;top:0;line-height:18px;font-size:10px;font-weight:700;color:#fff;text-shadow:0 0 4px #000;font-family:'Orbitron',sans-serif; }
.file-table { width:100%;border-collapse:collapse;margin:0.6rem 0;font-size:12px; }
.file-table th { background:var(--bg-secondary);color:var(--cyan);font-family:'Orbitron',sans-serif;font-size:10px;font-weight:700;letter-spacing:1.2px;text-transform:uppercase;text-align:left;padding:7px 10px;border:1px solid var(--border); }
.file-table td { padding:6px 10px;border:1px solid var(--border);color:var(--text-dim);vertical-align:middle; }
.file-table tr:hover td { background:var(--bg-hover); }
.file-table td:first-child { font-family:'Share Tech Mono',monospace;color:var(--accent-light);font-weight:600;white-space:nowrap; }
.file-table .num { text-align:right;font-family:'Share Tech Mono',monospace; }
.file-table .total-row td { background:var(--bg-secondary);font-weight:700;color:var(--text);border-top:2px solid var(--cyan); }
.file-table code { font-size:11px;color:var(--accent-light);background:var(--bg-primary);padding:1px 4px;border-radius:2px; }
.stat-grid { display:grid;grid-template-columns:repeat(auto-fill,minmax(14rem,1fr));gap:0.75rem;margin:1.2rem 0; }
.stat-card { border:1px solid var(--border);border-top:3px solid var(--cyan);background:var(--bg-card);padding:1rem 1.2rem;border-radius:2px;text-align:center; }
.stat-card .stat-val { font-family:'Orbitron',sans-serif;font-size:28px;font-weight:900;color:var(--cyan);line-height:1.1;text-shadow:0 0 20px var(--cyan-glow); }
.stat-card .stat-val.accent { color:var(--accent);text-shadow:0 0 20px var(--accent-glow); }
.stat-card .stat-val.green { color:var(--green);text-shadow:0 0 20px rgba(57,255,20,.3); }
.stat-card .stat-label { font-family:'Orbitron',sans-serif;font-size:9px;font-weight:700;letter-spacing:2px;text-transform:uppercase;color:var(--text-muted);margin-top:0.5rem; }
@keyframes glow-pulse { 0%,100%{text-shadow:0 0 20px var(--cyan-glow)}50%{text-shadow:0 0 40px var(--cyan-glow),0 0 80px var(--cyan-dim)} }
.stat-card .stat-val { animation:glow-pulse 3s ease-in-out infinite; }
.mapping-grid { display:grid;grid-template-columns:repeat(auto-fill,minmax(20rem,1fr));gap:0.65rem;margin:0.8rem 0; }
.mapping-card { border:1px solid var(--border);border-left:3px solid var(--magenta);background:var(--bg-card);padding:0.6rem 0.9rem;border-radius:2px; }
.mapping-card h4 { font-family:'Orbitron',sans-serif;font-size:10px;font-weight:700;letter-spacing:1.5px;text-transform:uppercase;color:var(--magenta);margin:0 0 0.3rem; }
.mapping-card p { margin:0;font-size:11px;color:var(--text-dim);line-height:1.5; }
.mapping-card code { font-size:10.5px;color:var(--accent-light);background:var(--bg-primary);padding:1px 4px;border-radius:2px; }
.section-rule { border:none;border-top:1px dashed var(--border);margin:2rem 0; }
.feature-grid { display:grid;grid-template-columns:repeat(auto-fill,minmax(22rem,1fr));gap:0.65rem;margin:0.8rem 0; }
.feature-card { border:1px solid var(--border);border-left:3px solid var(--cyan);background:var(--bg-card);padding:0.7rem 1rem;border-radius:2px; }
.feature-card h4 { font-family:'Orbitron',sans-serif;font-size:10px;font-weight:700;letter-spacing:1.5px;text-transform:uppercase;color:var(--cyan);margin:0 0 0.3rem; }
.feature-card p { margin:0;font-size:11px;color:var(--text-dim);line-height:1.55; }
.feature-card code { font-size:10.5px;color:var(--accent-light);background:var(--bg-primary);padding:1px 4px;border-radius:2px; }
.feature-card ul { margin:0.3rem 0 0;padding-left:1.2rem;font-size:11px;color:var(--text-dim);line-height:1.6; }
.feature-card li code { font-size:10px; }
</style>
</head>
<body>
<div class="app tutorial-app" id="reportApp">
<div class="crt-scanline" id="crtH" aria-hidden="true"></div>
<div class="crt-scanline-v" id="crtV" aria-hidden="true"></div>
<header class="tutorial-header">
<div class="tutorial-header-inner">
<div>
<h1 class="tutorial-brand">// STRYKELANG — ENGINEERING REPORT</h1>
<nav class="tutorial-crumbs" aria-label="Breadcrumb">
<span class="current">Engineering Report</span>
<span class="sep">/</span>
<a href="index.html">Stryke Docs</a>
<span class="sep">/</span>
<a href="reference.html">Reference</a>
<span class="sep">/</span>
<a href="https://github.com/MenkeTechnologies/strykelang" target="_blank" rel="noopener noreferrer">GitHub</a>
</nav>
<p style="margin:0.35rem 0 0;font-family:'Share Tech Mono',monospace;font-size:11px;color:var(--text-dim);letter-spacing:0.03em;opacity:0.75;">
Parallel Perl 5 interpreter in Rust · NaN-boxed bytecode VM · Cranelift JIT · Rayon work-stealing · pipe-forward (<code>|></code>) and thread macro (<code>~></code>)
</p>
</div>
<div class="tutorial-toolbar">
<button type="button" class="btn btn-secondary" id="btnTheme" title="Toggle light/dark">Theme</button>
<button type="button" class="btn btn-secondary active" id="btnCrt" title="CRT scanline overlay">CRT</button>
<button type="button" class="btn btn-secondary active" id="btnNeon" title="Neon border pulse">Neon</button>
</div>
</div>
</header>
<main class="tutorial-main">
<!-- ═══════════════════════════════════════ -->
<!-- SECTION 1: EXECUTIVE SUMMARY -->
<!-- ═══════════════════════════════════════ -->
<h2 class="tutorial-title"><span class="step-hash">>_</span>EXECUTIVE SUMMARY</h2>
<p class="tutorial-subtitle">strykelang is a single-binary Perl 5 implementation written in Rust. The interpreter compiles source to a 436-opcode bytecode, runs it on a register+stack hybrid VM, and JITs hot blocks through Cranelift to native code. Parallel primitives (<code>pmap</code>, <code>pgrep</code>, <code>pflat_map</code>, <code>pfor</code>) ride on rayon work-stealing. Pipe-forward (<code>|></code>) and the thread macro (<code>~></code>) extend Perl 5 syntax with Clojure / Racket / Scala threading semantics. <strong>268k production Rust lines + 110k stryke-program lines + 8,548 builtins (9,081 callable spellings) + 1,349/1,349 Rosetta tasks</strong> — matching surface coverage that took dynamic languages with multi-decade histories.</p>
<div class="stat-grid">
<div class="stat-card"><div class="stat-val">309,285</div><div class="stat-label">Rust Lines</div></div>
<div class="stat-card"><div class="stat-val">109,527</div><div class="stat-label">Stryke Lines (.stk)</div></div>
<div class="stat-card"><div class="stat-val accent">8,548</div><div class="stat-label">Builtins (Primary)</div></div>
<div class="stat-card"><div class="stat-val green">6,076</div><div class="stat-label">Test Functions</div></div>
<div class="stat-card"><div class="stat-val">436</div><div class="stat-label">VM Opcodes</div></div>
<div class="stat-card"><div class="stat-val">334</div><div class="stat-label">AST Variants</div></div>
<div class="stat-card"><div class="stat-val">20,058</div><div class="stat-label">Parity Cases</div></div>
<div class="stat-card"><div class="stat-val">1,995</div><div class="stat-label">Example Scripts</div></div>
<div class="stat-card"><div class="stat-val">134</div><div class="stat-label">Direct Dependencies</div></div>
<div class="stat-card"><div class="stat-val">966</div><div class="stat-label">Git Commits</div></div>
</div>
<div style="margin:1.2rem 0;">
<p style="font-size:11px;color:var(--text-muted);letter-spacing:0.5px;text-transform:uppercase;margin-bottom:4px;font-family:'Orbitron',sans-serif;font-weight:700;">Source Distribution — 309,285 lines</p>
<div class="bar-wrap" style="height:26px;">
<div class="bar-fill cyan" style="width:86.8%;"></div>
<span class="bar-pct" style="font-size:12px;">268,383 production / 40,902 tests / 105 tooling · 86.8% production</span>
</div>
<p style="font-size:10px;color:var(--text-muted);margin-top:4px;">Production: 89 files across <code>strykelang/</code> + <code>strykelang/pkg/</code> + <code>strykelang/bins/</code> excluding <code>*_tests.rs</code>. Tests: 17 inline test files in <code>strykelang/</code> + 85 integration files in <code>tests/</code>. Tooling: <code>build.rs</code> + <code>benches/</code>.</p>
</div>
<hr class="section-rule">
<!-- ═══════════════════════════════════════ -->
<!-- SECTION 1b: SCALE & POSITION -->
<!-- ═══════════════════════════════════════ -->
<h2 class="tutorial-title"><span class="step-hash">~</span>SCALE & POSITION</h2>
<p class="tutorial-subtitle">Quantitative comparison against the established dynamic-language reference set. Source-LOC figures are approximate (counted from each project's public source tree, excluding vendored deps and external bindings). Stryke is single-author single-language-binary; the others span tens to hundreds of contributors over multi-decade histories.</p>
<table class="file-table">
<thead>
<tr>
<th>Language</th>
<th>First release</th>
<th class="num">Years</th>
<th class="num">Production source</th>
<th class="num">Builtins (primary)</th>
<th>Native JIT</th>
<th>Rosetta complete?</th>
</tr>
</thead>
<tbody>
<tr style="background:rgba(57,255,20,0.05);">
<td style="color:var(--green);"><strong>stryke</strong></td>
<td>2026</td>
<td class="num">0.08</td>
<td class="num">230,982 Rust + 109,527 stk</td>
<td class="num">8,548</td>
<td>Cranelift</td>
<td><strong>1,349 / 1,349 (100%)</strong></td>
</tr>
<tr>
<td>Lua 5.4</td>
<td>1993</td>
<td class="num">~32</td>
<td class="num">~13,000 (C)</td>
<td class="num">~80</td>
<td>no (LuaJIT is separate)</td>
<td>partial</td>
</tr>
<tr>
<td>LuaJIT</td>
<td>2005</td>
<td class="num">~20</td>
<td class="num">~85,000 (C+asm)</td>
<td class="num">~80</td>
<td>tracing</td>
<td>n/a (rides on Lua)</td>
</tr>
<tr>
<td>Tcl 8.6</td>
<td>1988</td>
<td class="num">~37</td>
<td class="num">~150,000 (C)</td>
<td class="num">~90</td>
<td>no</td>
<td>complete</td>
</tr>
<tr>
<td>Crystal</td>
<td>2014</td>
<td class="num">~12</td>
<td class="num">~250,000 (Crystal)</td>
<td class="num">stdlib classes</td>
<td>LLVM AOT</td>
<td>partial</td>
</tr>
<tr>
<td>Perl 5</td>
<td>1994</td>
<td class="num">~31</td>
<td class="num">~700,000 (C+Perl)</td>
<td class="num">~250 keywords</td>
<td>no</td>
<td>complete</td>
</tr>
<tr>
<td>Python 3</td>
<td>2008</td>
<td class="num">~17</td>
<td class="num">~1,200,000 (C+Py)</td>
<td class="num">~150 builtins</td>
<td>no (3.13 experimental)</td>
<td>complete</td>
</tr>
</tbody>
</table>
<div class="feature-grid" style="margin-top:1.2rem;">
<div class="feature-card">
<h4>By Per-Year Output</h4>
<p>Stryke ships ~89,000 production lines per year of single-author Rust. Lua's lifetime average is ~400 lines/year of single-author C. Different orders of magnitude — different feature scope.</p>
</div>
<div class="feature-card">
<h4>By Test Surface</h4>
<p><code>6,076</code> <code>#[test]</code> functions + <code>20,058</code> Perl-parity cases + <code>22,236</code> assertions in the Rosetta corpus. The cross-implementation parity suite is the critical part — only mature dynamic langs ship one (Perl, Ruby, Python) and stryke is the only one running its parity suite against another implementation (perl) on every CI cycle.</p>
</div>
<div class="feature-card">
<h4>By Built-in Capability</h4>
<p>Things in stryke's binary that the reference set doesn't ship in-binary: Cranelift JIT, distributed-compute primitive (<code>cluster</code>/<code>pmap_on</code>), package manager (<code>s pkg</code>), web framework, language-level AI (<code>ai</code>/<code>tool fn</code>/MCP), AOT static-binary deployment (<code>s build</code>). Encyclopedic-stdlib axis: 8,548 builtins (9,081 spellings) vs ~80–250 for the reference set.</p>
</div>
<div class="feature-card">
<h4>Rosetta Code Completion</h4>
<p>Clearing all 1,349 published tasks is a third-party-verifiable completeness bar that takes most languages a decade or more to reach — differential is the encyclopedic-stdlib axis: tasks that other languages need third-party libraries for are one-builtin calls in stryke.</p>
</div>
</div>
<h3 class="tutorial-title" style="font-size:1.05em;margin-top:24px;"><span class="step-hash">#</span>Builtin Count vs Other Bareword-Fn Languages</h3>
<p class="tutorial-subtitle">Stryke's <strong>8,548</strong> primary builtins exceed every other language whose stdlib is exposed as bareword fns — including Wolfram Language, the only prior holder of "world's largest builtin set" branding. APL/J/K/q have hundreds of primitives, but as glyphs (<code>+/</code>, <code>⌽</code>, <code>~:</code>) rather than barewords; R has ~2k+, but split across <code>library()</code>'d packages rather than always-loaded. Stryke is the only bareword-fn language past the 8k threshold.</p>
<table class="file-table">
<thead><tr><th>Language</th><th class="num">Bareword Builtins</th><th>Source / Probe</th></tr></thead>
<tbody>
<tr><td style="color:var(--accent);"><strong>stryke</strong></td><td class="num"><strong>8,548</strong></td><td><code>len(keys %b)</code> at runtime — dynamic, not hardcoded</td></tr>
<tr><td>Wolfram Language v14.1</td><td class="num">~7,000</td><td>Stephen Wolfram blog ("7,000 or so" at v14.1, +89 net new from v14.0's 6,602)</td></tr>
<tr><td>Wolfram Language v14.3 (est.)</td><td class="num">7,100–7,300</td><td>Extrapolated from per-version deltas; exact count not published</td></tr>
<tr><td>Ruby Kernel</td><td class="num">~250</td><td><code>Kernel.methods.size</code></td></tr>
<tr><td>Perl 5 core</td><td class="num">~220</td><td><code>perlfunc</code> manpage</td></tr>
<tr><td>TCL</td><td class="num">~100</td><td><code>info commands</code></td></tr>
<tr><td>Lua base + std</td><td class="num">~100</td><td><code>_G</code> + standard tables</td></tr>
<tr><td>Bash</td><td class="num">~80</td><td><code>enable -a | wc -l</code></td></tr>
<tr><td>Python builtins</td><td class="num">~70</td><td><code>dir(__builtins__)</code> — stdlib is <code>module.fn</code>, not bareword</td></tr>
<tr><td>AWK</td><td class="num">~30</td><td>gawk manual</td></tr>
</tbody>
</table>
<p style="margin-top:12px;">Wolfram is the only language that has marketed builtin count as a competitive metric. Stryke's 8,548 clears Wolfram v14.1's stated count by ~1,000 and exceeds the highest plausible v14.3 estimate by ~800. Bareword-fn rivalry past the 8k mark: stryke is alone in the category.</p>
<hr class="section-rule">
<!-- ═══════════════════════════════════════ -->
<!-- SECTION 2: SUBSYSTEM BREAKDOWN -->
<!-- ═══════════════════════════════════════ -->
<h2 class="tutorial-title"><span class="step-hash">#</span>SUBSYSTEM BREAKDOWN</h2>
<p class="tutorial-subtitle">Source partitioned by role. Builtins dominate at 34.4% — the language ships with 8,548 builtins (9,081 callable spellings = 8,548 primaries + 533 aliases) spanning string / array / hash / regex / I/O / process / OO / format / pack / crypto / codec / parallel / HTTP / database / network / AI / web / math / physics / chemistry / biology / signal / finance domains. Core pipeline (lexer→parser→compiler→VM→JIT) is 21%.</p>
<table class="file-table">
<thead><tr><th>Subsystem</th><th>Key Files</th><th class="num">Lines</th><th class="num">%</th><th style="min-width:120px;">Share</th><th>Description</th></tr></thead>
<tbody>
<tr><td style="color:var(--accent);">Builtins</td><td><code>builtins, builtins_extended, list_builtins, math_wolfram*</code></td><td class="num">106,420</td><td class="num">34.4%</td><td><div class="bar-wrap"><div class="bar-fill magenta" style="width:34.4%"></div></div></td><td>8,548 builtins / 9,081 callable spellings: string, array, hash, regex, math, physics, chemistry, biology, signal, finance, ML, geometry, special functions, I/O, file, process, OO, format, pack, crypto, codec, network, HTTP, JWT</td></tr>
<tr><td style="color:var(--accent);">VM & Compiler</td><td><code>vm, compiler, bytecode</code></td><td class="num">22,213</td><td class="num">8.1%</td><td><div class="bar-wrap"><div class="bar-fill cyan" style="width:8.1%"></div></div></td><td>436-opcode bytecode, register+stack VM, AST→bytecode compiler with constant folding / register allocation / peephole, opcode disassembler</td></tr>
<tr><td style="color:var(--accent);">Tree Walker (vm_helper)</td><td><code>vm_helper</code></td><td class="num">20,892</td><td class="num">7.7%</td><td><div class="bar-wrap"><div class="bar-fill cyan" style="width:7.7%"></div></div></td><td>Tree-walking interpreter + runtime helpers: scope graph, error context, debugger hooks, special variables (<code>$_</code>, <code>$!</code>, <code>$/</code>, ...), reflection-hash population, package-stash refresh, AOP intercepts</td></tr>
<tr><td style="color:var(--accent);">Parser</td><td><code>parser, ast, token</code></td><td class="num">19,915</td><td class="num">7.3%</td><td><div class="bar-wrap"><div class="bar-fill cyan" style="width:7.3%"></div></div></td><td>Recursive-descent parser, 183 <code>parse_*</code> functions, AST variants across multiple enums, operator precedence climbing (or/and/not at lowest tier per <code>perlop</code>), heredocs, prototype parsing, builtin-name whitelist</td></tr>
<tr><td style="color:var(--accent);">AI / Web</td><td><code>ai, ai_sugar, web, web_orm, mcp</code></td><td class="num">13,367</td><td class="num">4.9%</td><td><div class="bar-wrap"><div class="bar-fill magenta" style="width:4.9%"></div></div></td><td>Anthropic / OpenAI client, tool-use protocol, AI sugar (<code>ai</code> as native verb), MCP server / client, web framework (route DSL, controllers, ORM, sessions, templates), JSON / form / multipart parsers</td></tr>
<tr><td style="color:var(--accent);">Value System</td><td><code>value, nanbox, scope, capture, convert, deconvert</code></td><td class="num">9,488</td><td class="num">3.5%</td><td><div class="bar-wrap"><div class="bar-fill cyan" style="width:3.5%"></div></div></td><td>NaN-boxed <code>PerlValue</code>: int / float / string / array / hash / code / regex / undef. Scoping (pad slots, closures, <code>local</code>/<code>my</code>/<code>our</code>/<code>oursync</code>), type coercion, capture cells</td></tr>
<tr><td style="color:var(--accent);">Codecs / Data</td><td><code>native_codec, native_data, map_stream, map_grep_fast, sort_fast</code></td><td class="num">6,362</td><td class="num">2.3%</td><td><div class="bar-wrap"><div class="bar-fill cyan" style="width:2.3%"></div></div></td><td>JSON / YAML / TOML / CSV / MessagePack encode-decode, streaming map/grep iterators, optimized sort</td></tr>
<tr><td style="color:var(--accent);">Distribution</td><td><code>cluster, controller, agent, remote_wire, pkg/*, script_cache, pcache</code></td><td class="num">6,251</td><td class="num">2.3%</td><td><div class="bar-wrap"><div class="bar-fill cyan" style="width:2.3%"></div></div></td><td>Multi-host cluster execution, agent / controller protocol, wire format, package manager (<code>pkg</code> — manifest, lockfile, store, resolver), bytecode cache</td></tr>
<tr><td style="color:var(--accent);">LSP</td><td><code>lsp</code></td><td class="num">6,594</td><td class="num">2.4%</td><td><div class="bar-wrap"><div class="bar-fill cyan" style="width:2.4%"></div></div></td><td>Language Server Protocol: hover descriptions, completion, diagnostics, go-to-definition, document symbols</td></tr>
<tr><td style="color:var(--accent);">CLI & REPL</td><td><code>main, repl</code></td><td class="num">5,451</td><td class="num">2.0%</td><td><div class="bar-wrap"><div class="bar-fill cyan" style="width:2.0%"></div></div></td><td>CLI entry: argv parsing, script loading, one-liner mode (<code>-e</code>/<code>-E</code>/<code>-n</code>/<code>-p</code>), reedline-based REPL with utop-style menu, columnar completion, history</td></tr>
<tr><td style="color:var(--accent);">JIT</td><td><code>jit</code></td><td class="num">5,172</td><td class="num">1.9%</td><td><div class="bar-wrap"><div class="bar-fill cyan" style="width:1.9%"></div></div></td><td>Cranelift block-level JIT: hot-path detection, native code emission for tight numeric loops, deoptimization stubs back to bytecode VM</td></tr>
<tr><td style="color:var(--accent);">Format / Deparse</td><td><code>fmt, deparse, format</code></td><td class="num">4,288</td><td class="num">1.6%</td><td><div class="bar-wrap"><div class="bar-fill cyan" style="width:1.6%"></div></div></td><td><code>perltidy</code>-compatible code formatter, AST→source deparser (<code>B::Deparse</code> equivalent), Perl <code>format</code>/<code>write</code> system</td></tr>
<tr><td style="color:var(--accent);">Parallel Runtime</td><td><code>par_lines, par_list, par_pipeline, par_walk, ppool, pchannel, pwatch, pmap_progress, parallel_trace, stress</code></td><td class="num">4,029</td><td class="num">1.5%</td><td><div class="bar-wrap"><div class="bar-fill cyan" style="width:1.5%"></div></div></td><td>Rayon work-stealing: <code>pmap</code>, <code>pgrep</code>, <code>pflat_map</code>, <code>pfor</code>, parallel file walking, async pipelines, progress tracking, channels, stress-testing primitives (<code>heat</code>, <code>fire</code>)</td></tr>
<tr><td style="color:var(--accent);">Perl Compat</td><td><code>perl_decode, perl_fs, perl_inc, perl_regex, perl_signal, perl_pty, special_vars, english</code></td><td class="num">3,578</td><td class="num">1.3%</td><td><div class="bar-wrap"><div class="bar-fill cyan" style="width:1.3%"></div></div></td><td><code>@INC</code>, <code>%ENV</code>, <code>%SIG</code>, file ops, Perl regex engine, signal handling, PTY support, magic special variables, <code>use English</code></td></tr>
<tr><td style="color:var(--accent);">Lexer</td><td><code>lexer</code></td><td class="num">3,506</td><td class="num">1.3%</td><td><div class="bar-wrap"><div class="bar-fill cyan" style="width:1.3%"></div></div></td><td>Tokenizer for Perl 5 + stryke extensions: heredocs, regex literals, <code>q/qq/qw/qr</code>, string interpolation, Unicode identifiers, sigil disambiguation</td></tr>
<tr><td style="color:var(--accent);">Misc / Error</td><td><code>error, mro, lib, bench_fusion, fib_like_tail, pending_destroy, bins/gen_docs, parse_smoke_*, run_semantics_more</code></td><td class="num">3,250</td><td class="num">1.2%</td><td><div class="bar-wrap"><div class="bar-fill cyan" style="width:1.2%"></div></div></td><td>Rich error reporter, MRO (C3 / DFS), library entry, fusion-pass optimizers, finalizer queue, doc generator, smoke tests</td></tr>
<tr><td style="color:var(--accent);">Tooling</td><td><code>debugger, profiler, static_analysis</code></td><td class="num">2,187</td><td class="num">0.8%</td><td><div class="bar-wrap"><div class="bar-fill cyan" style="width:0.8%"></div></div></td><td>Step debugger, sampling profiler, static analyzer with lints</td></tr>
<tr><td style="color:var(--accent);">FFI / AOT</td><td><code>rust_ffi, rust_sugar, aot, data_section, aop</code></td><td class="num">1,809</td><td class="num">0.7%</td><td><div class="bar-wrap"><div class="bar-fill cyan" style="width:0.7%"></div></div></td><td>Embed-Rust closure FFI, AOT bytecode caching, data-section relocations, AOP intercepts</td></tr>
<tr><td style="color:var(--accent);">Crypto / Pack</td><td><code>crypt_util, jwt, pack, secrets</code></td><td class="num">1,667</td><td class="num">0.6%</td><td><div class="bar-wrap"><div class="bar-fill cyan" style="width:0.6%"></div></div></td><td>Symmetric / asymmetric encryption, password hashing, JWT encode/decode, <code>pack</code>/<code>unpack</code> templates, secret-store helpers</td></tr>
<tr><td style="color:var(--green);">Tests</td><td><code>tests/suite/*, *_tests.rs</code></td><td class="num">40,902</td><td class="num">13.2%</td><td><div class="bar-wrap"><div class="bar-fill green" style="width:13.2%"></div></div></td><td>6,076 <code>#[test]</code> functions across 100+ files: parser, lexer, builtins, parallel, regex, values, OO, semantics, CLI, LSP, runtime, fix-regression suite</td></tr>
<tr><td style="color:var(--text-muted);">Build / Bench</td><td><code>build.rs, benches/, fuzz/</code></td><td class="num">669</td><td class="num">0.25%</td><td><div class="bar-wrap"><div class="bar-fill yellow" style="width:0.25%"></div></div></td><td>Build-time reflection generator (<code>BUILTIN_ARMS</code>, <code>CATEGORY_MAP</code>, <code>DESCRIPTIONS</code>), JIT vs interpreter micro-bench, libfuzzer harnesses</td></tr>
</tbody>
<tfoot><tr class="total-row"><td colspan="2" style="font-family:'Orbitron',sans-serif;font-size:10px;letter-spacing:1px;">TOTAL</td><td class="num">309,285</td><td class="num">100%</td><td></td><td></td></tr></tfoot>
</table>
<hr class="section-rule">
<!-- ═══════════════════════════════════════ -->
<!-- SECTION 3: TOP 20 FILES -->
<!-- ═══════════════════════════════════════ -->
<h2 class="tutorial-title"><span class="step-hash">$</span>TOP 20 FILES BY SIZE</h2>
<p class="tutorial-subtitle">The 20 largest source files account for 71% of the codebase. Builtins is by far the largest single file: every Perl 5 core function plus stryke extensions (HTTP, JSON, parallel, codec, OO, AI, web) lives here, dispatched through a single match table generated at build time.</p>
<table class="file-table">
<thead><tr><th>File</th><th class="num">Lines</th><th>Role</th></tr></thead>
<tbody>
<tr><td>strykelang/builtins.rs</td><td class="num">34,038</td><td>Core builtin dispatch table covering string/array/hash/regex/math/I/O/file/process/OO domains; routes 8,548 builtins (9,081 callable spellings)</td></tr>
<tr><td>strykelang/math_wolfram*.rs</td><td class="num">58,010</td><td>82 batch files (math_wolfram, math_wolfram2…82) <code>include!</code>'d into builtins.rs: 4,643 fns spanning Wolfram-class math, physics, chemistry, biology, signal, finance, ML, geometry, special functions, calendrical, astronomy, BLAS/LAPACK, sabermetrics, Excel/financial, GIS, robotics/control, actuarial, epidemiology, archive/encoding, music theory, geology, logic/SAT/SMT, compilers/parsing, linguistics, Postgres SQL/JSON, Redis, scipy.special, economics/game theory</td></tr>
<tr><td>strykelang/vm_helper.rs</td><td class="num">20,892</td><td>Runtime: scope graph, evaluation context, error reporter, debugger hooks, special-variable handling, reflection-hash population, package-stash refresh</td></tr>
<tr><td>strykelang/parser.rs</td><td class="num">17,754</td><td>Recursive-descent parser; precedence climbing, heredocs; whitelists every builtin spelling</td></tr>
<tr><td>strykelang/builtins_extended.rs</td><td class="num">12,524</td><td>Extended builtins: crypto, JWT, codecs (JSON/YAML/TOML/CSV/MsgPack), HTTP, email, QR, compression</td></tr>
<tr><td>strykelang/vm.rs</td><td class="num">10,282</td><td>Bytecode VM: register+stack hybrid, 436 opcodes, hot-path detection, exception unwinder</td></tr>
<tr><td>strykelang/compiler.rs</td><td class="num">9,476</td><td>AST→bytecode: constant folding, register allocation, peephole optimization, basic-block formation</td></tr>
<tr><td>tests/suite/fix_regressions.rs</td><td class="num">7,654</td><td>Regression test suite — one test per fixed bug; pin behaviors so refactors can’t silently re-break</td></tr>
<tr><td>strykelang/ai.rs</td><td class="num">6,603</td><td>Anthropic / OpenAI API client, tool-use protocol, batch / pmap fan-out, MCP integration, vision / audio modalities</td></tr>
<tr><td>strykelang/lsp.rs</td><td class="num">6,594</td><td>Language Server Protocol: hover descriptions, completion, diagnostics, document symbols</td></tr>
<tr><td>strykelang/run_semantics_tests.rs</td><td class="num">5,417</td><td>Perl-semantics correctness suite: behaviors that must match perl byte-for-byte</td></tr>
<tr><td>strykelang/jit.rs</td><td class="num">5,172</td><td>Cranelift JIT: IR generation, native code emission, deoptimization stubs, calling-convention bridge</td></tr>
<tr><td>strykelang/crate_api_tests.rs</td><td class="num">5,164</td><td>Public crate-API test suite: validates the embeddable interface (<code>stryke::eval</code>, <code>VMHelper</code>, ...)</td></tr>
<tr><td>strykelang/main.rs</td><td class="num">4,974</td><td>CLI: argv, script loading, one-liner mode (<code>-e</code>/<code>-E</code>/<code>-n</code>/<code>-p</code>), shebang dispatch, builtin-as-command</td></tr>
<tr><td>strykelang/value.rs</td><td class="num">4,546</td><td><code>PerlValue</code>: NaN-boxed union, conversions, stringify / numify, magic context handling</td></tr>
<tr><td>strykelang/web.rs</td><td class="num">3,554</td><td>Web framework: route DSL, controllers, sessions, cookies, flash, multipart parsing, static / template rendering</td></tr>
<tr><td>strykelang/lexer.rs</td><td class="num">3,506</td><td>Tokenizer: heredocs, regex literals, <code>q/qq/qw/qr</code>, string interpolation, sigil disambiguation</td></tr>
<tr><td>strykelang/native_codec.rs</td><td class="num">3,353</td><td>Built-in JSON / YAML / TOML / CSV / MessagePack encode-decode</td></tr>
<tr><td>strykelang/scope.rs</td><td class="num">2,948</td><td>Lexical scoping: pad slots, closures, <code>my</code>/<code>local</code>/<code>our</code>/<code>oursync</code>, <code>BEGIN</code>/<code>END</code>/<code>INIT</code>/<code>CHECK</code></td></tr>
<tr><td>strykelang/bytecode.rs</td><td class="num">2,455</td><td>Opcode definitions (436 variants), instruction encoding, disassembler</td></tr>
</tbody>
<tfoot><tr class="total-row"><td style="font-family:'Orbitron',sans-serif;font-size:10px;letter-spacing:1px;">TOP 20 SUBTOTAL</td><td class="num">193,962</td><td>84.0% of repo</td></tr></tfoot>
</table>
<hr class="section-rule">
<!-- ═══════════════════════════════════════ -->
<!-- SECTION 4: EXECUTION PIPELINE -->
<!-- ═══════════════════════════════════════ -->
<h2 class="tutorial-title"><span class="step-hash">@</span>EXECUTION PIPELINE</h2>
<p class="tutorial-subtitle">Source flows through 5 stages. Tier 1 is the bytecode VM; tier 2 is Cranelift JIT'd native code for hot blocks. Both tiers share the same NaN-boxed value representation, so deoptimization (JIT→VM fallback on type miss) is a frame-pointer swap, not a re-marshal.</p>
<pre style="margin:0.5rem 0;padding:1rem;border:1px solid var(--border);background:var(--bg-primary);color:var(--text-dim);font-size:11px;line-height:1.7;overflow-x:auto;">
Source (.stk / .pl / -e '...')
│
▼
┌─────────────┐ ┌─────────────┐ ┌──────────────┐
│ lexer.rs │────▶│ parser.rs │────▶│ compiler.rs │
│ (3,506) │ │ (17,754) │ │ (9,476) │
│ Tokenizer │ │ AST node │ │ 436 opcodes │
│ heredocs │ │ variants │ │ const fold │
│ regex lit │ │ prec climb │ │ reg alloc │
│ q/qq/qw/qr │ │ whitelist │ │ peephole │
└─────────────┘ └─────────────┘ └──────┬───────┘
│
┌────────────────────┤
│ │
▼ ▼
┌──────────────┐ ┌──────────────┐
│ vm.rs │ │ jit.rs │
│ (10,282) │ │ (5,172) │
│ Bytecode VM │ │ Cranelift │
│ reg + stack │ │ block JIT │
│ hot detect │────▶│ native code │
│ exc unwind │◀────│ deopt stubs │
└──────┬───────┘ └──────────────┘
│
▼
┌───────────────────┐
│ builtins.rs │
│ (31,091) │
│ 8,548 builtins │
│ 9,081 spellings │
│ + extended │
│ (12,524) │
│ + math_wolfram* │
│ (30,003 / 30 f) │
└─────────┬─────────┘
│
┌────────────────┼─────────────────┐
│ │ │
┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐
│ value.rs │ │ scope.rs │ │ parallel │
│ (4,546) │ │ (2,948) │ │ (4,029) │
│ NaN-boxed │ │ my/local/ │ │ pmap/pgrep │
│ PerlValue │ │ oursync │ │ rayon work │
└─────────────┘ └─────────────┘ └─────────────┘</pre>
<hr class="section-rule">
<!-- ═══════════════════════════════════════ -->
<!-- SECTION 5: BUILTIN INVENTORY -->
<!-- ═══════════════════════════════════════ -->
<h2 class="tutorial-title"><span class="step-hash">&</span>BUILTIN INVENTORY</h2>
<p class="tutorial-subtitle">Builtins are partitioned at build time by <code>build.rs</code>, which scans <code>parser.rs</code> and <code>builtins.rs</code> to generate <code>CORE_CATEGORY_MAP</code> (Perl 5 core), <code>EXT_CATEGORY_MAP</code> (stryke extensions), and <code>ALL_CATEGORY_MAP</code> (every callable spelling, primaries plus aliases). The reflection tables back the runtime <code>%b</code> / <code>%all</code> / <code>%pc</code> / <code>%e</code> / <code>%a</code> / <code>%d</code> / <code>%c</code> / <code>%p</code> hashes (plus their <code>%stryke::*</code> long-form aliases). At runtime stryke also exposes <code>%parameters</code> (zsh-style live binding view) and per-package stashes (<code>%main::</code>, <code>%Foo::</code>) refreshed lazily on read.</p>
<div class="stat-grid" style="grid-template-columns:repeat(auto-fill,minmax(13rem,1fr));">
<div class="stat-card" style="border-top-color:var(--accent);"><div class="stat-val accent">8,548</div><div class="stat-label">Builtins (Primary)</div></div>
<div class="stat-card" style="border-top-color:var(--accent);"><div class="stat-val accent">533</div><div class="stat-label">Aliases</div></div>
<div class="stat-card" style="border-top-color:var(--accent);"><div class="stat-val accent">9,081</div><div class="stat-label">Total Spellings</div></div>
<div class="stat-card" style="border-top-color:var(--cyan);"><div class="stat-val">213</div><div class="stat-label">Perl 5 Core</div></div>
<div class="stat-card" style="border-top-color:var(--cyan);"><div class="stat-val">5,436</div><div class="stat-label">Stryke Extensions</div></div>
<div class="stat-card" style="border-top-color:var(--cyan);"><div class="stat-val">2,845</div><div class="stat-label">LSP Descriptions</div></div>
<div class="stat-card" style="border-top-color:var(--cyan);"><div class="stat-val">2,505</div><div class="stat-label">Match Arms</div></div>
<div class="stat-card" style="border-top-color:var(--cyan);"><div class="stat-val">188</div><div class="stat-label">Categories</div></div>
</div>
<p style="font-size:11px;color:var(--text-muted);margin-top:0.5rem;">117 hot builtins are reachable through dedicated <code>BuiltinId</code> opcodes in <code>bytecode.rs</code> — the rest go through the generic dispatch table. The 533-alias overhead exists so canonical Perl spellings (<code>localtime</code>), abbreviations (<code>tj</code>), and stryke-style snake_case alternatives all coexist without disambiguation. Invariant: <code>keys %a + keys %b == keys %all</code>.</p>
<h3 style="font-family:'Orbitron',sans-serif;font-size:11px;color:var(--accent);letter-spacing:1.5px;margin:1.5rem 0 0.5rem;">// CATEGORIES</h3>
<div class="mapping-grid">
<div class="mapping-card"><h4>String</h4><p><code>chomp</code>, <code>uc</code>, <code>lc</code>, <code>sprintf</code>, <code>substr</code>, <code>index</code>, <code>reverse</code>, <code>split</code>, <code>join</code>, <code>tr///</code>, <code>s///</code>, <code>m//</code></p></div>
<div class="mapping-card"><h4>Array</h4><p><code>push</code>, <code>pop</code>, <code>shift</code>, <code>unshift</code>, <code>map</code>, <code>grep</code>, <code>sort</code>, <code>reverse</code>, <code>splice</code>, <code>wantarray</code></p></div>
<div class="mapping-card"><h4>Hash</h4><p><code>keys</code>, <code>values</code>, <code>each</code>, <code>exists</code>, <code>delete</code>, <code>tied</code>, <code>tie</code>, <code>untie</code></p></div>
<div class="mapping-card"><h4>Numeric</h4><p><code>abs</code>, <code>int</code>, <code>sqrt</code>, <code>sin</code>, <code>cos</code>, <code>atan2</code>, <code>exp</code>, <code>log</code>, <code>hex</code>, <code>oct</code>, <code>rand</code>, <code>srand</code></p></div>
<div class="mapping-card"><h4>I/O</h4><p><code>open</code>, <code>close</code>, <code>read</code>, <code>write</code>, <code>print</code>, <code>printf</code>, <code>say</code>, <code>readline</code>, <code>seek</code>, <code>tell</code>, <code>eof</code></p></div>
<div class="mapping-card"><h4>File</h4><p><code>stat</code>, <code>lstat</code>, <code>chmod</code>, <code>chown</code>, <code>unlink</code>, <code>rename</code>, <code>symlink</code>, <code>readlink</code>, <code>mkdir</code>, <code>rmdir</code>, file-test ops</p></div>
<div class="mapping-card"><h4>Process</h4><p><code>fork</code>, <code>exec</code>, <code>system</code>, <code>wait</code>, <code>waitpid</code>, <code>kill</code>, <code>getpid</code>, <code>getppid</code>, <code>setsid</code></p></div>
<div class="mapping-card"><h4>Regex</h4><p><code>m//</code>, <code>s///</code>, <code>qr//</code>, <code>tr///</code>, <code>pos</code>, named captures, lookahead/behind, fancy-regex backrefs</p></div>
<div class="mapping-card"><h4>OO</h4><p><code>bless</code>, <code>ref</code>, <code>isa</code>, <code>can</code>, <code>SUPER::</code>, MRO C3 / DFS, roles, traits, <code>class</code> blocks</p></div>
<div class="mapping-card"><h4>Format / Pack</h4><p><code>pack</code>, <code>unpack</code>, <code>format</code>, <code>write</code>, <code>printf</code>, <code>sprintf</code> with full Perl 5 format strings</p></div>
<div class="mapping-card"><h4>Codec</h4><p><code>to_json</code>, <code>from_json</code>, <code>to_yaml</code>, <code>from_yaml</code>, <code>to_toml</code>, <code>to_csv</code>, <code>to_msgpack</code>, <code>to_html</code>, <code>to_pdf</code></p></div>
<div class="mapping-card"><h4>Crypto</h4><p>AES, ChaCha20, RSA, Ed25519, P-256/384, X25519, Argon2, scrypt, bcrypt, PBKDF2, BLAKE3, SHA-2/3, JWT</p></div>
<div class="mapping-card"><h4>Network</h4><p><code>http_get</code>, <code>http_post</code>, <code>tcp_connect</code>, <code>tcp_listen</code>, DNS lookup, URL parse, IP utilities</p></div>
<div class="mapping-card"><h4>Parallel</h4><p><code>pmap</code>, <code>pgrep</code>, <code>pflat_map</code>, <code>pfor</code>, <code>par_lines</code>, <code>par_walk</code>, work-stealing iterators, channels</p></div>
<div class="mapping-card"><h4>Filesystem Stream</h4><p><code>fr</code> (file rec), <code>fw</code> (file write), <code>fa</code> (file append), <code>slurp</code>, <code>spurt</code>, <code>walk</code></p></div>
<div class="mapping-card"><h4>Reflection</h4><p><code>%b</code> / <code>%all</code> / <code>%pc</code> / <code>%e</code> / <code>%a</code> / <code>%d</code> / <code>%c</code> / <code>%p</code> (eight build-time reflection hashes), <code>%parameters</code> (live bindings, zsh <code>$parameters</code>), <code>%main::</code> / <code>%Pkg::</code> (package stashes), <code>caller</code>, <code>__PACKAGE__</code>, <code>__SUB__</code></p></div>
</div>
<hr class="section-rule">
<!-- ═══════════════════════════════════════ -->
<!-- SECTION 6: VM & BYTECODE -->
<!-- ═══════════════════════════════════════ -->
<h2 class="tutorial-title"><span class="step-hash">!</span>VM & BYTECODE</h2>
<p class="tutorial-subtitle">436 opcodes grouped into 26 functional categories. The VM is a register+stack hybrid: frame-local scalar slots provide O(1) access for hot variables (no string lookup), while the operand stack handles temporaries and complex expressions. Frame-local slots win on tight loops; the stack wins on irregular control flow.</p>
<h3 style="font-family:'Orbitron',sans-serif;font-size:11px;color:var(--cyan);letter-spacing:1.5px;margin:1rem 0 0.5rem;">// OPCODE CATEGORIES</h3>
<div class="mapping-grid">
<div class="mapping-card"><h4>Constants</h4><p><code>LoadInt</code>, <code>LoadFloat</code>, <code>LoadConst</code>, <code>LoadUndef</code></p></div>
<div class="mapping-card"><h4>Stack</h4><p><code>Pop</code>, <code>Dup</code>, <code>Swap</code>, <code>Roll</code></p></div>
<div class="mapping-card"><h4>Scalars</h4><p>Name-pool indexed get/set, <code>$_</code> magic, <code>local</code>/<code>my</code>/<code>our</code> binding</p></div>
<div class="mapping-card"><h4>Arrays</h4><p><code>NewArray</code>, <code>Push</code>, <code>Pop</code>, <code>Shift</code>, <code>Unshift</code>, indexed get/set</p></div>
<div class="mapping-card"><h4>Hashes</h4><p><code>NewHash</code>, get/set/delete, <code>exists</code>, <code>each</code>, <code>keys</code>, <code>values</code></p></div>
<div class="mapping-card"><h4>Arithmetic</h4><p><code>Add</code>, <code>Sub</code>, <code>Mul</code>, <code>Div</code>, <code>Mod</code>, <code>Pow</code>, <code>Neg</code>, integer/float dispatch</p></div>
<div class="mapping-card"><h4>String</h4><p><code>Concat</code>, <code>Repeat</code>, <code>Length</code>, interpolation, escape decoding</p></div>
<div class="mapping-card"><h4>Comparison</h4><p>Numeric (<code>==</code>, <code>!=</code>, <code><</code>, ...) + string (<code>eq</code>, <code>ne</code>, <code>lt</code>, ...) + spaceship</p></div>
<div class="mapping-card"><h4>Logical / Bitwise</h4><p><code>And</code>, <code>Or</code>, <code>Not</code>, <code>BitAnd</code>, <code>BitOr</code>, <code>BitXor</code>, shifts</p></div>
<div class="mapping-card"><h4>Control Flow</h4><p>Absolute jumps, conditional branches, <code>last</code>/<code>next</code>/<code>redo</code> labels</p></div>
<div class="mapping-card"><h4>Functions</h4><p><code>Call</code>, <code>TailCall</code>, <code>Return</code>, prototype dispatch</p></div>
<div class="mapping-card"><h4>Try / Catch</h4><p>VM exception handling: <code>try_recover_from_exception</code>, finally blocks, error propagation</p></div>
<div class="mapping-card"><h4>Frame Slots</h4><p>O(1) frame-local scalar access — bypasses pad lookup for hot registers</p></div>
<div class="mapping-card"><h4>Streaming Map</h4><p>Lazy iterator opcodes for <code>|></code> and <code>~></code> chains: produce pull-side, no intermediate vec</p></div>
</div>
<hr class="section-rule">
<!-- ═══════════════════════════════════════ -->
<!-- SECTION 7: JIT -->
<!-- ═══════════════════════════════════════ -->
<h2 class="tutorial-title"><span class="step-hash">~</span>CRANELIFT JIT</h2>
<p class="tutorial-subtitle">Tier-2 compiler. The VM detects hot blocks (loops with stable types) and hands them to <code>jit.rs</code>, which lowers bytecode to Cranelift IR, then to native machine code. NaN-boxed <code>PerlValue</code> stays the same shape across tiers, so a JIT→VM deopt is frame-pointer-swap-and-go — no value re-boxing.</p>
<div class="feature-grid">
<div class="feature-card"><h4>Cranelift Backend</h4><p>x86-64 + aarch64 native code generation. Same IR backend as Wasmtime — production-grade register allocator, optimizer, and code emitter.</p></div>
<div class="feature-card"><h4>Block-Level Compilation</h4><p>Cranelift compiles individual basic blocks of bytecode, not whole functions. Lower latency than method-JIT; warm-up cost amortized across invocations.</p></div>
<div class="feature-card"><h4>Hot-Path Detection</h4><p>VM tracks per-block invocation counts and type stability. Once a threshold is crossed and types haven’t shifted, the block is compiled.</p></div>
<div class="feature-card"><h4>Deoptimization</h4><p>Type guard miss in JIT'd code branches back into the VM at the same bytecode offset. Stack and frame state survive the transition.</p></div>
<div class="feature-card"><h4>Numeric Specialization</h4><p>Tight integer / float loops get specialized arithmetic with no boxing. NaN-tag bits are checked once per iteration, not per op.</p></div>
<div class="feature-card"><h4>Builtin Inlining</h4><p>The 117 bytecoded builtins reachable through <code>BuiltinId</code> can be inlined directly into JIT code, skipping the dispatch table entirely.</p></div>
</div>
<hr class="section-rule">
<!-- ═══════════════════════════════════════ -->
<!-- SECTION 8: PARALLEL RUNTIME -->
<!-- ═══════════════════════════════════════ -->
<h2 class="tutorial-title"><span class="step-hash">%</span>PARALLEL RUNTIME</h2>
<p class="tutorial-subtitle">10 modules totaling 4,029 lines wrapping rayon’s work-stealing pool. Every parallel builtin is a streaming iterator under the hood: <code>pmap</code>, <code>pgrep</code>, and <code>pflat_map</code> produce lazy results that flow into pipe-forward chains without materializing intermediate vectors.</p>
<table class="file-table">
<thead><tr><th>File</th><th class="num">Lines</th><th>Role</th></tr></thead>
<tbody>
<tr><td>pmap_progress.rs</td><td class="num">755</td><td>Progress reporting for long-running parallel maps; ETA estimation; cancellation tokens</td></tr>
<tr><td>par_pipeline.rs</td><td class="num">459</td><td>Multi-stage parallel pipelines: stage fusion, cross-stage work-stealing</td></tr>
<tr><td>ppool.rs</td><td class="num">265</td><td>Worker pool wrapper around rayon: thread-count tuning, panic isolation</td></tr>
<tr><td>pchannel.rs</td><td class="num">245</td><td>Bounded MPMC channels for cross-stage handoff in <code>par_pipeline</code></td></tr>
<tr><td>par_list.rs</td><td class="num">229</td><td>Parallel list operations: <code>pmap</code>, <code>pgrep</code>, <code>pflat_map</code>, <code>pfor</code> on plain arrays</td></tr>
<tr><td>pwatch.rs</td><td class="num">197</td><td>Filesystem-watcher integration: parallel reload on file change</td></tr>
<tr><td>par_lines.rs</td><td class="num">144</td><td>Parallel line-oriented file processing: chunked reads, line-boundary recovery</td></tr>
<tr><td>par_walk.rs</td><td class="num">69</td><td>Parallel filesystem walking: <code>walk</code>, <code>fr</code> (file rec), parallel <code>find</code></td></tr>
<tr><td>parallel_trace.rs</td><td class="num">61</td><td>Tracer that records work-steal events for debugging contention</td></tr>
<tr><td>pcache.rs</td><td class="num">38</td><td>Per-worker thread-local result cache; avoids cross-thread coordination on hot reads</td></tr>
</tbody>
<tfoot><tr class="total-row"><td style="font-family:'Orbitron',sans-serif;font-size:10px;letter-spacing:1px;">PARALLEL TOTAL</td><td class="num">2,462</td><td>10 modules</td></tr></tfoot>
</table>
<hr class="section-rule">
<!-- ═══════════════════════════════════════ -->
<!-- SECTION 9: PARSER & AST -->
<!-- ═══════════════════════════════════════ -->
<h2 class="tutorial-title"><span class="step-hash">^</span>PARSER & AST</h2>
<p class="tutorial-subtitle">Recursive-descent parser with operator-precedence climbing. 187 <code>parse_*</code> functions cover the full Perl 5 grammar plus stryke extensions: pipe-forward (<code>|></code>), thread macro (<code>~></code>), match patterns, <code>class</code> blocks, named arguments, retry / backoff syntax, <code>defer</code>, <code>try</code>/<code>catch</code>/<code>finally</code>.</p>
<table class="file-table">
<thead><tr><th>Enum</th><th class="num">Variants</th><th>Role</th></tr></thead>
<tbody>
<tr><td>ExprKind</td><td class="num">187</td><td>Every expression form: literals, ops, calls, slices, regex, formats, captures</td></tr>
<tr><td>StmtKind</td><td class="num">45</td><td>Statements: <code>if</code>, <code>while</code>, <code>for</code>, <code>foreach</code>, <code>sub</code>, <code>package</code>, <code>use</code>, <code>BEGIN</code>, ...</td></tr>
<tr><td>BinOp</td><td class="num">33</td><td>Binary operators: arithmetic, comparison, logical, bitwise, string, regex bind</td></tr>
<tr><td>PerlTypeName</td><td class="num">10</td><td>Type signatures: <code>Int</code>, <code>Str</code>, <code>Array</code>, <code>Hash</code>, <code>Code</code>, <code>Ref</code>, ...</td></tr>
<tr><td>UnaryOp</td><td class="num">7</td><td>Unary: <code>-</code>, <code>!</code>, <code>~</code>, <code>defined</code>, <code>not</code>, file-test, sigil-deref</td></tr>
<tr><td>MatchPattern</td><td class="num">6</td><td>Pattern-match arms: literal, range, struct, array, alternation, guard</td></tr>
<tr><td>SubSigParam</td><td class="num">5</td><td>Subroutine signature parameters: positional, named, slurpy, default, ...</td></tr>
<tr><td>Sigil / StringPart / MatchArrayElem / GrepBuiltinKeyword</td><td class="num">4 each</td><td>Lexical detail enums for sigils, interpolation parts, match elements, grep keywords</td></tr>
</tbody>
<tfoot><tr class="total-row"><td>20 enums total</td><td class="num">334</td><td>Full AST surface area</td></tr></tfoot>
</table>
<hr class="section-rule">
<!-- ═══════════════════════════════════════ -->
<!-- SECTION 10: TESTS & PARITY -->
<!-- ═══════════════════════════════════════ -->
<h2 class="tutorial-title"><span class="step-hash">*</span>TESTS & PARITY</h2>
<p class="tutorial-subtitle">Two complementary suites. Unit + integration tests are <code>#[test]</code> functions in Rust; parity tests are <code>.pl</code> scripts that must produce byte-identical output between system perl and stryke. CI runs both on every push.</p>
<div class="stat-grid" style="grid-template-columns:repeat(auto-fill,minmax(13rem,1fr));">
<div class="stat-card"><div class="stat-val green">6,076</div><div class="stat-label">#[test] Functions</div></div>
<div class="stat-card"><div class="stat-val">2,126</div><div class="stat-label">Unit Tests</div></div>
<div class="stat-card"><div class="stat-val">2,794</div><div class="stat-label">Integration Tests</div></div>
<div class="stat-card"><div class="stat-val accent">20,058</div><div class="stat-label">Parity Cases</div></div>
<div class="stat-card"><div class="stat-val">102</div><div class="stat-label">Test Files</div></div>
<div class="stat-card"><div class="stat-val">1,995</div><div class="stat-label">Example Scripts</div></div>
</div>
<h3 style="font-family:'Orbitron',sans-serif;font-size:11px;color:var(--cyan);letter-spacing:1.5px;margin:1.5rem 0 0.5rem;">// TEST SURFACES</h3>
<div class="feature-grid">
<div class="feature-card"><h4>Parity vs Perl</h4><p>20,058 <code>.pl</code> cases under <code>parity/cases/</code>. CI runs each through both perl and stryke; any output mismatch fails the job. Catches semantic drift the unit tests miss.</p></div>
<div class="feature-card"><h4>Fix Regressions</h4><p><code>tests/suite/fix_regressions.rs</code> at 7,643 lines. One test per fixed bug. Refactors can’t silently re-break old behavior.</p></div>
<div class="feature-card"><h4>Crate API</h4><p><code>strykelang/crate_api_tests.rs</code> at 5,164 lines. Validates the embeddable interface: <code>stryke::eval</code>, <code>Interpreter</code>, public types stay stable across versions.</p></div>
<div class="feature-card"><h4>Run Semantics</h4><p><code>strykelang/run_semantics_tests.rs</code> at 5,411 lines. Behaviors that must match perl byte-for-byte: special variables, autovivification, list context.</p></div>
<div class="feature-card"><h4>Rosetta</h4><p>1,648 <code>.stk</code> programs in <code>examples/rosetta/t/</code> — canonical cross-language tasks (sort, parse JSON, fetch URL) ported into stryke. <strong>100% of <code>list.txt</code> tasks complete (1,349 / 1,349).</strong></p></div>
<div class="feature-card"><h4>Stryke Project</h4><p><code>examples/project/</code> — full multi-module project with 169 stryke files (23,714 LOC) exercising the package layout, <code>lib/</code>, <code>t/</code>.</p></div>
</div>
<hr class="section-rule">
<!-- ═══════════════════════════════════════ -->
<!-- SECTION 10b: EXAMPLES & SOLVED PROBLEMS -->
<!-- ═══════════════════════════════════════ -->
<h2 class="tutorial-title"><span class="step-hash">.</span>EXAMPLES & SOLVED PROBLEMS</h2>
<p class="tutorial-subtitle">Stryke ships with the largest curated corpus of cross-language exemplars in any single-author Perl 5 work-alike: 1,993 <code>.stk</code> programs totaling 100,247 LOC. <strong>All 1,349 Rosetta Code tasks in <code>list.txt</code> are solved (100%)</strong> — every test compiles and runs against the current build, so any builtin regression surfaces as a failing test before it reaches the parity suite.</p>
<div class="stat-grid" style="grid-template-columns:repeat(auto-fill,minmax(13rem,1fr));">
<div class="stat-card"><div class="stat-val accent">1,993</div><div class="stat-label">.stk Programs</div></div>
<div class="stat-card"><div class="stat-val">100,247</div><div class="stat-label">Total LOC</div></div>
<div class="stat-card"><div class="stat-val green">1,349</div><div class="stat-label">Rosetta Solved</div></div>
<div class="stat-card"><div class="stat-val accent">100%</div><div class="stat-label">Rosetta Complete</div></div>
<div class="stat-card"><div class="stat-val">87</div><div class="stat-label">Exercism Exercises</div></div>
<div class="stat-card"><div class="stat-val">22,236</div><div class="stat-label">Test Assertions</div></div>
</div>
<h3 style="font-family:'Orbitron',sans-serif;font-size:11px;color:var(--cyan);letter-spacing:1.5px;margin:1.5rem 0 0.5rem;">// CORPUS BREAKDOWN</h3>
<table class="file-table">
<thead><tr><th>Corpus</th><th>Path</th><th class="num">Files</th><th class="num">LOC</th><th>Status</th></tr></thead>
<tbody>
<tr><td style="color:var(--accent);">Rosetta Code</td><td><code>examples/rosetta/t/</code></td><td class="num">1,648</td><td class="num">73,687</td><td><strong>All 1,349 of 1,349 problems in <code>list.txt</code> solved (100%).</strong> Avg 45 LOC/test. Largest: <code>heavy_light</code> 189, <code>red_black_tree</code> 179, <code>baum_welch</code> 177, <code>strassen</code> 168, <code>delaunay</code> 167.</td></tr>
<tr><td style="color:var(--accent);">Sample Project</td><td><code>examples/project/</code></td><td class="num">168</td><td class="num">23,714</td><td>Multi-module mini-project: <code>lib/</code> namespaces + <code>t/</code> test layout exercising the package manager, <code>use</code> resolution, namespace dispatch.</td></tr>
<tr><td style="color:var(--accent);">Exercism</td><td><code>examples/exercism/</code></td><td class="num">174</td><td class="num">2,777</td><td>87 exercises (one solution + tests each). Avg 32 LOC. Polyglot <code>.exercism.json</code> compatible.</td></tr>
<tr><td style="color:var(--accent);">Top-level</td><td><code>examples/*.stk</code></td><td class="num">3</td><td class="num">69</td><td><code>fibonacci</code>, <code>parallel_demo</code>, <code>text_processing</code> — quick-start demos.</td></tr>
</tbody>
<tfoot><tr class="total-row"><td colspan="2" style="font-family:'Orbitron',sans-serif;font-size:10px;letter-spacing:1px;">EXAMPLES TOTAL</td><td class="num">1,993</td><td class="num">100,247</td><td>4 dirs · ~50 LOC/file avg</td></tr></tfoot>
</table>
<p style="font-size:11px;color:var(--text-muted);margin-top:0.8rem;">The Rosetta corpus is a complete cross-language reference port at 1,349/1,349 (100%). The full test runner (<code>s test examples/project/t examples/rosetta/t</code>) executes 1,750 test files and 22,236 <code>assert_eq</code> / <code>assert_ok</code> assertions; any builtin drift surfaces as a failing test before it reaches the parity suite. New Rosetta tasks land as fast as the canonical site adds them.</p>
<hr class="section-rule">
<!-- ═══════════════════════════════════════ -->
<!-- SECTION 11: DEPENDENCIES -->
<!-- ═══════════════════════════════════════ -->
<h2 class="tutorial-title"><span class="step-hash">+</span>DEPENDENCIES</h2>
<p class="tutorial-subtitle">130 direct dependencies, 679 transitive crates in <code>Cargo.lock</code>. Every dep is audited against the “will this still build cleanly in 2030” bar — foundational crates (<code>serde</code>, <code>regex</code>, <code>libc</code>, <code>nix</code>) over fashionable ones.</p>
<div class="mapping-grid">
<div class="mapping-card"><h4>Core Runtime</h4><p><code>rayon</code>, <code>crossbeam</code>, <code>parking_lot</code>, <code>dashmap</code>, <code>indexmap</code>, <code>thiserror</code></p></div>
<div class="mapping-card"><h4>JIT</h4><p><code>cranelift-codegen</code>, <code>cranelift-frontend</code>, <code>cranelift-jit</code>, <code>cranelift-module</code></p></div>
<div class="mapping-card"><h4>Regex</h4><p><code>regex</code>, <code>fancy-regex</code> — standard + lookahead/behind / backref engine</p></div>
<div class="mapping-card"><h4>Codec</h4><p><code>serde_json</code>, <code>serde_yaml</code>, <code>toml</code>, <code>csv</code>, <code>rmp-serde</code> (MessagePack)</p></div>
<div class="mapping-card"><h4>Crypto</h4><p><code>aes</code>, <code>chacha20</code>, <code>rsa</code>, <code>ed25519-dalek</code>, <code>x25519-dalek</code>, <code>p256</code>, <code>p384</code>, <code>k256</code>, <code>argon2</code>, <code>scrypt</code>, <code>bcrypt</code>, <code>sha2</code>, <code>sha3</code>, <code>blake3</code>, <code>ripemd</code>, <code>md4</code>, <code>md-5</code></p></div>
<div class="mapping-card"><h4>HTTP / Network</h4><p><code>ureq</code>, <code>scraper</code>, <code>roxmltree</code>, <code>uuid</code>, TCP / DNS via <code>libc</code>+<code>nix</code></p></div>
<div class="mapping-card"><h4>Output</h4><p><code>svg2pdf</code>, <code>pdf-extract</code>, <code>id3</code>, <code>mp3lame-encoder</code>, <code>qrcode</code></p></div>
<div class="mapping-card"><h4>CLI</h4><p><code>clap</code> (no default features), <code>itoa</code>, <code>caseless</code>, <code>glob</code>, <code>libc</code></p></div>
<div class="mapping-card"><h4>LSP</h4><p><code>lsp-server</code>, <code>serde</code>, <code>serde_derive</code></p></div>
<div class="mapping-card"><h4>System</h4><p><code>sysinfo</code>, <code>nix</code>, <code>libc</code>, <code>rand</code>, <code>lru</code>, <code>itertools</code>, <code>totp-lite</code></p></div>
</div>
<hr class="section-rule">
<!-- ═══════════════════════════════════════ -->
<!-- SECTION 12: PUBLIC API SURFACE -->
<!-- ═══════════════════════════════════════ -->
<h2 class="tutorial-title"><span class="step-hash">;</span>PUBLIC API SURFACE</h2>
<p class="tutorial-subtitle">strykelang ships as both a binary (<code>stryke</code>, <code>st</code>, <code>s</code>) and an embeddable Rust crate (<code>stryke</code> on docs.rs). The public surface stays small relative to internals — embedders get the high-level entry points; the rest is implementation.</p>
<table class="file-table">
<thead><tr><th>Surface</th><th class="num">Count</th><th>Notes</th></tr></thead>
<tbody>
<tr><td>Public functions</td><td class="num">645</td><td>Across the whole repo — <code>pub fn</code> at every visibility level</td></tr>
<tr><td>Public structs</td><td class="num">87</td><td>Plus 112 internal structs (199 total)</td></tr>
<tr><td>Public enums</td><td class="num">41</td><td>Plus 33 internal enums (74 total)</td></tr>
<tr><td>Impl blocks</td><td class="num">185</td><td>Across both data and trait impls</td></tr>
<tr><td>Total fns (any vis)</td><td class="num">9,611</td><td>Including methods, closures, and inline fns</td></tr>
</tbody>
</table>
<hr class="section-rule">
<!-- ═══════════════════════════════════════ -->
<!-- SECTION 13: KEY DESIGN DECISIONS -->
<!-- ═══════════════════════════════════════ -->
<h2 class="tutorial-title"><span class="step-hash">?</span>KEY DESIGN DECISIONS</h2>
<p class="tutorial-subtitle">Why stryke looks the way it does. Each call-out below is a decision the implementation could have gone either way on, with the rationale for the path taken.</p>
<div class="feature-grid">
<div class="feature-card"><h4>NaN-Boxed PerlValue</h4><p>Every value is one 64-bit word. Tag bits live in the unused mantissa of an IEEE-754 NaN. Saves a pointer indirection on every read; keeps the JIT’s register allocator happy with uniform value width.</p></div>
<div class="feature-card"><h4>Bytecode VM, Not Tree-Walker</h4><p>An AST tree-walker is simpler but pays a virtual-call cost per node. Bytecode collapses that into a dense dispatch loop, which the CPU’s branch predictor can actually warm up to.</p></div>
<div class="feature-card"><h4>Cranelift, Not LLVM</h4><p>LLVM gives slightly better steady-state code but compiles 10× slower and pulls in a giant C++ dependency. Cranelift is pure Rust, fast to compile, and ships in Wasmtime — production-tested.</p></div>
<div class="feature-card"><h4>Rayon, Not Tokio</h4><p>Stryke parallelism is data-parallel, not async-IO-parallel. Rayon’s work-stealing fits <code>pmap</code>/<code>pgrep</code> exactly; tokio’s task model would force every callback into a future.</p></div>
<div class="feature-card"><h4>Streaming Iterators</h4><p><code>pmap</code> doesn’t materialize a vec before <code>pgrep</code> consumes it. <code>map_stream.rs</code> threads results pull-side through pipe-forward chains; only the final sink pays the allocation.</p></div>
<div class="feature-card"><h4>Single Cargo Package</h4><p>Stryke is one crate, three binaries (<code>stryke</code>/<code>st</code>/<code>s</code>) and a library. No workspace, no internal sub-crates — rebuilds are smaller, dependency graph is shallow, embedders see a flat API.</p></div>
<div class="feature-card"><h4>Build-Time Reflection</h4><p><code>build.rs</code> scans the dispatcher source and generates <code>%builtins</code>, <code>%aliases</code>, <code>%descriptions</code>. Source is the single truth; LSP descriptions can’t drift from the actual dispatcher.</p></div>
<div class="feature-card"><h4>Pipe-Forward + Thread Macro</h4><p><code>|></code> and <code>~></code> aren’t cosmetic — they’re first-class parser productions that compile into streaming-iterator opcodes. Reading left-to-right is the point; allocation-free chains are the dividend.</p></div>
<div class="feature-card"><h4>AOP at the Call Site</h4><p><code>before</code> / <code>after</code> / <code>around</code> register advice into a single <code>Vec<Intercept></code> on the interpreter. <code>vm_dispatch_user_call</code> takes a one-line glob-match guard before the existing fast-path, so calls with no intercepts pay zero overhead. Around is AspectJ-style: the block’s value is the call’s return; <code>proceed()</code> invokes the original. Same surface as zshrs <code>intercept</code> — one design across CLI and language.</p></div>
</div>
</main>
<footer style="text-align:center;padding:2rem;font-size:10px;color:var(--text-muted);font-family:'Orbitron',sans-serif;letter-spacing:2px;">
STRYKELANG ENGINEERING REPORT · 309,285 RUST LINES · 109,527 STRYKE LINES · 6,076 TESTS · 8,548 BUILTINS / 9,081 SPELLINGS · MENKETECHNOLOGIES
</footer>
</div>
<script>
const html = document.documentElement;
const btnTheme = document.getElementById('btnTheme');
const btnCrt = document.getElementById('btnCrt');
const btnNeon = document.getElementById('btnNeon');
const crtH = document.getElementById('crtH');
const crtV = document.getElementById('crtV');
btnTheme?.addEventListener('click', () => {
html.setAttribute('data-theme', html.getAttribute('data-theme') === 'light' ? 'dark' : 'light');
});
btnCrt?.addEventListener('click', () => {
btnCrt.classList.toggle('active');
const on = btnCrt.classList.contains('active');
if (crtH) crtH.style.display = on ? '' : 'none';
if (crtV) crtV.style.display = on ? '' : 'none';
});
btnNeon?.addEventListener('click', () => {
btnNeon.classList.toggle('active');
document.querySelector('.app')?.classList.toggle('neon-off');
});
document.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('.bar-fill').forEach(bar => {
const w = bar.style.width;
bar.style.width = '0';
requestAnimationFrame(() => { requestAnimationFrame(() => { bar.style.width = w; }); });
});
});
</script>
</body>
</html>