<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Miron Tuteyshi</title>
    <description>The latest articles on DEV Community by Miron Tuteyshi (@miron_tuteyshi_2bc4f14ec6).</description>
    <link>https://dev.to/miron_tuteyshi_2bc4f14ec6</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4078393%2Fddc1901a-cabd-4249-9d4c-c7af2c5537cf.jpg</url>
      <title>DEV Community: Miron Tuteyshi</title>
      <link>https://dev.to/miron_tuteyshi_2bc4f14ec6</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/miron_tuteyshi_2bc4f14ec6"/>
    <language>en</language>
    <item>
      <title>Designing a Stack-Based VM in Rust: 44 Instructions, Dual Backends, and Zero-Cost Security Types</title>
      <dc:creator>Miron Tuteyshi</dc:creator>
      <pubDate>Sat, 15 Aug 2026 02:58:14 +0000</pubDate>
      <link>https://dev.to/miron_tuteyshi_2bc4f14ec6/designing-a-stack-based-vm-in-rust-44-instructions-dual-backends-and-zero-cost-security-types-58df</link>
      <guid>https://dev.to/miron_tuteyshi_2bc4f14ec6/designing-a-stack-based-vm-in-rust-44-instructions-dual-backends-and-zero-cost-security-types-58df</guid>
      <description>&lt;h1&gt;
  
  
  Designing a Stack-Based VM in Rust: 44 Instructions, Dual Backends, and Zero-Cost Security Types
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;A deep dive into the architecture of Metalogos — how 30,500 lines of Rust implement a language where XSS and SQL injection are compile-time errors, and why two execution backends crosscheck every program.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Most programming languages treat security as an external concern — linters, SAST tools, code review. Metalogos takes a different approach: security constraints are enforced by the type system and erased before execution. This post explores the Rust implementation behind that idea, focusing on architectural decisions that are reusable beyond this specific language.&lt;/p&gt;

&lt;p&gt;The codebase is ~30,500 lines of Rust, 91 Architecture Decision Records (ADRs), and two execution backends that must agree on every program's output. It is not a toy. It is not a DSL. It is a compiler, a bytecode VM, an HTTP server, a semantic memory engine, and a security audit tool — all in one workspace.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The Grammar as Contract
&lt;/h2&gt;

&lt;p&gt;The parser is a Pest 2.7 PEG grammar: 384 lines, ~180 rules. This was the first component built, and it remained stable for 18 months while everything else changed underneath it.&lt;/p&gt;

&lt;p&gt;Why PEG over LALR or a hand-written recursive descent parser? Two reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Operator precedence is declarative.&lt;/strong&gt; In Pest, &lt;code&gt;~&lt;/code&gt; (sequence) and &lt;code&gt;|&lt;/code&gt; (ordered choice) make precedence explicit without left-factoring boilerplate. Metalogos has custom syntax for fluid types (&lt;code&gt;Float[42.0][0.9] or String["answer"][0.1]&lt;/code&gt;) and learnable patterns (&lt;code&gt;learnable pattern Classify(msg: String) -&amp;gt; String&lt;/code&gt;). PEG handles this without a separate lexer stage.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The grammar is the spec.&lt;/strong&gt; Every ADR that changes syntax starts with a grammar rule. If the grammar doesn't parse it, the feature doesn't exist. This eliminated an entire class of "parser drift" bugs where the AST and parser disagree.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The AST has 27 declaration variants, 14 expression types, 12 statement types, and 4 match arm patterns. All nodes use arena-friendly structures — mostly &lt;code&gt;Box&lt;/code&gt; and &lt;code&gt;Vec&lt;/code&gt; — with shared ownership via &lt;code&gt;Rc&lt;/code&gt; where the semantic analyzer needs to reference the same node from multiple contexts.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Dual Backends: Correctness Through Disagreement
&lt;/h2&gt;

&lt;p&gt;Metalogos has two execution backends with identical semantics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tree-walking interpreter&lt;/strong&gt; (~4,400 LOC): Recursive evaluation of the AST. Full feature support, including all 246+ builtins.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bytecode VM&lt;/strong&gt; (44 instructions, ~2,100 LOC): Stack-based execution of compiled bytecode.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every program runs through both. If the outputs differ, the test fails. This is not property-based testing. It is a structural guarantee that the compiler and interpreter implement the same semantics.&lt;/p&gt;

&lt;h3&gt;
  
  
  The 13 Parity Gaps
&lt;/h3&gt;

