<?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: S V Mohit Kumar</title>
    <description>The latest articles on DEV Community by S V Mohit Kumar (@svmk_18).</description>
    <link>https://dev.to/svmk_18</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%2F1988203%2F849d14f1-68af-4b83-834e-7a22344d42fb.jpg</url>
      <title>DEV Community: S V Mohit Kumar</title>
      <link>https://dev.to/svmk_18</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/svmk_18"/>
    <language>en</language>
    <item>
      <title>Building a Verification-Aware Programming Language from Scratch in C (with Z3)</title>
      <dc:creator>S V Mohit Kumar</dc:creator>
      <pubDate>Tue, 01 Sep 2026 08:13:49 +0000</pubDate>
      <link>https://dev.to/svmk_18/building-a-verification-aware-programming-language-from-scratch-in-c-with-z3-32on</link>
      <guid>https://dev.to/svmk_18/building-a-verification-aware-programming-language-from-scratch-in-c-with-z3-32on</guid>
      <description>&lt;p&gt;Most modern programming languages rely on runtime assertions or unit tests to catch bugs. While useful, runtime checks only catch errors along paths your test suite actually executes. &lt;/p&gt;

&lt;p&gt;What if a programming language could &lt;strong&gt;mathematically prove&lt;/strong&gt; that assertions, loop invariants, and function contracts hold across &lt;em&gt;all&lt;/em&gt; possible inputs before generating a single line of bytecode?&lt;/p&gt;

&lt;p&gt;Over the past few weeks, I designed and built &lt;strong&gt;Vera&lt;/strong&gt;—a compiled language written entirely from scratch in C, featuring a custom stack-based Virtual Machine and an integrated static verification engine powered by the &lt;strong&gt;Z3 Theorem Prover&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this post, I'll walk through how Vera works, how the compiler pipeline is structured, and how we implement &lt;strong&gt;Weakest Precondition (WP) calculus&lt;/strong&gt; to verify programs at compile time.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. What Does Vera Code Look Like?
&lt;/h2&gt;

