strykelang 0.11.0

A highly parallel Perl 5 interpreter written in Rust
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
<!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 &mdash; 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 &mdash; 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 &middot; NaN-boxed bytecode VM &middot; Cranelift JIT &middot; Rayon work-stealing &middot; pipe-forward (<code>|&gt;</code>) and thread macro (<code>~&gt;</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">&gt;_</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>|&gt;</code>) and the thread macro (<code>~&gt;</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 &mdash; 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 &middot; 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% &mdash; 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&rarr;parser&rarr;compiler&rarr;VM&rarr;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 &amp; 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&rarr;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 &amp; 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&rarr;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&rarr;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 &mdash; one test per fixed bug; pin behaviors so refactors can&rsquo;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&rarr;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&rarr;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 &#39;...&#39;)
       │
       ▼
  ┌─────────────┐     ┌─────────────┐     ┌──────────────┐
  │  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">&amp;</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> &mdash; 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 &amp; BYTECODE                -->
      <!-- ═══════════════════════════════════════ -->
      <h2 class="tutorial-title"><span class="step-hash">!</span>VM &amp; 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>&lt;</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 &mdash; bypasses pad lookup for hot registers</p></div>
        <div class="mapping-card"><h4>Streaming Map</h4><p>Lazy iterator opcodes for <code>|&gt;</code> and <code>~&gt;</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&rarr;VM deopt is frame-pointer-swap-and-go &mdash; 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 &mdash; 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&rsquo;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&rsquo;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 &amp; AST                 -->
      <!-- ═══════════════════════════════════════ -->
      <h2 class="tutorial-title"><span class="step-hash">^</span>PARSER &amp; 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>|&gt;</code>), thread macro (<code>~&gt;</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 &amp; PARITY              -->
      <!-- ═══════════════════════════════════════ -->
      <h2 class="tutorial-title"><span class="step-hash">*</span>TESTS &amp; 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&rsquo;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> &mdash; 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> &mdash; 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 &ldquo;will this still build cleanly in 2030&rdquo; bar &mdash; 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> &mdash; 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 &mdash; 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 &mdash; <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&rsquo;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&rsquo;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&times; slower and pulls in a giant C++ dependency. Cranelift is pure Rust, fast to compile, and ships in Wasmtime &mdash; production-tested.</p></div>
        <div class="feature-card"><h4>Rayon, Not Tokio</h4><p>Stryke parallelism is data-parallel, not async-IO-parallel. Rayon&rsquo;s work-stealing fits <code>pmap</code>/<code>pgrep</code> exactly; tokio&rsquo;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&rsquo;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 &mdash; 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&rsquo;t drift from the actual dispatcher.</p></div>
        <div class="feature-card"><h4>Pipe-Forward + Thread Macro</h4><p><code>|&gt;</code> and <code>~&gt;</code> aren&rsquo;t cosmetic &mdash; they&rsquo;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&lt;Intercept&gt;</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&rsquo;s value is the call&rsquo;s return; <code>proceed()</code> invokes the original. Same surface as zshrs <code>intercept</code> &mdash; 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 &middot; 198,178 LINES &middot; 4,796 TESTS &middot; 3,737 BUILTINS &middot; 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>