&lt;p&gt;Recently, a systematic audit (Наряд №72) found 13 hidden divergence points between the interpreter and VM. These were not crashes — they were subtle semantic differences:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rule priority sorting: the interpreter used stable sort, the VM evaluated rules in declaration order.&lt;/li&gt;
&lt;li&gt;Collections flag propagation: the compiler tracked &lt;code&gt;collections_loaded&lt;/code&gt; but never passed it to the VM's &lt;code&gt;Program&lt;/code&gt; struct, so &lt;code&gt;map&lt;/code&gt;/&lt;code&gt;filter&lt;/code&gt;/&lt;code&gt;reduce&lt;/code&gt; were silently unavailable in VM mode.&lt;/li&gt;
&lt;li&gt;Lenient testing: VM mismatches were reported as "skipped" rather than failures, masking drift.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All 13 were fixed. ADR-0075 documents the crosscheck methodology: 58/58 test programs now pass with zero both-error cases — every match is a genuine both-success.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Two Backends?
&lt;/h3&gt;

&lt;p&gt;The interpreter is the reference implementation. It is slow but obviously correct. The VM is the production target. It is faster (~3-5x) but complex. The crosscheck ensures that complexity does not introduce semantic bugs.&lt;/p&gt;

&lt;p&gt;This pattern is reusable: any system with a reference implementation and an optimized implementation can use crosscheck validation. The cost is ~40% more implementation time. The benefit is confidence that unit tests cannot provide.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. The VM: 44 Instructions and a Stack
&lt;/h2&gt;

&lt;p&gt;The VM is intentionally minimal. One opcode per action. Everything non-primitive is a builtin call.&lt;/p&gt;

&lt;h3&gt;
  
  
  Instruction Categories
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Constants and variables:&lt;/strong&gt; &lt;code&gt;Const&lt;/code&gt;, &lt;code&gt;LoadGlobal&lt;/code&gt;, &lt;code&gt;LoadGlobalByName&lt;/code&gt;, &lt;code&gt;StoreGlobal&lt;/code&gt;, &lt;code&gt;LoadLocal&lt;/code&gt;, &lt;code&gt;StoreLocal&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Calls:&lt;/strong&gt; &lt;code&gt;CallBuiltin(arity, index)&lt;/code&gt;, &lt;code&gt;CallPattern(arity, index)&lt;/code&gt;, &lt;code&gt;Return&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Arithmetic and comparison:&lt;/strong&gt; &lt;code&gt;Add&lt;/code&gt;, &lt;code&gt;Sub&lt;/code&gt;, &lt;code&gt;Mul&lt;/code&gt;, &lt;code&gt;Div&lt;/code&gt;, &lt;code&gt;CmpGt&lt;/code&gt;, &lt;code&gt;CmpLt&lt;/code&gt;, &lt;code&gt;CmpGe&lt;/code&gt;, &lt;code&gt;CmpLe&lt;/code&gt;, &lt;code&gt;CmpEq&lt;/code&gt;, &lt;code&gt;CmpNe&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Structs and lists:&lt;/strong&gt; &lt;code&gt;MakeStruct&lt;/code&gt;, &lt;code&gt;GetField&lt;/code&gt;, &lt;code&gt;IndexAccess&lt;/code&gt;, &lt;code&gt;MakeList&lt;/code&gt;, &lt;code&gt;ListLen&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Control flow:&lt;/strong&gt; &lt;code&gt;Jump&lt;/code&gt;, &lt;code&gt;JumpIfNot&lt;/code&gt;, &lt;code&gt;JumpIfLow(threshold, offset)&lt;/code&gt; — the last is unique to Metalogos: it branches based on confidence scores from fluid types.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Metalogos-specific:&lt;/strong&gt; &lt;code&gt;Collapse&lt;/code&gt; (fluid type resolution), &lt;code&gt;Memorize&lt;/code&gt;, &lt;code&gt;Recall&lt;/code&gt;, &lt;code&gt;Forget&lt;/code&gt;, &lt;code&gt;LlmCall&lt;/code&gt;, &lt;code&gt;Adapt&lt;/code&gt;, &lt;code&gt;Relate&lt;/code&gt;, &lt;code&gt;Mutate&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Meta:&lt;/strong&gt; &lt;code&gt;ExecuteRules&lt;/code&gt;, &lt;code&gt;Halt&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Compilation
&lt;/h3&gt;