&lt;p&gt;Vera looks similar to a C/Rust hybrid, but contracts and invariants are first-class language constructs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Function Contracts (&lt;code&gt;requires&lt;/code&gt; and &lt;code&gt;ensures&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Functions can specify preconditions (&lt;code&gt;requires&lt;/code&gt;) and postconditions (&lt;code&gt;ensures&lt;/code&gt;), with the special &lt;code&gt;result&lt;/code&gt; identifier representing the returned value:&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;fn&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;requires&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;ensures&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Output: 15.00&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Loop Invariants
&lt;/h3&gt;

&lt;p&gt;Invariants can be placed on &lt;code&gt;while&lt;/code&gt;, &lt;code&gt;for&lt;/code&gt;, and &lt;code&gt;do-while&lt;/code&gt; loops:&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;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;invariant&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="n"&gt;i&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;If any contract, invariant, or assertion can fail, the compiler halts at compile-time and outputs a concrete &lt;strong&gt;counterexample&lt;/strong&gt;!&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Compiler Architecture
&lt;/h2&gt;

&lt;p&gt;Vera follows an end-to-end compiler pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Source Code (*.ver)
        │
        ▼
   [ Lexer ]          Tokenizes input characters into tokens
        │
        ▼
   [ Parser ]         Recursive-descent parser producing an AST
        │
        ▼
 [ Verification ]     Static verification via Weakest Preconditions (Z3)
        │             (Compilation ABORTS if Z3 finds a counterexample)
        ▼
   [ Codegen ]        Walks the AST and emits stack bytecode instructions
        │
        ▼
     [ VM ]           Executes bytecode on a stack machine with heap/callframes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. How Compile-Time Static Verification Works
&lt;/h2&gt;

&lt;p&gt;Instead of only verifying contracts at runtime inside the VM, Vera performs &lt;strong&gt;Verification Condition Generation (VCG)&lt;/strong&gt; using &lt;strong&gt;Dijkstra's Weakest Precondition (WP) calculus&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Core Idea of Weakest Precondition
&lt;/h3&gt;

&lt;p&gt;For any statement &lt;code&gt;S&lt;/code&gt; and desired postcondition &lt;code&gt;Q&lt;/code&gt;, &lt;code&gt;WP(S, Q)&lt;/code&gt; computes the least restrictive condition that must hold &lt;em&gt;before&lt;/em&gt; executing &lt;code&gt;S&lt;/code&gt; to guarantee that &lt;code&gt;Q&lt;/code&gt; holds &lt;em&gt;after&lt;/em&gt; &lt;code&gt;S&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here is how Vera computes &lt;code&gt;WP&lt;/code&gt; across different AST nodes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Assignment / Let (&lt;code&gt;x = E&lt;/code&gt;):&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  WP(x = E, Q) = Q[x := E]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;(Syntactic substitution: replace every occurrence of variable &lt;code&gt;x&lt;/code&gt; in &lt;code&gt;Q&lt;/code&gt; with expression &lt;code&gt;E&lt;/code&gt;)&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Assertions (&lt;code&gt;assert C&lt;/code&gt;):&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  WP(assert C, Q) = C &amp;amp;&amp;amp; Q
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Conditionals (&lt;code&gt;if (C) S1 else S2&lt;/code&gt;):&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  WP(if, Q) = (C =&amp;gt; WP(S1, Q)) &amp;amp;&amp;amp; (!C =&amp;gt; WP(S2, Q))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Loops (&lt;code&gt;while (C) invariant (Inv) { Body }&lt;/code&gt;):&lt;/strong&gt;&lt;br&gt;
A loop generates three independent verification obligations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Loop Entry:&lt;/strong&gt; The invariant must hold before the loop starts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Loop Preservation:&lt;/strong&gt; Assuming &lt;code&gt;Inv &amp;amp;&amp;amp; C&lt;/code&gt;, executing the loop body must re-establish &lt;code&gt;Inv&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Inv &amp;amp;&amp;amp; C =&amp;gt; WP(Body, Inv)
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Loop Exit:&lt;/strong&gt; When the loop terminates, the invariant and negated condition must establish the outer postcondition:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Inv &amp;amp;&amp;amp; !C =&amp;gt; Q
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  4. Bridging C to Z3 via SMT-LIB2
&lt;/h2&gt;

&lt;p&gt;Once Vera constructs the top-level Verification Condition (VC) as an AST formula, it translates it into the &lt;strong&gt;SMT-LIB2&lt;/strong&gt; standard format and passes it to the Z3 SMT solver.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Sort Mismatch Challenge
&lt;/h3&gt;

&lt;p&gt;In the runtime VM, all variables and numbers are stored as &lt;code&gt;double&lt;/code&gt; (Real). But in mathematical logic, boolean operators (&lt;code&gt;and&lt;/code&gt;, &lt;code&gt;or&lt;/code&gt;, &lt;code&gt;not&lt;/code&gt;) expect &lt;code&gt;Bool&lt;/code&gt; sorts.&lt;/p&gt;

&lt;p&gt;To prevent Z3 sort mismatch errors, the AST-to-SMT serializer inspects node expressions. If an arithmetic expression is used inside a boolean context, it automatically coerces it to SMT &lt;code&gt;Bool&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;print_smt_bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;FILE&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ASTNode&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_smt_bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;print_smt_expr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Coerce Real numeric value to Bool: (not (= E 0.0))&lt;/span&gt;
        &lt;span class="n"&gt;fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"(not (= "&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;print_smt_expr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;" 0.0))"&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;h3&gt;
  
  
  Proving Validity by Searching for Counterexamples
&lt;/h3&gt;

&lt;p&gt;To prove that a verification condition &lt;code&gt;VC&lt;/code&gt; is &lt;strong&gt;always true (valid)&lt;/strong&gt;, we ask Z3 if its negation is &lt;strong&gt;satisfiable&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Assert( not VC )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;If Z3 returns &lt;strong&gt;&lt;code&gt;unsat&lt;/code&gt;&lt;/strong&gt;: No input can ever violate the condition. &lt;strong&gt;The program is proven correct!&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;If Z3 returns &lt;strong&gt;&lt;code&gt;sat&lt;/code&gt;&lt;/strong&gt;: Z3 found a concrete assignment of variables that breaks the code. &lt;strong&gt;Verification fails.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  5. Extracting Concrete Counterexamples
&lt;/h2&gt;

&lt;p&gt;When Z3 returns &lt;code&gt;sat&lt;/code&gt;, we don't just want to tell the developer "Verification Failed". We want to tell them &lt;strong&gt;which inputs&lt;/strong&gt; caused the failure.&lt;/p&gt;

&lt;p&gt;We append &lt;code&gt;(get-model)&lt;/code&gt; to the SMT query and parse Z3's output model in C:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(declare-const x Real)
(declare-const y Real)
(assert (not (=&amp;gt; (&amp;gt; x 0.0) (&amp;gt; (+ x y) (+ y 10.0)))))
(check-sat)
(get-model)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For this buggy function:&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;fn&lt;/span&gt; &lt;span class="nf"&gt;bad_add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;requires&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;ensures&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;y&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;Running the compiler immediately halts with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Verification FAIL: Function contract for 'bad_add' (Z3 output: sat)
Counterexample values: 
  x = 1.0
  y = 0.0
Error: Static verification failed. VM execution aborted.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Z3 found that with &lt;code&gt;x = 1.0&lt;/code&gt; (which satisfies &lt;code&gt;x &amp;gt; 0&lt;/code&gt;) and &lt;code&gt;y = 0.0&lt;/code&gt;, the returned result &lt;code&gt;1.0&lt;/code&gt; is not greater than &lt;code&gt;y + 10 = 10.0&lt;/code&gt;, saving you from a runtime defect!&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Key Takeaways &amp;amp; Lessons Learned
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;AST Memory Ownership:&lt;/strong&gt; Verification condition generation involves heavy AST substitution and synthesis. Strict cloning (&lt;code&gt;clone_ast&lt;/code&gt;) is critical to avoid double-free errors during AST destruction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;First-Principles Systems Programming:&lt;/strong&gt; Writing a compiler and bytecode VM from scratch in C gives an unmatched appreciation for how call frames, instruction pointers, symbol tables, and heap memory interact.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Formal Methods in Compilers:&lt;/strong&gt; Integrating SMT solvers at compile time makes writing reliable software intuitive and mathematically rigorous.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;Future directions for &lt;strong&gt;Vera&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Static array bounds checking (&lt;code&gt;0 &amp;lt;= i &amp;lt; length&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;[ ] Static division-by-zero detection.&lt;/li&gt;
&lt;li&gt;[ ] A dedicated Web-based IDE with live verification diagnostics and error squiggles.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check out the full source code and test scripts on GitHub:&lt;br&gt;
👉 &lt;strong&gt;&lt;a href="https://github.com/SVMK2808/toy_compiler" rel="noopener noreferrer"&gt;https://github.com/SVMK2808/toy_compiler&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I’d love to hear your thoughts, suggestions, and feedback in the comments below! Have you experimented with formal verification or building toy compilers? Let's discuss!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>computerscience</category>
      <category>c</category>
      <category>compiling</category>
    </item>
  </channel>
</rss>
