<!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: 198k lines, 4.8k tests, 3.7k builtins, 338 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 338-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.</p>
<div class="stat-grid">
<div class="stat-card"><div class="stat-val">198,178</div><div class="stat-label">Rust Lines</div></div>
<div class="stat-card"><div class="stat-val">182</div><div class="stat-label">Source Files</div></div>
<div class="stat-card"><div class="stat-val accent">3,737</div><div class="stat-label">Builtins (Callable)</div></div>
<div class="stat-card"><div class="stat-val green">4,796</div><div class="stat-label">Test Functions</div></div>
<div class="stat-card"><div class="stat-val">338</div><div class="stat-label">VM Opcodes</div></div>
<div class="stat-card"><div class="stat-val">330</div><div class="stat-label">AST Variants</div></div>
<div class="stat-card"><div class="stat-val">20,056</div><div class="stat-label">Parity Cases</div></div>
<div class="stat-card"><div class="stat-val">757</div><div class="stat-label">Example Scripts</div></div>
<div class="stat-card"><div class="stat-val">128</div><div class="stat-label">Direct Dependencies</div></div>
<div class="stat-card"><div class="stat-val">776</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 — 198,178 lines</p>
<div class="bar-wrap" style="height:26px;">
<div class="bar-fill cyan" style="width:78.5%;"></div>
<span class="bar-pct" style="font-size:12px;">155,606 production / 41,219 tests / 1,353 tooling · 78.5% production</span>
</div>
<p style="font-size:10px;color:var(--text-muted);margin-top:4px;">Production: 79 files in <code>strykelang/</code> excluding <code>*_tests.rs</code>. Tests: 17 inline test files in <code>strykelang/</code> + 81 integration files in <code>tests/</code>. Tooling: <code>build.rs</code>, <code>benches/</code>, <code>scripts/</code>, debug examples.</p>
</div>
<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 21% — the language ships with 3,737 callable names spanning string / array / hash / regex / I/O / process / OO / format / pack / crypto / codec / parallel / HTTP / database / network domains. Core pipeline (lexer→parser→compiler→VM→JIT) is 23%.</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</code></td><td class="num">42,597</td><td class="num">21.5%</td><td><div class="bar-wrap"><div class="bar-fill magenta" style="width:21.5%"></div></div></td><td>3,737 callable names: string, array, hash, regex, math, 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">21,006</td><td class="num">10.6%</td><td><div class="bar-wrap"><div class="bar-fill cyan" style="width:10.6%"></div></div></td><td>338-opcode bytecode, register+stack VM, AST→bytecode compiler with constant folding / register allocation / peephole, opcode disassembler</td></tr>
<tr><td style="color:var(--accent);">Interpreter</td><td><code>interpreter</code></td><td class="num">19,416</td><td class="num">9.8%</td><td><div class="bar-wrap"><div class="bar-fill cyan" style="width:9.8%"></div></div></td><td>Runtime state: scope graph, error context, debugger hooks, special variables (<code>$_</code>, <code>$!</code>, <code>$/</code>, ...)</td></tr>
<tr><td style="color:var(--accent);">Parser</td><td><code>parser, ast, token</code></td><td class="num">17,546</td><td class="num">8.9%</td><td><div class="bar-wrap"><div class="bar-fill cyan" style="width:8.9%"></div></div></td><td>Recursive-descent parser, 187 <code>parse_*</code> functions, 330 AST variants across 19 enums, operator precedence climbing, heredocs, prototype parsing</td></tr>
<tr><td style="color:var(--accent);">Value System</td><td><code>value, nanbox, scope, capture, convert, deconvert</code></td><td class="num">8,634</td><td class="num">4.4%</td><td><div class="bar-wrap"><div class="bar-fill cyan" style="width:4.4%"></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>), 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,297</td><td class="num">3.2%</td><td><div class="bar-wrap"><div class="bar-fill cyan" style="width:3.2%"></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);">JIT</td><td><code>jit</code></td><td class="num">5,172</td><td class="num">2.6%</td><td><div class="bar-wrap"><div class="bar-fill cyan" style="width:2.6%"></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);">Distribution</td><td><code>cluster, controller, agent, remote_wire, pkg/*, script_cache</code></td><td class="num">4,904</td><td class="num">2.5%</td><td><div class="bar-wrap"><div class="bar-fill cyan" style="width:2.5%"></div></div></td><td>Multi-host cluster execution, agent / controller protocol, wire format, package manager (<code>pkg</code>), bytecode cache for fast startup</td></tr>
<tr><td style="color:var(--accent);">CLI & REPL</td><td><code>main, repl</code></td><td class="num">4,747</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>CLI entry: argv parsing, script loading, one-liner mode (<code>-e</code>/<code>-E</code>/<code>-n</code>/<code>-p</code>), REPL with line editor</td></tr>
<tr><td style="color:var(--accent);">Format / Deparse</td><td><code>fmt, deparse, format</code></td><td class="num">4,222</td><td class="num">2.1%</td><td><div class="bar-wrap"><div class="bar-fill cyan" style="width:2.1%"></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);">LSP</td><td><code>lsp</code></td><td class="num">4,141</td><td class="num">2.1%</td><td><div class="bar-wrap"><div class="bar-fill cyan" style="width:2.1%"></div></div></td><td>Language Server Protocol: 2,696 hover descriptions, completion, diagnostics, go-to-definition, document symbols</td></tr>
<tr><td style="color:var(--accent);">Lexer</td><td><code>lexer</code></td><td class="num">2,860</td><td class="num">1.4%</td><td><div class="bar-wrap"><div class="bar-fill cyan" style="width:1.4%"></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);">Perl Compat</td><td><code>perl_decode, perl_fs, perl_inc, perl_regex, perl_signal, special_vars, english</code></td><td class="num">2,511</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, magic special variables, <code>use English</code></td></tr>
<tr><td style="color:var(--accent);">Parallel Runtime</td><td><code>par_lines, par_list, par_pipeline, par_walk, ppool, pchannel, pcache, pwatch, pmap_progress, parallel_trace</code></td><td class="num">2,462</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>Rayon work-stealing: <code>pmap</code>, <code>pgrep</code>, <code>pflat_map</code>, <code>pfor</code>, parallel file walking, async pipelines, progress tracking, channels</td></tr>
<tr><td style="color:var(--accent);">Tooling</td><td><code>debugger, profiler, static_analysis</code></td><td class="num">2,185</td><td class="num">1.1%</td><td><div class="bar-wrap"><div class="bar-fill cyan" style="width:1.1%"></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</code></td><td class="num">1,698</td><td class="num">0.9%</td><td><div class="bar-wrap"><div class="bar-fill cyan" style="width:0.9%"></div></div></td><td>Embed-Rust closure FFI, AOT bytecode caching, data-section relocations</td></tr>
<tr><td style="color:var(--accent);">Crypto / Pack</td><td><code>crypt_util, jwt, pack</code></td><td class="num">1,472</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>Symmetric / asymmetric encryption, password hashing, JWT encode/decode, <code>pack</code>/<code>unpack</code> templates</td></tr>
<tr><td style="color:var(--accent);">Misc</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,736</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>Rich error reporter, MRO (C3 / DFS), library entry, fusion-pass optimizers, finalizer queue, doc generator, smoke tests</td></tr>
<tr><td style="color:var(--green);">Tests</td><td><code>tests/suite/*, *_tests.rs</code></td><td class="num">41,219</td><td class="num">20.8%</td><td><div class="bar-wrap"><div class="bar-fill green" style="width:20.8%"></div></div></td><td>4,796 <code>#[test]</code> functions across 164 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/, scripts/</code></td><td class="num">1,353</td><td class="num">0.7%</td><td><div class="bar-wrap"><div class="bar-fill yellow" style="width:0.7%"></div></div></td><td>Build-time reflection generator, micro-benches, debug helpers</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">198,178</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 84% of the codebase. Builtins is by far the largest single file: every Perl 5 core function plus stryke extensions (HTTP, JSON, parallel, codec, OO) 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">28,226</td><td>Core builtin dispatch table; 1,528 functions covering string/array/hash/regex/math/I/O/file/process/OO domains</td></tr>
<tr><td>strykelang/interpreter.rs</td><td class="num">19,416</td><td>Runtime: scope graph, evaluation context, error reporter, debugger hooks, special-variable handling</td></tr>
<tr><td>strykelang/parser.rs</td><td class="num">15,425</td><td>Recursive-descent parser; 187 <code>parse_*</code> functions across 258 total fns; precedence climbing, heredocs</td></tr>
<tr><td>strykelang/builtins_extended.rs</td><td class="num">12,518</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">9,763</td><td>Bytecode VM: register+stack hybrid, 338 opcodes, hot-path detection, exception unwinder</td></tr>
<tr><td>strykelang/compiler.rs</td><td class="num">8,833</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,580</td><td>Regression test suite — one test per fixed bug; pin behaviors so refactors can’t silently re-break</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,161</td><td>Public crate-API test suite: validates the embeddable interface (<code>stryke::eval</code>, <code>Interpreter</code>, ...)</td></tr>
<tr><td>strykelang/run_semantics_tests.rs</td><td class="num">4,673</td><td>Perl-semantics correctness suite: behaviors that must match perl byte-for-byte</td></tr>
<tr><td>strykelang/main.rs</td><td class="num">4,462</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,207</td><td><code>PerlValue</code>: NaN-boxed union, conversions, stringify / numify, magic context handling</td></tr>
<tr><td>strykelang/lsp.rs</td><td class="num">4,141</td><td>Language Server Protocol: 2,696 hover descriptions, completion, diagnostics, document symbols</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/lexer.rs</td><td class="num">2,860</td><td>Tokenizer: 157 fns; heredocs, regex literals, <code>q/qq/qw/qr</code>, string interpolation, sigil disambiguation</td></tr>
<tr><td>strykelang/scope.rs</td><td class="num">2,450</td><td>Lexical scoping: pad slots, closures, <code>my</code>/<code>local</code>/<code>our</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,410</td><td>Opcode definitions (338 variants), instruction encoding, disassembler</td></tr>
<tr><td>strykelang/deparse.rs</td><td class="num">2,084</td><td>AST→source: <code>B::Deparse</code> equivalent, round-trip fidelity for <code>perl -MO=Deparse</code></td></tr>
<tr><td>strykelang/list_builtins.rs</td><td class="num">1,853</td><td><code>List::Util</code>: <code>reduce</code>, <code>any</code>, <code>all</code>, <code>none</code>, <code>first</code>, <code>max</code>, <code>min</code>, <code>sum</code>, <code>product</code>, <code>shuffle</code>, <code>uniq</code>, <code>zip</code>, <code>pairs</code></td></tr>
<tr><td>strykelang/map_stream.rs</td><td class="num">1,735</td><td>Streaming map / grep / flat-map: lazy iterators feeding pipe-forward chains</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">146,322</td><td>73.8% 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 │
│ (2,860) │ │ (15,425) │ │ (8,833) │
│ Tokenizer │ │ 330 AST │ │ 338 opcodes │
│ heredocs │ │ variants │ │ const fold │
│ regex lit │ │ prec climb │ │ reg alloc │
│ q/qq/qw/qr │ │ 187 parse_*│ │ peephole │
└─────────────┘ └─────────────┘ └──────┬───────┘
│
┌────────────────────┤
│ │
▼ ▼
┌──────────────┐ ┌──────────────┐
│ vm.rs │ │ jit.rs │
│ (9,763) │ │ (5,172) │
│ Bytecode VM │ │ Cranelift │
│ reg + stack │ │ block JIT │
│ hot detect │────▶│ native code │
│ exc unwind │◀────│ deopt stubs │
└──────┬───────┘ └──────────────┘
│
▼
┌───────────────────┐
│ builtins.rs │
│ (28,226) │
│ 3,737 callables │
│ + extended │
│ (12,518) │
└─────────┬─────────┘
│
┌────────────────┼─────────────────┐
│ │ │
┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐
│ value.rs │ │ scope.rs │ │ parallel │
│ (4,207) │ │ (2,450) │ │ (3,891) │
│ NaN-boxed │ │ my/local │ │ pmap/pgrep │
│ PerlValue │ │ closures │ │ 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>%builtins</code>, <code>%aliases</code>, <code>%descriptions</code> hashes.</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">3,737</div><div class="stat-label">Total Callables</div></div>
<div class="stat-card" style="border-top-color:var(--accent);"><div class="stat-val accent">3,229</div><div class="stat-label">Primaries</div></div>
<div class="stat-card" style="border-top-color:var(--accent);"><div class="stat-val accent">508</div><div class="stat-label">Aliases</div></div>
<div class="stat-card" style="border-top-color:var(--cyan);"><div class="stat-val">207</div><div class="stat-label">Perl 5 Core</div></div>
<div class="stat-card" style="border-top-color:var(--cyan);"><div class="stat-val">3,022</div><div class="stat-label">Stryke Extensions</div></div>
<div class="stat-card" style="border-top-color:var(--cyan);"><div class="stat-val">2,696</div><div class="stat-label">LSP Descriptions</div></div>
<div class="stat-card" style="border-top-color:var(--cyan);"><div class="stat-val">2,230</div><div class="stat-label">Match Arms</div></div>
<div class="stat-card" style="border-top-color:var(--cyan);"><div class="stat-val">117</div><div class="stat-label">Bytecoded Builtins</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 508-alias overhead exists so canonical Perl spellings (<code>localtime</code>), abbreviations (<code>tj</code>), and stryke-style snake_case alternatives all coexist without disambiguation.</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>%builtins</code>, <code>%aliases</code>, <code>%descriptions</code>, <code>caller</code>, <code>__PACKAGE__</code>, <code>__SUB__</code>, runtime introspection</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">338 opcodes grouped into 27 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 3,891 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>19 enums total</td><td class="num">330</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">4,796</div><div class="stat-label">#[test] Functions</div></div>
<div class="stat-card"><div class="stat-val">2,052</div><div class="stat-label">Unit Tests</div></div>
<div class="stat-card"><div class="stat-val">2,744</div><div class="stat-label">Integration Tests</div></div>
<div class="stat-card"><div class="stat-val accent">20,056</div><div class="stat-label">Parity Cases</div></div>
<div class="stat-card"><div class="stat-val">164</div><div class="stat-label">Test Files</div></div>
<div class="stat-card"><div class="stat-val">757</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,056 <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,580 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,161 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 4,673 lines. Behaviors that must match perl byte-for-byte: special variables, autovivification, list context.</p></div>
<div class="feature-card"><h4>Rosetta</h4><p>584 <code>.stk</code> programs in <code>examples/rosetta/</code> — canonical cross-language tasks (sort, parse JSON, fetch URL) ported into stryke.</p></div>
<div class="feature-card"><h4>Stryke Project</h4><p><code>examples/project/</code> — full multi-module project with 168 stryke files and 103 test files exercising the package layout, <code>lib/</code>, <code>t/</code>.</p></div>
</div>
<hr class="section-rule">
<!-- ═══════════════════════════════════════ -->
<!-- SECTION 11: DEPENDENCIES -->
<!-- ═══════════════════════════════════════ -->
<h2 class="tutorial-title"><span class="step-hash">+</span>DEPENDENCIES</h2>
<p class="tutorial-subtitle">128 direct dependencies, 657 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 · 198,178 LINES · 4,796 TESTS · 3,737 BUILTINS · 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>