&lt;p&gt;The compiler is two-pass:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Pass 1:&lt;/strong&gt; Collect global variables, assign slot indices, resolve imports recursively.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pass 2:&lt;/strong&gt; Generate instructions. Expression compilation is context-aware: pattern parameters become &lt;code&gt;LoadLocal&lt;/code&gt;, globals become &lt;code&gt;LoadGlobal&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Flow declarations compile into a single &lt;code&gt;FlowPipeline&lt;/code&gt; macro instruction. The pipeline steps are resolved at runtime, but the step names are validated at compile time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Call Frames
&lt;/h3&gt;

&lt;p&gt;The VM uses a stack of &lt;code&gt;CallFrame&lt;/code&gt; structs: return address + base pointer. This is standard, but the implementation uses Rust's &lt;code&gt;Vec&lt;/code&gt; as the value stack and &lt;code&gt;usize&lt;/code&gt; indices for frame boundaries — no unsafe code for stack manipulation.&lt;/p&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;is_pure&lt;/code&gt; Flag
&lt;/h3&gt;

&lt;p&gt;Every compiled pattern carries an &lt;code&gt;is_pure&lt;/code&gt; flag, set by the compiler's purity analysis. A pattern is pure if it has no LLM calls, no side effects, and no global access. This flag is currently used for documentation, but the scaffold exists for JIT compilation via Cranelift (ADR-0073). The JIT is not production-ready, but the infrastructure is there.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Zero-Cost Security Types
&lt;/h2&gt;

&lt;p&gt;Metalogos has five opaque types: &lt;code&gt;Html&lt;/code&gt;, &lt;code&gt;Secret&lt;/code&gt;, &lt;code&gt;Encrypted&lt;/code&gt;, &lt;code&gt;Hash&lt;/code&gt;, &lt;code&gt;SqlQuery&lt;/code&gt;. These are not runtime wrappers. They are compile-time constraints enforced during semantic analysis and erased before codegen.&lt;/p&gt;

&lt;h3&gt;
  
  
  How It Works
&lt;/h3&gt;

&lt;p&gt;The semantic analyzer (&lt;code&gt;semantic.rs&lt;/code&gt;) walks the AST after parsing but before compilation. It checks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Template return types:&lt;/strong&gt; Only &lt;code&gt;Html&lt;/code&gt; is valid. &lt;code&gt;template Page() -&amp;gt; Secret&lt;/code&gt; is a compile-time error.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;String interpolation in queries:&lt;/strong&gt; &lt;code&gt;query("SELECT * WHERE id = " + id)&lt;/code&gt; fails because &lt;code&gt;String&lt;/code&gt; ≠ &lt;code&gt;SqlQuery&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secret leakage:&lt;/strong&gt; &lt;code&gt;print(apiKey)&lt;/code&gt; where &lt;code&gt;apiKey: Secret&lt;/code&gt; fails because &lt;code&gt;Secret&lt;/code&gt; has no &lt;code&gt;Display&lt;/code&gt; implementation at the language level.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTML auto-escaping:&lt;/strong&gt; Values of type &lt;code&gt;String&lt;/code&gt; cannot be embedded in templates without explicit conversion to &lt;code&gt;Html&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the VM level, &lt;code&gt;Secret&lt;/code&gt; is just a &lt;code&gt;String&lt;/code&gt;. &lt;code&gt;Html&lt;/code&gt; is just a &lt;code&gt;String&lt;/code&gt;. The security guarantee is enforced once, at compile time, and never checked again. This is the same principle as Rust's borrow checker: invariants at compile time, zero cost at runtime.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defense in Depth: SVG/HTML Lint
&lt;/h3&gt;

&lt;p&gt;Наряд №74 added a static lint for SVG and HTML builtins (&lt;code&gt;svg_text&lt;/code&gt;, &lt;code&gt;html_response&lt;/code&gt;, &lt;code&gt;escape_html&lt;/code&gt;). It inspects string literals at compile time for &lt;code&gt;javascript:&lt;/code&gt; and &lt;code&gt;data:text/html&lt;/code&gt; prefixes. This is not a replacement for the type system — it is a second layer for cases where the type system cannot reason about string content.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Builtin Dispatch: 246 Functions, One Registry
&lt;/h2&gt;

&lt;p&gt;All builtins are declared in a single const array:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;BUILTIN_REGISTRY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;BuiltinSpec&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nd"&gt;spec!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"upper"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nd"&gt;spec!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"lower"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="c1"&gt;// ... 246+ entries&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The order determines bytecode indices. This is a single source of truth: add a &lt;code&gt;spec!&lt;/code&gt; row, add a handler in &lt;code&gt;Builtins::new()&lt;/code&gt;, and the builtin exists in both the interpreter and VM.&lt;/p&gt;

&lt;p&gt;The dispatch system uses a &lt;code&gt;HashMap&amp;lt;String, BuiltinFn&amp;gt;&lt;/code&gt; for the interpreter (name-based) and direct index access for the VM (&lt;code&gt;CallBuiltin(arity, index)&lt;/code&gt;). The registry guarantees that both paths resolve to the same implementation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;14 modules:&lt;/strong&gt; string, math, collections, crypto, llm, http, json, io, memory, cron, server, core, std, tests.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Error Handling: Thiserror and Soft Failures
&lt;/h2&gt;

&lt;p&gt;Rust-level errors use &lt;code&gt;thiserror::Error&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[derive(thiserror::Error,&lt;/span&gt; &lt;span class="nd"&gt;Debug)]&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;RuntimeError&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;#[error(&lt;/span&gt;&lt;span class="s"&gt;"parse error: {0}"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
    &lt;span class="nf"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nd"&gt;#[error(&lt;/span&gt;&lt;span class="s"&gt;"io error: {0}"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
    &lt;span class="nf"&gt;Io&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;#[from]&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nd"&gt;#[error(&lt;/span&gt;&lt;span class="s"&gt;"llm error: {0}"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
    &lt;span class="nf"&gt;Llm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nd"&gt;#[error(&lt;/span&gt;&lt;span class="s"&gt;"sandbox violation"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;Sandbox&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Language-level errors (type mismatch, undefined variable) are soft failures: they return &lt;code&gt;Value::Unit&lt;/code&gt; or &lt;code&gt;Result&amp;lt;Value, String&amp;gt;&lt;/code&gt;. The interpreter does not panic. The VM does not crash. This is essential for a language that may run AI-generated code — hard failures on every type mismatch would make the language unusable for LLM outputs.&lt;/p&gt;

&lt;p&gt;A custom macro replaces &lt;code&gt;.lock().unwrap()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;macro_rules!&lt;/span&gt; &lt;span class="n"&gt;lock_or_err&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$lock_expr:expr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$lock_expr&lt;/span&gt;
            &lt;span class="nf"&gt;.lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nf"&gt;.map_err&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;$crate&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;RuntimeError&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="nf"&gt;.to_string&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No poisoned mutexes crash the runtime.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. What We Deferred
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Self-Hosting
&lt;/h3&gt;

&lt;p&gt;ADR-0023 describes a self-hosted lexer written in Metalogos. It is not functional. The test is &lt;code&gt;#[ignore]&lt;/code&gt;. The 5 builtins described in the ADR were never implemented — only opcode indices were registered. The decision (re-measured August 2026): defer self-hosting until post-v1.0. Current priority is VM stabilization and a self-hosted lexer/parser as a stepping stone, not a full bootstrap.&lt;/p&gt;

&lt;h3&gt;
  
  
  JIT
&lt;/h3&gt;

&lt;p&gt;Cranelift integration exists as a scaffold (ADR-0073). The &lt;code&gt;is_pure&lt;/code&gt; flag is set. The JIT module is not connected to the main pipeline. This is intentional — correctness before speed.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. What We Added Recently
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;13 TW/VM parity gaps closed&lt;/strong&gt; — full semantic equivalence&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ADR-0023 re-measurement&lt;/strong&gt; — honest assessment of self-hosting status&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SVG/HTML security lint&lt;/strong&gt; — defense-in-depth for template injection&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PDF, Email, Calendar (CalDAV+iCal), Contacts (CardDAV+vCard)&lt;/strong&gt; — office automation builtins&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;http_download&lt;/code&gt;&lt;/strong&gt; &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retry/backoff&lt;/strong&gt; &lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Building a language alone is possible. Building a correct language alone requires discipline: dual backends for confidence, traits for extensibility, opaque types for security, and ADRs for sanity.&lt;/p&gt;

&lt;p&gt;The patterns in this post — crosscheck validation, zero-cost type erasure, const registries, and soft failure modes — are not specific to Metalogos. They are applicable to any Rust project that needs correctness guarantees without runtime overhead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repository:&lt;/strong&gt; &lt;a href="https://github.com/ShkodnikAI/Metalogos-" rel="noopener noreferrer"&gt;https://github.com/ShkodnikAI/Metalogos-&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;License:&lt;/strong&gt; MIT/Apache-2.0&lt;br&gt;&lt;br&gt;
&lt;strong&gt;ADR Collection:&lt;/strong&gt; 91 decisions, fully documented in &lt;code&gt;docs/adr/&lt;/code&gt;&lt;/p&gt;




</description>
      <category>security</category>
      <category>ai</category>
      <category>programming</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
