<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://stefano.ie/feed.xml" rel="self" type="application/atom+xml" /><link href="https://stefano.ie/" rel="alternate" type="text/html" hreflang="en" /><updated>2026-08-27T17:50:45+00:00</updated><id>https://stefano.ie/feed.xml</id><title type="html">Stefano Anelli</title><subtitle>Millennial software engineer from Italy, living in Ireland. C# and .NET, open-source tools, and lists of books, games, movies, music, and travels.</subtitle><author><name>Stefano Anelli</name></author><entry><title type="html">Moving to stefano.ie</title><link href="https://stefano.ie/website/2026/08/27/moving-to-stefano-ie.html" rel="alternate" type="text/html" title="Moving to stefano.ie" /><published>2026-08-27T17:30:00+00:00</published><updated>2026-08-27T17:30:00+00:00</updated><id>https://stefano.ie/website/2026/08/27/moving-to-stefano-ie</id><content type="html" xml:base="https://stefano.ie/website/2026/08/27/moving-to-stefano-ie.html"><![CDATA[<div class="with-post-photo">
  <figure class="post-photo">
  <img src="/assets/images/me-elevator.jpg" alt="Stefano Anelli in a lift, taking a mirror photo" width="1995" height="4323" />
</figure>

  <p>I had been circling this decision for years, in that slow, slightly embarrassing way you circle something that would be nice to have and never quite feels urgent enough to sit down and do. This week I finally registered a domain, my first, and I was lucky enough to get the one I actually wanted: my first name, on Ireland’s country-code TLD. This site now lives at <a href="https://stefano.ie">stefano.ie</a>.</p>

  <p>Buying the name was much easier than the version of the story I had been telling myself. I pointed it at the same GitHub Pages site that used to live only at <a href="https://sanelli.github.io">sanelli.github.io</a>, with a bit of help from <a href="https://gemini.google.com">Google Gemini</a> on the DNS side, and both the apex and the <code class="language-plaintext highlighter-rouge">www</code> hostnames serve the pages the way I wanted them to. The DNS check in the GitHub repository still fails, even though the site loads; I assume GitHub is looking at one hostname while I configured the other, or both, and the checker has not caught up with that split. Either way, I am not going to lose sleep over a red mark in a settings screen.</p>

  <p>With a bit more effort I also wired <a href="mailto:projects@stefano.ie">projects@stefano.ie</a> through to my Gmail account. There are still some wrinkles, mostly mail from that address landing in spam on my side, but it is a real address on a domain that is mine, which already feels like a step forward from hiding behind a Gmail handle.</p>

  <p>The older posts are still here, including the one about <a href="/website/2026/08/16/rebuilding-this-site.html">rebuilding this site</a>. Same pages, same GitHub repository. They just have a shorter name on the door.</p>
</div>

<p class="made-with">— Made with<svg class="icon icon-cursor" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><use href="#icon-cursor"></use></svg><a href="https://cursor.com">Cursor</a></p>]]></content><author><name>Stefano Anelli</name></author><category term="website" /><summary type="html"><![CDATA[]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://stefano.ie/assets/images/stefano.jpg" /><media:content medium="image" url="https://stefano.ie/assets/images/stefano.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Did I change my mind about AI? Yes, yes I did.</title><link href="https://stefano.ie/thoughts/2026/08/24/did-i-change-my-mind-about-ai.html" rel="alternate" type="text/html" title="Did I change my mind about AI? Yes, yes I did." /><published>2026-08-24T20:20:00+00:00</published><updated>2026-08-24T20:20:00+00:00</updated><id>https://stefano.ie/thoughts/2026/08/24/did-i-change-my-mind-about-ai</id><content type="html" xml:base="https://stefano.ie/thoughts/2026/08/24/did-i-change-my-mind-about-ai.html"><![CDATA[<p>The first time I thought about artificial intelligence I was a kid, watching films like <a href="https://en.wikipedia.org/wiki/The_Terminator"><em>Terminator</em></a> and <a href="https://en.wikipedia.org/wiki/RoboCop"><em>Robocop</em></a>. I do not think my taste in movies has improved much since.</p>

<div class="with-book-cover">
  <figure class="book-cover">
  <img src="/assets/images/covers/intelligenza-artificiale.jpg" alt="Front cover of Intelligenza Artificiale: Un approccio moderno, Volume 1, by Stuart Russell and Peter Norvig" width="200" height="284" />
  <figcaption>The Italian 2nd edition, Volume 1. Pearson Prentice Hall, 2005.</figcaption>
</figure>

  <p>The only time I took AI seriously was at <a href="https://www.polimi.it">Politecnico di Milano</a>, at least twenty years ago. The course was <em>Intelligenza Artificiale</em>. It was mostly intelligent agents, search and search algorithms (the <a href="https://en.wikipedia.org/wiki/A%2A_search_algorithm">A*</a> algorithm, for finding solutions to problems), backtracking, logic, and inference. There was also <em>Soft Computing</em>: genetic algorithms, fuzzy logic, and neural networks.</p>

  <p>I still have the book, <a href="https://en.wikipedia.org/wiki/Artificial_Intelligence:_A_Modern_Approach"><em>Intelligenza Artificiale: Un approccio moderno</em>, Volume 1</a>, by <a href="https://en.wikipedia.org/wiki/Stuart_J._Russell">Stuart Russell</a> and <a href="https://en.wikipedia.org/wiki/Peter_Norvig">Peter Norvig</a>. I even remember writing some code, probably in Java, to train a neural network, or a simulation of lions and monkeys: the lions were supposed to catch the monkeys, and the monkeys were supposed to run away. I probably still have that code in my Gmail account; a classmate and I wrote it.</p>
</div>

<h2 id="i-did-not-keep-up">I did not keep up</h2>

<p>After that I honestly did not put much effort into following AI, or LLMs. That does not mean nothing happened. In November 2022 <a href="https://openai.com/index/chatgpt/">OpenAI released ChatGPT</a>, and I was still oblivious to what large language models could do. In my head it was something like: nice tool, but it cannot do anything I cannot do myself. That may even have been true at the time. I also thought LLMs were destined to be useless, or useful only in a very thin niche, like blockchain. For a few months everything was blockchain this and blockchain that. I have never needed to write anything with a blockchain, or use a blockchain library, and I suspect most people barely remember what they were for, even if they are probably useful in their corner.</p>

<p>A few years passed. The next real encounters were in the summer and autumn of 2025. The first was on holiday in Mallorca with a friend. I was mostly using Google; they preferred a conversation with ChatGPT. I was very sceptical of the answers. In my mind the model could only repeat what it had been trained on: stale at best, made up at worst. I was still not convinced.</p>

<p>Later that autumn, or maybe a bit earlier, coding models started showing up everywhere, and at Unity there were more and more discussions about using AI to write code, or about what AI could do for customers. A couple of people who reported to me decided to try LLMs for tests and scaffolding. I did not stop them. My line was:</p>

<blockquote>
  <p>If you commit that code, you are responsible for that code, no matter whether you, AI, or Stack Overflow wrote it.</p>
</blockquote>

<p>I still did not trust AI to produce code I would want in production.</p>

<h2 id="then-i-actually-used-it">Then I actually used it</h2>

<p>In 2026 I left Unity and went back to SIG. The company line on AI was simple: try it, and see if it helps with the day-to-day work. It did.</p>

<p>Some colleagues gave me a proper introduction to <a href="https://cursor.com">Cursor</a>, and I realised I could save a lot of time and mental energy, especially in a legacy codebase, and spend it on the part that matters: architecture and problem solving. Day by day I got more comfortable with it. I learned the modes, Plan and Ask, when to switch models, and when to trust the model versus my own software-engineering instinct. AI can be wrong. That part did not change.</p>

<p>After a couple of months I wanted Cursor at home too, so I bought myself a Cursor Pro subscription and went back to <a href="https://github.com/sanelli/Mappa">Mappa</a>. Before Cursor, a new feature could take months: not only because there is a lot of code, but because the <a href="https://github.com/dotnet/roslyn">Roslyn</a> API is poorly documented, and writing tests that cover every case took a huge amount of energy. Since I started using Cursor on Mappa I have shipped three versions: <a href="/projects/csharp/nuget/source-generator/mappa/2026/06/11/Mappa-v10.0.0.html">10.0</a>, <a href="/projects/csharp/nuget/source-generator/mappa/2026/07/04/Mappa-v10.1.0.html">10.1</a>, and <a href="/projects/csharp/nuget/source-generator/mappa/2026/08/09/Mappa-v10.2.0.html">10.2</a>. On top of that I <a href="/website/2026/08/16/rebuilding-this-site.html">rebuilt this site</a>, and in a single day, while I was also cleaning the apartment windows, I wrote a <a href="/projects/eml/ada/compiler/interpreter/2026/08/22/EML-an-exp-minus-log-compiler-and-interpreter.html">compiler and interpreter for EML</a>.</p>

<h2 id="a-walk-a-meal-log-and-a-change-of-mind">A walk, a meal log, and a change of mind</h2>

<p>What made me sit down and write this is something I noticed today, while complaining to myself about how hard it is to track what I eat. For my own reasons I am trying to eat a bit healthier, and a big part of that is knowing what I actually consume. I got a <a href="https://blog.google/products-and-platforms/devices/fitbit/fitbit-air/">Fitbit Air</a> and installed <a href="https://health.google/">Google Health</a> on my iPhone. Fine, except logging every meal is tedious, the app UI is confusing and overwhelming, and even the “smart” bits are frustrating. I tried to scan the barcode on a pack of mixed nuts; the portion-size screen came up in Korean, which I do not speak.</p>

<p>On a post-lunch walk I thought: what if I write a small program that reads a JSON file and sends a request to the Google Health API? I have had this kind of idea before. I usually get stuck, because turning it into something real means learning a pile of details: how does this API work, how does auth work, what are the valid values for these fields?</p>

<p>Today, after I got home from work, I opened Cursor, described what I wanted, and built a small set of tools: ask <a href="https://gemini.google.com">Gemini</a> to turn a markdown log of what I ate (and maybe some photos) into JSON in the right shape, then upload it through the Google Health API. All of that in less than a couple of hours, and I was having fun doing it.</p>

<p>AI, used properly, is very good at removing this kind of roadblock. It brought back the fun of writing something new. The tool is called foody. Once I have used it myself for a while I will make it public and write a post about it.</p>

<h2 id="so-did-i-change-my-mind">So, did I change my mind?</h2>

<p>How do I see the future of software engineering? A slightly easier job than it used to be, especially for senior engineers. AI took away a lot of the hurdles that made writing code a chore, and left more room for the part that is actually the job, and possibly the fun part: problem solving. The work will change. Being a software engineer is still a good career.</p>

<p>I do want to say something to junior engineers, and to people studying computer science. It is more or less what my maths teacher told me in primary school, when I was learning arithmetic: do not use a calculator. In your case: do not use AI to write the code and the projects for you. Learn to code the hard way. Sit with the problems that make you a better engineer. Use AI to check your work, or to reason with. If you skip the fundamentals, you will not get them.</p>

<p>I was wrong about AI.</p>

<aside class="album-facts">
  <p class="album-facts-label">Disclosure</p>
  <p>The ideas and stories are mine. I wrote the first draft in Notes, then asked Cursor to make it cleaner English. I might post that original draft later.</p>
</aside>

<p class="made-with">— Made with<svg class="icon icon-cursor" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><use href="#icon-cursor"></use></svg><a href="https://cursor.com">Cursor</a></p>]]></content><author><name>Stefano Anelli</name></author><category term="thoughts" /><summary type="html"><![CDATA[The first time I thought about artificial intelligence I was a kid, watching films like Terminator and Robocop. I do not think my taste in movies has improved much since.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://stefano.ie/assets/images/stefano.jpg" /><media:content medium="image" url="https://stefano.ie/assets/images/stefano.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">EML: an exp-minus-log compiler and interpreter</title><link href="https://stefano.ie/projects/eml/ada/compiler/interpreter/2026/08/22/EML-an-exp-minus-log-compiler-and-interpreter.html" rel="alternate" type="text/html" title="EML: an exp-minus-log compiler and interpreter" /><published>2026-08-22T22:20:00+00:00</published><updated>2026-08-22T22:20:00+00:00</updated><id>https://stefano.ie/projects/eml/ada/compiler/interpreter/2026/08/22/EML-an-exp-minus-log-compiler-and-interpreter</id><content type="html" xml:base="https://stefano.ie/projects/eml/ada/compiler/interpreter/2026/08/22/EML-an-exp-minus-log-compiler-and-interpreter.html"><![CDATA[<p>This post, and the work it describes, was done with <a href="https://cursor.com">Cursor</a>. I wanted to build a small compiler from scratch and see how far that would go, but I also wanted the problem to stay small enough that I would still hit every stage: preprocessor, tokenizer, parser, IR, interpreter, emitters.</p>

<p>The result is <a href="https://github.com/sanelli/eml">eml</a>, an <a href="https://ada-lang.io">Ada</a> compiler and interpreter built with <a href="https://alire.ada.dev">Alire</a>. Math goes in, a two-opcode stack IR comes out, and you can run that IR or emit JavaScript and C.</p>

<h2 id="the-eml-function">The eml function</h2>

<p>A few months ago <a href="https://arxiv.org/html/2603.21852v2">Andrzej Odrzywołek’s paper</a> <em>All elementary functions from a single operator</em> showed up in my X feed. The claim is simple and a bit wild: one binary operator,</p>

<p><code class="language-plaintext highlighter-rouge">eml(x, y) = exp(x) − ln(y)</code></p>

<p>together with the constant 1, is enough to rebuild the usual scientific-calculator basis — arithmetic, exp and ln, trig, roots, constants like <em>e</em>, π, and <em>i</em>. Closed programs are a binary tree of identical nodes, and the grammar is just <code class="language-plaintext highlighter-rouge">S → 1 | eml(S, S)</code>. NAND for continuous math, if you like that analogy.</p>

<p>For example, <code class="language-plaintext highlighter-rouge">e = eml(1, 1)</code>, <code class="language-plaintext highlighter-rouge">exp(x) = eml(x, 1)</code>, and <code class="language-plaintext highlighter-rouge">ln(z) = eml(1, eml(eml(1, z), 1))</code>. Work happens over complex numbers, principal branch.</p>

<p>I found that idea fascinating: most of the operations I was taught as separate buttons on a calculator can stem from one function and one number. I am also really into compilers, and this looked like a language that was still manageable while still forcing me through the basics.</p>

<h2 id="why-ada">Why Ada?</h2>

<p>In theory I could have used any language I wanted. Cursor wrote the code; I steered. What I noticed along the way is that these models do their best work when they are tightly constrained, and Ada gives you a type system that can enforce some of that out of the box. I also turned on the strictest Alire switches I could: warnings as errors, style checks, contracts, every runtime check, Ada 2022.</p>

<p>There was a second reason. Ada is not C, Python, or JavaScript, and I wanted to see whether a less common language would give Cursor a harder time.</p>

<h2 id="why-no-crates">Why no crates?</h2>

<p>There are no third-party Ada libraries. Tokenizers need regular expressions, so I had Cursor build a small in-repo compiler from a regex subset to an NFA. I wanted to see whether skipping packages would hurt performance. This is a simple language, but using custom automata for the tokenizers actually worked incredibly well.</p>

<h2 id="architecture">Architecture</h2>

<p>Everything funnels into one IR: a binary tree of <code class="language-plaintext highlighter-rouge">1</code> and <code class="language-plaintext highlighter-rouge">eml(S, S)</code>. Front ends differ by format; backends only see that tree.</p>

<figure class="pipeline-diagram">
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 840 690" role="img" aria-labelledby="eml-pd-title eml-pd-desc">
    <title id="eml-pd-title">EML compiler pipeline</title>
    <desc id="eml-pd-desc">mxeml and teml go through preproc into tokenize; eml enters at tokenize; beml goes through Beml_Reader into parse. Parse lowers to IR_Eml.Node, which compile emits as eml, beml, JavaScript, or C, and run evaluates on a complex stack.</desc>
    <defs>
      <marker id="eml-pd-arrow" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" refX="7" refY="3.5" orient="auto">
        <path d="M0 0 L7 3.5 L0 7 Z" class="pd-arrow-head" />
      </marker>
    </defs>
    <style>
      .pd-edges path { fill: none; marker-end: url(#eml-pd-arrow); }
    </style>

    <g class="pd-input">
      <rect x="50" y="20" width="130" height="32" rx="6" />
      <text x="115" y="36">mxeml</text>
      <rect x="200" y="20" width="130" height="32" rx="6" />
      <text x="265" y="36">teml</text>
      <rect x="470" y="20" width="130" height="32" rx="6" />
      <text x="535" y="36">eml</text>
      <rect x="640" y="20" width="130" height="32" rx="6" />
      <text x="705" y="36">beml</text>
    </g>

    <g class="pd-stage">
      <rect x="125" y="88" width="130" height="32" rx="6" />
      <text x="190" y="104">preproc</text>
      <rect x="290" y="158" width="130" height="32" rx="6" />
      <text x="355" y="174">tokenize</text>
      <rect x="350" y="228" width="130" height="32" rx="6" />
      <text x="415" y="244">parse</text>
      <rect x="16" y="436" width="152" height="32" rx="6" />
      <text x="92" y="452">compile -of eml</text>
      <rect x="348" y="436" width="144" height="32" rx="6" />
      <text x="420" y="452">compile -of js</text>
      <rect x="500" y="436" width="136" height="32" rx="6" />
      <text x="568" y="452">compile -of c</text>
      <rect x="652" y="436" width="156" height="32" rx="6" />
      <text x="730" y="452">compile -of clib</text>
      <rect x="164" y="504" width="168" height="32" rx="6" />
      <text x="248" y="520">compile -of beml</text>
    </g>

    <g class="pd-internal">
      <rect x="625" y="88" width="160" height="32" rx="6" />
      <text x="705" y="104">Beml_Reader</text>
      <rect x="480" y="296" width="200" height="32" rx="6" />
      <text x="580" y="312">Expr_Lower or IR tree</text>
      <rect x="335" y="364" width="170" height="36" rx="6" />
      <text x="420" y="382">IR_Eml.Node</text>
      <rect x="180" y="436" width="144" height="32" rx="6" />
      <text x="252" y="452">IR_Eml.Flatten</text>
    </g>

    <g class="pd-out">
      <rect x="20" y="156" width="210" height="36" rx="6" />
      <text x="125" y="174">expanded .mxeml / .teml</text>
      <rect x="120" y="228" width="155" height="32" rx="6" />
      <text x="197.5" y="244">.tokens</text>
      <rect x="20" y="296" width="190" height="32" rx="6" />
      <text x="115" y="312">parse mxeml: AST dump</text>
      <rect x="230" y="296" width="230" height="32" rx="6" />
      <text x="345" y="312">parse teml/eml/beml: IR dump</text>
      <rect x="52" y="504" width="80" height="28" rx="6" />
      <text x="92" y="518">.eml</text>
      <rect x="384" y="504" width="72" height="28" rx="6" />
      <text x="420" y="518">.js</text>
      <rect x="498" y="504" width="140" height="28" rx="6" />
      <text x="568" y="518">.c with main</text>
      <rect x="640" y="504" width="180" height="32" rx="6" />
      <text x="730" y="520">.c eml+compute</text>
      <rect x="204" y="568" width="88" height="28" rx="6" />
      <text x="248" y="582">.beml</text>
      <rect x="334" y="568" width="172" height="28" rx="6" />
      <text x="420" y="582">.html when -o</text>
      <rect x="656" y="568" width="148" height="28" rx="6" />
      <text x="730" y="582">.h when -o</text>
      <rect x="16" y="568" width="148" height="32" rx="6" />
      <text x="90" y="584">Complex stack</text>
      <rect x="16" y="632" width="268" height="32" rx="6" />
      <text x="150" y="648">eml run: compact Complex</text>
    </g>

    <g class="pd-edges">
      <path d="M115 52 V70 H160 V88" />
      <path d="M265 52 V70 H230 V88" />
      <path d="M190 120 V156" />
      <path d="M255 104 H355 V158" />
      <path d="M535 52 V174 H420" />
      <path d="M705 52 V88" />
      <path d="M355 190 V210 H198 V228" />
      <path d="M355 190 V228" />
      <path d="M705 120 V244 H480" />
      <path d="M415 260 V278 H115 V296" />
      <path d="M415 260 V278 H345 V296" />
      <path d="M415 260 V278 H580 V296" />
      <path d="M580 328 V346 H420 V364" />
      <path d="M420 400 V418 H92 V436" />
      <path d="M420 400 V418 H252 V436" />
      <path d="M420 400 V436" />
      <path d="M420 400 V418 H568 V436" />
      <path d="M420 400 V418 H730 V436" />
      <path d="M92 468 V504" />
      <path d="M252 468 V504" />
      <path d="M420 468 V504" />
      <path d="M568 468 V504" />
      <path d="M730 468 V504" />
      <path d="M248 536 V568" />
      <path d="M420 532 V568" />
      <path d="M730 536 V568" />
      <path d="M252 468 V478 H148 V550 H90 V568" />
      <path d="M90 600 V632" />
    </g>

    <g class="pd-legend">
      <g class="pd-input">
        <rect x="626" y="624" width="18" height="11" rx="3" />
      </g>
      <text x="650" y="629">Input</text>
      <g class="pd-stage">
        <rect x="728" y="624" width="18" height="11" rx="3" />
      </g>
      <text x="752" y="629">Command</text>
      <g class="pd-internal">
        <rect x="626" y="646" width="18" height="11" rx="3" />
      </g>
      <text x="650" y="651">Internal</text>
      <g class="pd-out">
        <rect x="728" y="646" width="18" height="11" rx="3" />
      </g>
      <text x="752" y="651">Output</text>
    </g>
  </svg>
  <figcaption>The four input formats through preproc, tokenize, parse, and <code>IR_Eml.Node</code>, then compile and run.</figcaption>
</figure>

<p><code class="language-plaintext highlighter-rouge">preproc</code>, <code class="language-plaintext highlighter-rouge">tokenize</code>, and <code class="language-plaintext highlighter-rouge">parse</code> stop at their dump (expanded text, tokens, or a tree). <code class="language-plaintext highlighter-rouge">compile</code> and <code class="language-plaintext highlighter-rouge">run</code> continue from <code class="language-plaintext highlighter-rouge">IR_Eml.Node</code>. <code class="language-plaintext highlighter-rouge">run</code> flattens to opcodes and evaluates on a complex stack, while the JavaScript and C emitters walk the tree as nested <code class="language-plaintext highlighter-rouge">eml(...)</code> calls instead of flattening.</p>

<p>Stack semantics are two instructions: <code class="language-plaintext highlighter-rouge">ONE</code> pushes 1; <code class="language-plaintext highlighter-rouge">EML</code> pops Y then X and pushes <code class="language-plaintext highlighter-rouge">eml(X, Y)</code>.</p>

<h2 id="actions">Actions</h2>

<p>The executable is one binary, <code class="language-plaintext highlighter-rouge">eml</code>. The front end is chosen from the effective input format.</p>

<table>
  <thead>
    <tr>
      <th>Command</th>
      <th>What it does</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">preproc</code></td>
      <td>Substitute <code class="language-plaintext highlighter-rouge">$VARNAME</code> from <code class="language-plaintext highlighter-rouge">--var</code> / <code class="language-plaintext highlighter-rouge">-v</code> bindings. <code class="language-plaintext highlighter-rouge">.mxeml</code> and <code class="language-plaintext highlighter-rouge">.teml</code> only.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">tokenize</code></td>
      <td>Optionally preprocess, then dump the token stream. Accepts <code class="language-plaintext highlighter-rouge">mxeml</code>, <code class="language-plaintext highlighter-rouge">teml</code>, and <code class="language-plaintext highlighter-rouge">eml</code> (not <code class="language-plaintext highlighter-rouge">beml</code>).</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">parse</code></td>
      <td>Build a tree and dump it. <code class="language-plaintext highlighter-rouge">mxeml</code> dumps the expression AST; the other three dump the IR tree.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">compile</code></td>
      <td>Lower or reconstruct to IR, then emit a compile target.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">run</code></td>
      <td>Flatten IR, evaluate on a <code class="language-plaintext highlighter-rouge">Long_Float</code> complex stack, print one compact complex value on stdout. No output file.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">help</code></td>
      <td>Usage, or <code class="language-plaintext highlighter-rouge">eml help &lt;command&gt;</code> for one command.</td>
    </tr>
  </tbody>
</table>

<p>Diagnostics print as <code class="language-plaintext highlighter-rouge">[ID] line:column description</code> (five-digit IDs). Unused <code class="language-plaintext highlighter-rouge">--var</code> bindings follow <code class="language-plaintext highlighter-rouge">--warn</code> (<code class="language-plaintext highlighter-rouge">default</code>, <code class="language-plaintext highlighter-rouge">none</code>, or <code class="language-plaintext highlighter-rouge">error</code>).</p>

<h2 id="input-formats">Input formats</h2>

<table>
  <thead>
    <tr>
      <th>Format</th>
      <th>Extension</th>
      <th>Role</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">mxeml</code></td>
      <td><code class="language-plaintext highlighter-rouge">.mxeml</code></td>
      <td>Math source: <code class="language-plaintext highlighter-rouge">+</code> <code class="language-plaintext highlighter-rouge">-</code> <code class="language-plaintext highlighter-rouge">*</code> <code class="language-plaintext highlighter-rouge">/</code> <code class="language-plaintext highlighter-rouge">^</code>, functions (<code class="language-plaintext highlighter-rouge">log</code>, <code class="language-plaintext highlighter-rouge">sin</code>, <code class="language-plaintext highlighter-rouge">cos</code>, <code class="language-plaintext highlighter-rouge">tan</code>, <code class="language-plaintext highlighter-rouge">sqrt</code>, <code class="language-plaintext highlighter-rouge">sinh</code>, <code class="language-plaintext highlighter-rouge">cosh</code>, <code class="language-plaintext highlighter-rouge">tanh</code>), constants (<code class="language-plaintext highlighter-rouge">i</code>, <code class="language-plaintext highlighter-rouge">pi</code>, <code class="language-plaintext highlighter-rouge">e</code>, <code class="language-plaintext highlighter-rouge">phi</code>), and <code class="language-plaintext highlighter-rouge">eml(x, y)</code> itself. <code class="language-plaintext highlighter-rouge">$VARNAME</code> is preprocessor paste.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">teml</code></td>
      <td><code class="language-plaintext highlighter-rouge">.teml</code></td>
      <td>Nested tree text only: <code class="language-plaintext highlighter-rouge">1</code> and <code class="language-plaintext highlighter-rouge">eml(S, S)</code>. Same <code class="language-plaintext highlighter-rouge">$VARNAME</code> preprocessor.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">eml</code></td>
      <td><code class="language-plaintext highlighter-rouge">.eml</code></td>
      <td>Textual stack IR: <code class="language-plaintext highlighter-rouge">ONE</code> / <code class="language-plaintext highlighter-rouge">EML</code>, with <code class="language-plaintext highlighter-rouge">--</code> comments.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">beml</code></td>
      <td><code class="language-plaintext highlighter-rouge">.beml</code></td>
      <td>Packed-bit binary of that same instruction stream. Magic <code class="language-plaintext highlighter-rouge">BEML</code>, big-endian counts, bits <code class="language-plaintext highlighter-rouge">1</code> = <code class="language-plaintext highlighter-rouge">ONE</code> and <code class="language-plaintext highlighter-rouge">0</code> = <code class="language-plaintext highlighter-rouge">EML</code>.</td>
    </tr>
  </tbody>
</table>

<p><code class="language-plaintext highlighter-rouge">--input</code> / <code class="language-plaintext highlighter-rouge">-i</code> is optional (stdin when omitted). If <code class="language-plaintext highlighter-rouge">-i</code> is omitted, <code class="language-plaintext highlighter-rouge">--input-format</code> / <code class="language-plaintext highlighter-rouge">-if</code> is required. When both are present, <code class="language-plaintext highlighter-rouge">-if</code> overrides the file extension.</p>

<h2 id="output-formats">Output formats</h2>

<p><code class="language-plaintext highlighter-rouge">-o</code> / <code class="language-plaintext highlighter-rouge">--output</code> is optional on <code class="language-plaintext highlighter-rouge">preproc</code>, <code class="language-plaintext highlighter-rouge">tokenize</code>, <code class="language-plaintext highlighter-rouge">parse</code>, and <code class="language-plaintext highlighter-rouge">compile</code> (stdout if omitted). When <code class="language-plaintext highlighter-rouge">-o</code> is set, the extension must match <code class="language-plaintext highlighter-rouge">-of</code>.</p>

<table>
  <thead>
    <tr>
      <th>Action</th>
      <th><code class="language-plaintext highlighter-rouge">-of</code></th>
      <th>What you get</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">preproc</code></td>
      <td><code class="language-plaintext highlighter-rouge">mxeml</code> or <code class="language-plaintext highlighter-rouge">teml</code></td>
      <td>Expanded source. Default is the input format; <code class="language-plaintext highlighter-rouge">-of</code> must match the input.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">tokenize</code></td>
      <td><code class="language-plaintext highlighter-rouge">tokens</code></td>
      <td><code class="language-plaintext highlighter-rouge">.tokens</code> dump: one token per line. Default, and the only value.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">parse</code></td>
      <td><code class="language-plaintext highlighter-rouge">mermaid</code></td>
      <td><code class="language-plaintext highlighter-rouge">.syntaxtree</code> — raw Mermaid <code class="language-plaintext highlighter-rouge">flowchart TD</code>. Default. <code class="language-plaintext highlighter-rouge">mxeml</code> dumps the AST; the other formats dump the IR tree.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">parse</code></td>
      <td><code class="language-plaintext highlighter-rouge">md</code></td>
      <td><code class="language-plaintext highlighter-rouge">.md</code> — Markdown with a fenced Mermaid block.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">parse</code></td>
      <td><code class="language-plaintext highlighter-rouge">dot</code></td>
      <td><code class="language-plaintext highlighter-rouge">.dot</code> — Graphviz <code class="language-plaintext highlighter-rouge">digraph</code>.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">parse</code></td>
      <td><code class="language-plaintext highlighter-rouge">svg</code></td>
      <td><code class="language-plaintext highlighter-rouge">.svg</code> — self-drawn SVG (no Graphviz).</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">compile</code></td>
      <td><code class="language-plaintext highlighter-rouge">beml</code></td>
      <td>Binary stack IR, <code class="language-plaintext highlighter-rouge">.beml</code>. Default.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">compile</code></td>
      <td><code class="language-plaintext highlighter-rouge">eml</code></td>
      <td>Textual stack IR, <code class="language-plaintext highlighter-rouge">.eml</code>, with a UTC header.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">compile</code></td>
      <td><code class="language-plaintext highlighter-rouge">js</code></td>
      <td>A classic browser script: <code class="language-plaintext highlighter-rouge">eml(x, y)</code> via <a href="https://mathjs.org/">math.js</a> (<code class="language-plaintext highlighter-rouge">math.exp</code> / <code class="language-plaintext highlighter-rouge">math.log</code>), and an entry function (default <code class="language-plaintext highlighter-rouge">main</code>, or <code class="language-plaintext highlighter-rouge">--function-name</code> / <code class="language-plaintext highlighter-rouge">-fn</code>) of nested <code class="language-plaintext highlighter-rouge">eml(...)</code> calls. With <code class="language-plaintext highlighter-rouge">-o</code>, also a companion <code class="language-plaintext highlighter-rouge">.html</code> that loads a pinned math.js CDN bundle.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">compile</code></td>
      <td><code class="language-plaintext highlighter-rouge">c</code></td>
      <td>A standalone C program: <code class="language-plaintext highlighter-rouge">&lt;complex.h&gt;</code>, <code class="language-plaintext highlighter-rouge">long double complex</code>, <code class="language-plaintext highlighter-rouge">cexpl</code> / <code class="language-plaintext highlighter-rouge">clogl</code>, and <code class="language-plaintext highlighter-rouge">main</code> printing the result.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">compile</code></td>
      <td><code class="language-plaintext highlighter-rouge">clib</code></td>
      <td>A C library <code class="language-plaintext highlighter-rouge">.c</code> defining <code class="language-plaintext highlighter-rouge">eml</code> and an entry (default <code class="language-plaintext highlighter-rouge">compute</code>, or <code class="language-plaintext highlighter-rouge">-fn</code>). With <code class="language-plaintext highlighter-rouge">-o</code>, a companion <code class="language-plaintext highlighter-rouge">.h</code>. <code class="language-plaintext highlighter-rouge">--emit-eml</code> also declares <code class="language-plaintext highlighter-rouge">eml</code> in the header; otherwise <code class="language-plaintext highlighter-rouge">eml</code> stays <code class="language-plaintext highlighter-rouge">static</code> in the <code class="language-plaintext highlighter-rouge">.c</code>.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">run</code></td>
      <td>—</td>
      <td>One compact complex value on stdout. <code class="language-plaintext highlighter-rouge">-o</code> and <code class="language-plaintext highlighter-rouge">-of</code> are invalid.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">help</code></td>
      <td>—</td>
      <td>Usage on stdout (<code class="language-plaintext highlighter-rouge">eml help</code> or <code class="language-plaintext highlighter-rouge">eml help &lt;command&gt;</code>).</td>
    </tr>
  </tbody>
</table>

<p>Same-format compile is rejected (<code class="language-plaintext highlighter-rouge">eml</code> → <code class="language-plaintext highlighter-rouge">eml</code>, <code class="language-plaintext highlighter-rouge">beml</code> → <code class="language-plaintext highlighter-rouge">beml</code>).</p>

<h2 id="what-went-well">What went well</h2>

<p>Instructing Cursor to generate the right code was fairly easy. I just had to keep the tasks bite-sized: create the tokenizer for this format, allow outputting this other format, and so on.</p>

<h2 id="what-took-some-time">What took some time</h2>

<p>When building the Ada interpreter, Cursor got stuck a few times on infinite values that show up as mid-steps. The identities are not free of ±∞ — the paper is explicit about that (<code class="language-plaintext highlighter-rouge">ln 0 = −∞</code>, <code class="language-plaintext highlighter-rouge">e^(−∞) = 0</code>) — and while Ada and IEEE-754 can live with it, getting the interpreter to live with it took a few rounds.</p>

<p>Also, as usual, JavaScript proved to be a poor language, or maybe I am just not good with it. Ada and the generated C both execute simple expressions such as <code class="language-plaintext highlighter-rouge">1 + 2 * 3</code>, but the JavaScript backend, at least in Safari, comes back with <code class="language-plaintext highlighter-rouge">Infinity + Infinityi</code>, which is underwhelming. I am even using an external library for this, <a href="https://mathjs.org/">math.js</a>, and I do not blame the library so much as the language.</p>

<h2 id="next">Next</h2>

<p>Still on the list:</p>

<ul>
  <li>Compile to a native binary via LLVM</li>
  <li>Compile to CIL</li>
  <li>Compile to Java bytecode</li>
  <li>Compile to <code class="language-plaintext highlighter-rouge">wat</code>, and possibly to <code class="language-plaintext highlighter-rouge">wasm</code></li>
  <li>A VS Code extension for <code class="language-plaintext highlighter-rouge">.mxeml</code> / <code class="language-plaintext highlighter-rouge">.teml</code> / <code class="language-plaintext highlighter-rouge">.eml</code> files</li>
</ul>

<p class="made-with">— Made with<svg class="icon icon-cursor" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><use href="#icon-cursor"></use></svg><a href="https://cursor.com">Cursor</a></p>]]></content><author><name>Stefano Anelli</name></author><category term="projects" /><category term="eml" /><category term="ada" /><category term="compiler" /><category term="interpreter" /><summary type="html"><![CDATA[This post, and the work it describes, was done with Cursor. I wanted to build a small compiler from scratch and see how far that would go, but I also wanted the problem to stay small enough that I would still hit every stage: preprocessor, tokenizer, parser, IR, interpreter, emitters.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://stefano.ie/assets/images/stefano.jpg" /><media:content medium="image" url="https://stefano.ie/assets/images/stefano.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Adding a travels section</title><link href="https://stefano.ie/website/2026/08/19/travels-section.html" rel="alternate" type="text/html" title="Adding a travels section" /><published>2026-08-19T21:00:00+00:00</published><updated>2026-08-19T21:00:00+00:00</updated><id>https://stefano.ie/website/2026/08/19/travels-section</id><content type="html" xml:base="https://stefano.ie/website/2026/08/19/travels-section.html"><![CDATA[<p>This post, and the work it describes, was done with <a href="https://cursor.com">Cursor</a>. After rebuilding the site around lists of books, music, movies, and games, I wanted the same treatment for places I have been.</p>

<p>The new <strong><a href="/travels/">Travels</a></strong> page sits in the header next to the other media lists. Trips live in <code class="language-plaintext highlighter-rouge">_data/travels.yml</code>, with the same card layout, year rail, search, ratings, and month gaps you already get on books or movies. Each entry has a title, dates, a star rating when I remember one, and the places I visited, with Wikipedia links where they exist.</p>

<p>On top of that I added a map. <a href="https://leafletjs.com/">Leaflet</a> loads above the list, with a pin for every place that has coordinates in <code class="language-plaintext highlighter-rouge">_data/travel_coords.yml</code>. Dublin is marked as home. Older visits fade a little on the map so recent trips stand out. When you search or filter by rating, the list and the pins stay in sync.</p>

<p>The quiet <strong><a href="/stats/">Stats</a></strong> page now counts trips too, alongside the other yearly totals.</p>

<p>It is the same Jekyll pattern as the rest of the rebuild: YAML, Liquid, a bit of JavaScript, no new stack. I had years of trips scattered in photo folders and memory; now they have a proper home on the site.</p>

<p class="made-with">— Made with<svg class="icon icon-cursor" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><use href="#icon-cursor"></use></svg><a href="https://cursor.com">Cursor</a></p>]]></content><author><name>Stefano Anelli</name></author><category term="website" /><summary type="html"><![CDATA[This post, and the work it describes, was done with Cursor. After rebuilding the site around lists of books, music, movies, and games, I wanted the same treatment for places I have been.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://stefano.ie/assets/images/stefano.jpg" /><media:content medium="image" url="https://stefano.ie/assets/images/stefano.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Rebuilding this site</title><link href="https://stefano.ie/website/2026/08/16/rebuilding-this-site.html" rel="alternate" type="text/html" title="Rebuilding this site" /><published>2026-08-16T09:00:00+00:00</published><updated>2026-08-16T09:00:00+00:00</updated><id>https://stefano.ie/website/2026/08/16/rebuilding-this-site</id><content type="html" xml:base="https://stefano.ie/website/2026/08/16/rebuilding-this-site.html"><![CDATA[<p>This post, and the work it describes, was done with <a href="https://cursor.com">Cursor</a>. I sat down to tidy a stock Jekyll site and came out the other side with something that actually feels like mine.</p>

<p>I have been running this page on the default <a href="https://github.com/jekyll/minima">Minima</a> setup for years. That setup is already more than enough: Markdown, a theme, GitHub Pages, done. I never really looked further. I also do not write Ruby, which is what Jekyll is built on, so I treated the generator as a black box and left it alone.</p>

<p>That was a mistake, or at least a missed chance. Once you start using data files, layouts, and a few plugins, Jekyll is a small static CMS. I was surprised how far it goes without a database or a build toolchain I would normally reach for at work.</p>

<p>What changed:</p>

<ul>
  <li>The <strong>Career</strong> page is a proper CV again: roles, product shots, chips for languages and frameworks, education, awards, and links.</li>
  <li><strong>Portfolio</strong> items are cards driven from YAML, with the related posts hanging off each one.</li>
  <li><strong>Books, music, movies, and games</strong> moved out of hand-written tables into data files. The pages search, filter, and sort in the browser.</li>
  <li>Emoji prefixes are gone. A single SVG sprite covers navigation, projects, and this post.</li>
  <li>Dark is still the default. A footer control cycles dark, light, and system.</li>
  <li>The site builds with GitHub Actions on Jekyll 4, which meant I could add plugins Pages would not run on its own: a sitemap, redirects, cached includes, external links opening in a new tab, and pagination.</li>
  <li>There is a real <strong><a href="/posts/">/posts/</a></strong> index now. The homepage only keeps the latest few.</li>
  <li>Yearly counts live on a quiet <strong><a href="/stats/">/stats/</a></strong> page (the “Stats for nerds” link at the bottom of the home page).</li>
</ul>

<p>None of this needed me to become a Ruby developer. Liquid, YAML, and a bit of CSS were enough. I should have opened the hood years ago. The default site was already good; the rest was sitting there waiting.</p>

<p class="made-with">— Made with<svg class="icon icon-cursor" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><use href="#icon-cursor"></use></svg><a href="https://cursor.com">Cursor</a></p>]]></content><author><name>Stefano Anelli</name></author><category term="website" /><summary type="html"><![CDATA[This post, and the work it describes, was done with Cursor. I sat down to tidy a stock Jekyll site and came out the other side with something that actually feels like mine.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://stefano.ie/assets/images/stefano.jpg" /><media:content medium="image" url="https://stefano.ie/assets/images/stefano.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Mappa v10.2.0</title><link href="https://stefano.ie/projects/csharp/nuget/source-generator/mappa/2026/08/09/Mappa-v10.2.0.html" rel="alternate" type="text/html" title="Mappa v10.2.0" /><published>2026-08-09T17:00:00+00:00</published><updated>2026-08-09T17:00:00+00:00</updated><id>https://stefano.ie/projects/csharp/nuget/source-generator/mappa/2026/08/09/Mappa-v10.2.0</id><content type="html" xml:base="https://stefano.ie/projects/csharp/nuget/source-generator/mappa/2026/08/09/Mappa-v10.2.0.html"><![CDATA[<p>A new version of <a href="https://github.com/sanelli/Mappa">Mappa</a> (v10.2.0) has been released.</p>

<p>Mappa <strong>10.2.0</strong> expands mapping control with reference handling and compile-time cycle breaking, <code class="language-plaintext highlighter-rouge">IQueryable</code> projection, nested property paths, dependency-injection registrars, inaccessible-member mapping, object factories, before/after hooks, and richer enum / settings options. Benchmarks, coverage tooling, and generator performance also improve.
<strong>Full changelog:</strong> <a href="https://github.com/sanelli/Mappa/compare/v10.1.0...v10.2.0">v10.1.0…v10.2.0</a></p>

<h2 id="breaking-changes">Breaking changes</h2>
<p>When upgrading from 10.1.0, see the <a href="https://github.com/sanelli/Mappa/blob/main/Documentation/upgrade.md">upgrade guide</a>.</p>

<h3 id="relaxed-nullability-matching-for-existing-map-methods">Relaxed nullability matching for existing map methods</h3>
<ul>
  <li><strong>Nested mappings may reuse an existing map method when nullability annotations differ slightly</strong> (<a href="https://github.com/sanelli/Mappa/issues/184">#184</a>, <a href="https://github.com/sanelli/Mappa/pull/272">#272</a>)
    <ul>
      <li>With <code class="language-plaintext highlighter-rouge">#nullable enable</code>, nested mappings may now invoke an existing map method on the mapper, a dependency, or a matching polymorphic method when the underlying types match even if nullability annotations differ.</li>
      <li>Exact nullability matches are still preferred; a relaxed match is used only when no exact match exists.</li>
      <li>Supported relaxations: nested needs <code class="language-plaintext highlighter-rouge">TTarget?</code> → may invoke a method returning <code class="language-plaintext highlighter-rouge">TTarget</code>; nested needs <code class="language-plaintext highlighter-rouge">TSource</code> → may invoke a method accepting <code class="language-plaintext highlighter-rouge">TSource?</code>.</li>
      <li>Previously, a nullability mismatch caused the generator to skip the existing method and generate inline mapping (or select another strategy). Review nested mappings that relied on the old behaviour.</li>
    </ul>
  </li>
</ul>

<h2 id="whats-new">What’s new</h2>

<h3 id="reference-handling">Reference handling</h3>
<ul>
  <li><strong>Circular reference / reference handling</strong> (<a href="https://github.com/sanelli/Mappa/issues/249">#249</a>, <a href="https://github.com/sanelli/Mappa/pull/307">#307</a>) — Reuse mapped reference-type instances for cycles and shared graphs (<code class="language-plaintext highlighter-rouge">ReferenceReusing</code>), limit runtime nesting (<code class="language-plaintext highlighter-rouge">MaxRuntimeDepth</code>), and guard generator discovery (<code class="language-plaintext highlighter-rouge">MaxCompileTimeDepth</code> + compile-time mapping-cycle detection). Not supported on <code class="language-plaintext highlighter-rouge">IQueryable</code> projection.</li>
  <li><strong>Per-<code class="language-plaintext highlighter-rouge">TTarget</code> reference reuse and codegen polish</strong> (<a href="https://github.com/sanelli/Mappa/issues/320">#320</a>, <a href="https://github.com/sanelli/Mappa/issues/321">#321</a>, <a href="https://github.com/sanelli/Mappa/issues/322">#322</a>, <a href="https://github.com/sanelli/Mappa/pull/333">#333</a>) — Key reuse by source identity and <code class="language-plaintext highlighter-rouge">typeof(TTarget)</code>, omit redundant <code class="language-plaintext highlighter-rouge">AddReferencePair</code> calls, and cache the reference-manager local.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">BreakCompileTimeCycles</code></strong> (<a href="https://github.com/sanelli/Mappa/issues/306">#306</a>, <a href="https://github.com/sanelli/Mappa/pull/311">#311</a>) — Optionally break compile-time mapping cycles by synthesizing private map methods; emits <strong>MP00078</strong> when a cycle is auto-broken.</li>
</ul>

<h3 id="new-features">New features</h3>
<ul>
  <li><strong><code class="language-plaintext highlighter-rouge">IQueryable</code> projection (<code class="language-plaintext highlighter-rouge">ProjectTo</code>-style)</strong> (<a href="https://github.com/sanelli/Mappa/issues/245">#245</a>, <a href="https://github.com/sanelli/Mappa/pull/284">#284</a>) — Map methods with <code class="language-plaintext highlighter-rouge">IQueryable&lt;TSource&gt;</code> → <code class="language-plaintext highlighter-rouge">IQueryable&lt;TTarget&gt;</code> emit provider-translatable <code class="language-plaintext highlighter-rouge">Select</code> projections. Not compatible with Native AOT (<code class="language-plaintext highlighter-rouge">[RequiresDynamicCode]</code>).</li>
  <li><strong>Nested (dot-separated) property paths</strong> (<a href="https://github.com/sanelli/Mappa/issues/120">#120</a>, <a href="https://github.com/sanelli/Mappa/pull/274">#274</a>, <a href="https://github.com/sanelli/Mappa/issues/275">#275</a>, <a href="https://github.com/sanelli/Mappa/pull/278">#278</a>) — Use paths such as <code class="language-plaintext highlighter-rouge">"Address.City"</code> on <code class="language-plaintext highlighter-rouge">MappaUseProperty</code>, invoke, constant, context, and ignore attributes for flattening/unflattening.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">MappaObjectFactory</code></strong> (<a href="https://github.com/sanelli/Mappa/issues/253">#253</a>, <a href="https://github.com/sanelli/Mappa/pull/291">#291</a>) — Construct target types via named factory methods instead of <code class="language-plaintext highlighter-rouge">new</code>.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">MappaBeforeMap</code> / <code class="language-plaintext highlighter-rouge">MappaAfterMap</code></strong> (<a href="https://github.com/sanelli/Mappa/issues/250">#250</a>, <a href="https://github.com/sanelli/Mappa/pull/281">#281</a>) — Invoke named hooks immediately before and after the generated root mapping body.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">MappaMustMapTargetProperty</code></strong> (<a href="https://github.com/sanelli/Mappa/issues/20">#20</a>, <a href="https://github.com/sanelli/Mappa/pull/298">#298</a>) — Require listed (or all) non-required target properties to be mapped on the empty-constructor path; otherwise <strong>MP00065</strong>.</li>
  <li><strong>Inaccessible / private members</strong> (<a href="https://github.com/sanelli/Mappa/issues/254">#254</a>, <a href="https://github.com/sanelli/Mappa/pull/300">#300</a>) — Opt in with <code class="language-plaintext highlighter-rouge">MappaAllowInaccessibleSourceMembers</code> / <code class="language-plaintext highlighter-rouge">MappaAllowInaccessibleTargetMembers</code> to read/write private or protected members (and invoke inaccessible constructors) via <code class="language-plaintext highlighter-rouge">UnsafeAccessor</code>.</li>
  <li><strong>Generic polymorphic type-mapping attributes</strong> (<a href="https://github.com/sanelli/Mappa/issues/305">#305</a>, <a href="https://github.com/sanelli/Mappa/pull/316">#316</a>) — Prefer <code class="language-plaintext highlighter-rouge">MappaTypeMapping&lt;TTarget, TSource&gt;</code> and <code class="language-plaintext highlighter-rouge">MappaTypeMappingDefault&lt;TDefault&gt;</code> over non-generic forms.</li>
</ul>

<h3 id="dependency-injection">Dependency injection</h3>
<ul>
  <li><strong><code class="language-plaintext highlighter-rouge">MappaDependencyInjection</code> attribute</strong> (<a href="https://github.com/sanelli/Mappa/issues/299">#299</a>, <a href="https://github.com/sanelli/Mappa/pull/302">#302</a>) — Generate <code class="language-plaintext highlighter-rouge">IServiceCollection</code> registration methods for <code class="language-plaintext highlighter-rouge">[Mappa]</code> mappers; static DI mappers are skipped with <strong>MP00073</strong>.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">InjectFromAssemblies</code></strong> (<a href="https://github.com/sanelli/Mappa/issues/301">#301</a>, <a href="https://github.com/sanelli/Mappa/pull/317">#317</a>) — Discover <code class="language-plaintext highlighter-rouge">[Mappa]</code> mappers across assemblies for DI registration; Bson and Protobuf DI packages migrate to generated registrars.</li>
</ul>

<h3 id="mappasettings-and-mapping-behaviour"><code class="language-plaintext highlighter-rouge">MappaSettings</code> and mapping behaviour</h3>
<ul>
  <li><strong><code class="language-plaintext highlighter-rouge">DictionaryAssignment</code></strong> (<a href="https://github.com/sanelli/Mappa/issues/34">#34</a>, <a href="https://github.com/sanelli/Mappa/pull/273">#273</a>) — Choose indexer or <code class="language-plaintext highlighter-rouge">Add</code> insertion for dictionary-to-dictionary mapping.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">PreventEnumerableCount</code></strong> (<a href="https://github.com/sanelli/Mappa/issues/108">#108</a>, <a href="https://github.com/sanelli/Mappa/pull/285">#285</a>) — Avoid <code class="language-plaintext highlighter-rouge">Enumerable.Count</code> for fixed-size targets when the source length is unknown.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">CompatibleMapMethod</code></strong> (<a href="https://github.com/sanelli/Mappa/issues/13">#13</a>, <a href="https://github.com/sanelli/Mappa/pull/296">#296</a>) — Opt-in reuse of existing map methods when the source is a base/interface type and the method returns a compatible derived type.</li>
  <li><strong>Richer enum mapping configuration</strong> (<a href="https://github.com/sanelli/Mappa/issues/255">#255</a>, <a href="https://github.com/sanelli/Mappa/pull/282">#282</a>) — Configure enum↔integral, enum↔string, and enum↔enum pairings via <code class="language-plaintext highlighter-rouge">MappaMapEnumMember</code>, <code class="language-plaintext highlighter-rouge">MappaMapEnumIgnore</code>, and <code class="language-plaintext highlighter-rouge">MappaMapEnumDefault</code>.</li>
  <li><strong>Relaxed nullability fallback for map method matching</strong> (<a href="https://github.com/sanelli/Mappa/issues/184">#184</a>, <a href="https://github.com/sanelli/Mappa/pull/272">#272</a>) — See <a href="#breaking-changes">Breaking changes</a>.</li>
</ul>

<h3 id="projection-polish">Projection polish</h3>
<ul>
  <li><strong>Remove unused <code class="language-plaintext highlighter-rouge">{MethodName}Element</code> from <code class="language-plaintext highlighter-rouge">IQueryable</code> projections</strong> (<a href="https://github.com/sanelli/Mappa/issues/303">#303</a>, <a href="https://github.com/sanelli/Mappa/pull/304">#304</a>) — Stop emitting unused local helpers in projection-generated code.</li>
</ul>

<h3 id="generator-quality-and-performance">Generator quality and performance</h3>
<ul>
  <li><strong>Narrow syntax providers and honor <code class="language-plaintext highlighter-rouge">CancellationToken</code></strong> (<a href="https://github.com/sanelli/Mappa/issues/323">#323</a>, <a href="https://github.com/sanelli/Mappa/issues/325">#325</a>, <a href="https://github.com/sanelli/Mappa/pull/335">#335</a>) — Attribute-driven incremental discovery via <code class="language-plaintext highlighter-rouge">ForAttributeWithMetadataName</code>, and cooperative cancellation on hot paths.</li>
  <li><strong>Reduce ReportGenerator CRAP / cyclomatic complexity</strong> (<a href="https://github.com/sanelli/Mappa/issues/238">#238</a>, <a href="https://github.com/sanelli/Mappa/pull/318">#318</a>) — Refactor hotspot methods and enforce CRAP/CC maxima in the coverage script.</li>
  <li><strong>Branch coverage improvements</strong> (<a href="https://github.com/sanelli/Mappa/issues/327">#327</a>, <a href="https://github.com/sanelli/Mappa/pull/336">#336</a>) — Targeted tests for previously uncovered generator branches; comparison-chart annotation polish.</li>
  <li><strong>Bug fixes</strong> (<a href="https://github.com/sanelli/Mappa/issues/319">#319</a>, <a href="https://github.com/sanelli/Mappa/issues/328">#328</a>, <a href="https://github.com/sanelli/Mappa/issues/329">#329</a>, <a href="https://github.com/sanelli/Mappa/pull/330">#330</a>) — Null-class continue path, culture typo, and <code class="language-plaintext highlighter-rouge">MappaContext</code> documentation corrections.</li>
</ul>

<h3 id="benchmarks-and-ci-tooling">Benchmarks and CI tooling</h3>
<ul>
  <li><strong>Expanded benchmark suite with SVG charts</strong> (<a href="https://github.com/sanelli/Mappa/issues/134">#134</a>, <a href="https://github.com/sanelli/Mappa/pull/286">#286</a>) — Broader mapper scenarios, competitor/Mappa percentage charts, and gist/history publishing.</li>
  <li><strong>Benchmark display and comparison charts</strong> (<a href="https://github.com/sanelli/Mappa/issues/295">#295</a>, <a href="https://github.com/sanelli/Mappa/pull/297">#297</a>, <a href="https://github.com/sanelli/Mappa/issues/309">#309</a>, <a href="https://github.com/sanelli/Mappa/pull/315">#315</a>) — Bogus-seeded inputs, refined TIME/MEMORY SVGs, and a winner comparison table.</li>
  <li><strong>Default BenchmarkDotNet job; skip PR benchmarks</strong> (<a href="https://github.com/sanelli/Mappa/issues/331">#331</a>, <a href="https://github.com/sanelli/Mappa/pull/332">#332</a>) — Reduce flakiness and stop running/commenting benchmarks on pull requests.</li>
  <li><strong>Coverage history and PR coverage comments</strong> (<a href="https://github.com/sanelli/Mappa/issues/250">#250</a>, <a href="https://github.com/sanelli/Mappa/issues/276">#276</a>, <a href="https://github.com/sanelli/Mappa/pull/280">#280</a>, <a href="https://github.com/sanelli/Mappa/pull/281">#281</a>) — PR coverage comments with drop thresholds and improved coverage-history SVGs.</li>
  <li><strong>Gist update retries</strong> (<a href="https://github.com/sanelli/Mappa/issues/293">#293</a>, <a href="https://github.com/sanelli/Mappa/pull/294">#294</a>) — Idempotent history merges with retries on gist updates.</li>
</ul>

<h3 id="test-infrastructure">Test infrastructure</h3>
<ul>
  <li><strong>Stronger generator syntax assertions</strong> (<a href="https://github.com/sanelli/Mappa/issues/277">#277</a>, <a href="https://github.com/sanelli/Mappa/pull/279">#279</a>, <a href="https://github.com/sanelli/Mappa/issues/290">#290</a>, <a href="https://github.com/sanelli/Mappa/pull/292">#292</a>) — Require <code class="language-plaintext highlighter-rouge">HasNextSyntaxNode</code> walks and full validation after <code class="language-plaintext highlighter-rouge">HaveGeneratedSourceCode()</code>.</li>
  <li><strong>Diagnostic assertion rules</strong> (<a href="https://github.com/sanelli/Mappa/issues/310">#310</a>, <a href="https://github.com/sanelli/Mappa/pull/313">#313</a>) — Require <code class="language-plaintext highlighter-rouge">HaveDiagnostics(n)</code> or <code class="language-plaintext highlighter-rouge">NotHaveDiagnostics()</code> on generator test chains.</li>
  <li><strong>Dump generated sources from generator tests</strong> (<a href="https://github.com/sanelli/Mappa/issues/308">#308</a>, <a href="https://github.com/sanelli/Mappa/pull/312">#312</a>) — Persist successful generation dumps for issue reports.</li>
</ul>

<h3 id="maintenance">Maintenance</h3>
<ul>
  <li><strong>Update outdated NuGet package dependencies</strong> (<a href="https://github.com/sanelli/Mappa/issues/287">#287</a>, <a href="https://github.com/sanelli/Mappa/pull/337">#337</a>) — Bump Roslyn, analyzers, test packages, samples, benchmarks, and integration packages.</li>
  <li><strong>Release 10.2.0</strong> (<a href="https://github.com/sanelli/Mappa/issues/271">#271</a>, <a href="https://github.com/sanelli/Mappa/pull/338">#338</a>) — Promote version from <code class="language-plaintext highlighter-rouge">10.2.0-alpha.*</code> to stable <code class="language-plaintext highlighter-rouge">10.2.0</code>.</li>
</ul>

<h2 id="whats-next">What’s next</h2>
<p>This is a tentative and non-exhaustive list of issues that I would like to cover in the upcoming version of Mappa:</p>

<h3 id="mapping--generator-features">Mapping / generator features</h3>
<ul>
  <li><a href="https://github.com/sanelli/Mappa/issues/334">#334</a> — Inline mapping via C# interceptors</li>
  <li><a href="https://github.com/sanelli/Mappa/issues/256">#256</a> — Collection merge semantics and map into existing collections</li>
  <li><a href="https://github.com/sanelli/Mappa/issues/251">#251</a> — Conditional mapping, null substitution, and value transformers</li>
  <li><a href="https://github.com/sanelli/Mappa/issues/248">#248</a> — Generic mapping methods</li>
  <li><a href="https://github.com/sanelli/Mappa/issues/247">#247</a> — Map into existing target / merge semantics</li>
  <li><a href="https://github.com/sanelli/Mappa/issues/246">#246</a> — Reverse / bidirectional mapping</li>
  <li><a href="https://github.com/sanelli/Mappa/issues/283">#283</a> — <code class="language-plaintext highlighter-rouge">IQueryable</code> projection follow-ups</li>
  <li><a href="https://github.com/sanelli/Mappa/issues/73">#73</a> — Support fields, not only properties</li>
</ul>

<h3 id="generator-performance">Generator performance</h3>
<ul>
  <li><a href="https://github.com/sanelli/Mappa/issues/326">#326</a> — Optimize hot paths (<code class="language-plaintext highlighter-rouge">TypeSymbolExtensions</code>, constructor detection, attribute helpers)</li>
  <li><a href="https://github.com/sanelli/Mappa/issues/324">#324</a> — Reduce <code class="language-plaintext highlighter-rouge">Collect()</code> fan-out and document incremental host behavior</li>
  <li><a href="https://github.com/sanelli/Mappa/issues/314">#314</a> — Investigate Mapperly/Mapster benchmark wins and <code class="language-plaintext highlighter-rouge">FastCollections</code> behaviour</li>
</ul>

<h3 id="diagnostics-and-maintainability">Diagnostics and maintainability</h3>
<ul>
  <li><a href="https://github.com/sanelli/Mappa/issues/141">#141</a> — Improved debug feature</li>
</ul>]]></content><author><name>Stefano Anelli</name></author><category term="projects" /><category term="csharp" /><category term="nuget" /><category term="source-generator" /><category term="mappa" /><summary type="html"><![CDATA[A new version of Mappa (v10.2.0) has been released.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://stefano.ie/assets/images/stefano.jpg" /><media:content medium="image" url="https://stefano.ie/assets/images/stefano.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Mappa v10.1.0</title><link href="https://stefano.ie/projects/csharp/nuget/source-generator/mappa/2026/07/04/Mappa-v10.1.0.html" rel="alternate" type="text/html" title="Mappa v10.1.0" /><published>2026-07-04T19:00:00+00:00</published><updated>2026-07-04T19:00:00+00:00</updated><id>https://stefano.ie/projects/csharp/nuget/source-generator/mappa/2026/07/04/Mappa-v10.1.0</id><content type="html" xml:base="https://stefano.ie/projects/csharp/nuget/source-generator/mappa/2026/07/04/Mappa-v10.1.0.html"><![CDATA[<p>A new version of <a href="https://github.com/sanelli/Mappa">Mappa</a> (v10.1.0) has been released.</p>

<p>Mappa <strong>10.1.0</strong> builds on the 10.0.0 foundation with expanded enum mapping, richer parse and format <code class="language-plaintext highlighter-rouge">MappaSettings</code>, identity deep-copy and collection buffer options, stronger diagnostics, safer generated code, and a migrated test stack. Documentation now includes a full feature catalog.
<strong>Full changelog:</strong> <a href="https://github.com/sanelli/Mappa/compare/v10.0.0...v10.1.0">v10.0.0…v10.1.0</a></p>

<h2 id="breaking-changes">Breaking changes</h2>
<p>When upgrading from 10.0.0, see the <a href="https://github.com/sanelli/Mappa/blob/main/Documentation/upgrade.md">upgrade guide</a>.</p>

<h3 id="mappasettings-rename"><code class="language-plaintext highlighter-rouge">MappaSettings</code> rename</h3>
<ul>
  <li><strong><code class="language-plaintext highlighter-rouge">ForceCaseInsensitivePropertyMap</code> renamed to <code class="language-plaintext highlighter-rouge">CaseInsensitivePropertyMap</code></strong> (<a href="https://github.com/sanelli/Mappa/issues/257">#257</a>, <a href="https://github.com/sanelli/Mappa/pull/260">#260</a>)
    <ul>
      <li>Update attribute usage: <code class="language-plaintext highlighter-rouge">[MappaSettings(CaseInsensitivePropertyMap = BooleanSetting.Enable)]</code></li>
      <li>Update <code class="language-plaintext highlighter-rouge">.editorconfig</code>: <code class="language-plaintext highlighter-rouge">mappa.caseinsensitivepropertymap = enable</code></li>
      <li>The legacy <code class="language-plaintext highlighter-rouge">.editorconfig</code> key <code class="language-plaintext highlighter-rouge">mappa.forcecaseinsensitivepropertymap</code> is no longer supported</li>
    </ul>
  </li>
</ul>

<h3 id="stricter-diagnostics">Stricter diagnostics</h3>
<p>Projects that previously compiled may now fail with new or tightened generator errors:</p>

<ul>
  <li><strong>MP00042 — ambiguous invoke-method resolution</strong> (<a href="https://github.com/sanelli/Mappa/issues/233">#233</a>, <a href="https://github.com/sanelli/Mappa/pull/266">#266</a>) — When multiple methods match <code class="language-plaintext highlighter-rouge">[MappaInvokeMethod]</code> or a polymorphism <code class="language-plaintext highlighter-rouge">InvokeMethod</code> default, the generator reports an error instead of silently selecting the first match.</li>
  <li><strong>MP00038 — invalid parse style values</strong> (<a href="https://github.com/sanelli/Mappa/issues/231">#231</a>, <a href="https://github.com/sanelli/Mappa/pull/241">#241</a>) — Arbitrary integer <code class="language-plaintext highlighter-rouge">DateTimeStyles</code> / <code class="language-plaintext highlighter-rouge">NumberStyles</code> values in <code class="language-plaintext highlighter-rouge">[MappaSettings]</code> now produce a generator diagnostic instead of being silently decomposed into known flag bits.</li>
</ul>

<h2 id="whats-new">What’s new</h2>

<h3 id="test-infrastructure">Test infrastructure</h3>
<ul>
  <li><strong>Migrate to xUnit v3</strong> (<a href="https://github.com/sanelli/Mappa/issues/119">#119</a>, <a href="https://github.com/sanelli/Mappa/pull/222">#222</a>) — Test projects now use xUnit v3 and Microsoft Testing Platform.</li>
  <li><strong>Replace FluentAssertions with AwesomeAssertions</strong> (<a href="https://github.com/sanelli/Mappa/issues/208">#208</a>, <a href="https://github.com/sanelli/Mappa/pull/223">#223</a>) — Assertion library updated across all test projects.</li>
</ul>

<h3 id="new-features">New features</h3>
<ul>
  <li><strong><code class="language-plaintext highlighter-rouge">IdentityMapDeepCopy</code> setting</strong> (<a href="https://github.com/sanelli/Mappa/issues/14">#14</a>, <a href="https://github.com/sanelli/Mappa/pull/267">#267</a>) — Control shallow, deep, and nested same-type copying in identity mappings via <code class="language-plaintext highlighter-rouge">[MappaSettings]</code>.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">EnumerableConcreteType</code> setting</strong> (<a href="https://github.com/sanelli/Mappa/issues/29">#29</a>, <a href="https://github.com/sanelli/Mappa/pull/268">#268</a>) — Prefer <code class="language-plaintext highlighter-rouge">T[]</code> over <code class="language-plaintext highlighter-rouge">List&lt;T&gt;</code> when mapping to sequence-like interface targets (e.g. <code class="language-plaintext highlighter-rouge">IEnumerable&lt;T&gt;</code>).</li>
  <li><strong><code class="language-plaintext highlighter-rouge">DateTimeStyle</code> for parse</strong> (<a href="https://github.com/sanelli/Mappa/issues/214">#214</a>, <a href="https://github.com/sanelli/Mappa/pull/224">#224</a>) — Per-type <code class="language-plaintext highlighter-rouge">DateTimeStyles</code> for <code class="language-plaintext highlighter-rouge">Parse</code> / <code class="language-plaintext highlighter-rouge">ParseExact</code> on <code class="language-plaintext highlighter-rouge">DateTime</code>, <code class="language-plaintext highlighter-rouge">DateOnly</code>, and <code class="language-plaintext highlighter-rouge">TimeOnly</code>.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">NumberStyles</code> for parse</strong> (<a href="https://github.com/sanelli/Mappa/issues/215">#215</a>, <a href="https://github.com/sanelli/Mappa/pull/226">#226</a>) — Per-type <code class="language-plaintext highlighter-rouge">NumberStyles</code> for string-to-numeric <code class="language-plaintext highlighter-rouge">Parse</code> conversions.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">GlobalDateTimeStyle</code> and <code class="language-plaintext highlighter-rouge">GlobalNumberStyle</code></strong> (<a href="https://github.com/sanelli/Mappa/issues/225">#225</a>, <a href="https://github.com/sanelli/Mappa/pull/228">#228</a>) — Shared parse-style defaults applied across date/time and numeric types.</li>
</ul>

<h3 id="enum-mapping">Enum mapping</h3>
<ul>
  <li><strong><code class="language-plaintext highlighter-rouge">Description</code> attribute support</strong> (<a href="https://github.com/sanelli/Mappa/issues/15">#15</a>, <a href="https://github.com/sanelli/Mappa/issues/16">#16</a>, <a href="https://github.com/sanelli/Mappa/pull/265">#265</a>) — Map enums using <code class="language-plaintext highlighter-rouge">[Description]</code> for enum-to-string, string-to-enum, and enum-to-enum conversions.</li>
  <li><strong>Case-insensitive string-to-enum</strong> (<a href="https://github.com/sanelli/Mappa/issues/17">#17</a>, <a href="https://github.com/sanelli/Mappa/pull/258">#258</a>) — Optional case-insensitive matching when parsing strings to enums.</li>
  <li><strong>Numeric enum-to-enum mapping</strong> (<a href="https://github.com/sanelli/Mappa/issues/18">#18</a>, <a href="https://github.com/sanelli/Mappa/pull/264">#264</a>) — Map enums by numeric value instead of member name via <code class="language-plaintext highlighter-rouge">EnumToEnumMapSetting</code>.</li>
  <li><strong>Partial enum-to-enum warning (MP00039)</strong> (<a href="https://github.com/sanelli/Mappa/issues/19">#19</a>, <a href="https://github.com/sanelli/Mappa/pull/244">#244</a>) — Warn when not all source enum members can be mapped to the target enum.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">CaseInsensitiveEnumMap</code></strong> (<a href="https://github.com/sanelli/Mappa/issues/15">#15</a>, <a href="https://github.com/sanelli/Mappa/pull/265">#265</a>) — Optional case-insensitive enum member matching.</li>
  <li><strong>Rename <code class="language-plaintext highlighter-rouge">ForceCaseInsensitivePropertyMap</code></strong> (<a href="https://github.com/sanelli/Mappa/issues/257">#257</a>, <a href="https://github.com/sanelli/Mappa/pull/260">#260</a>) — Setting renamed to <code class="language-plaintext highlighter-rouge">CaseInsensitivePropertyMap</code>; legacy <code class="language-plaintext highlighter-rouge">.editorconfig</code> key removed.</li>
</ul>

<h3 id="mappainvokemethod-attribute"><code class="language-plaintext highlighter-rouge">[MappaInvokeMethod]</code> attribute</h3>
<ul>
  <li><strong>Optional <code class="language-plaintext highlighter-rouge">SourcePropertyName</code> parameter</strong> (<a href="https://github.com/sanelli/Mappa/issues/67">#67</a>, <a href="https://github.com/sanelli/Mappa/pull/243">#243</a>) — Invoke a method with an explicit source property value instead of the full source object.</li>
  <li><strong>Ambiguous invoke-method diagnostic (MP00042)</strong> (<a href="https://github.com/sanelli/Mappa/issues/233">#233</a>, <a href="https://github.com/sanelli/Mappa/pull/266">#266</a>) — Report a diagnostic when <code class="language-plaintext highlighter-rouge">[MappaInvokeMethod]</code> or polymorphism invoke-method resolution is ambiguous.</li>
</ul>

<h3 id="diagnostics-and-quality">Diagnostics and quality</h3>
<ul>
  <li><strong>Invalid style values (MP00038)</strong> (<a href="https://github.com/sanelli/Mappa/issues/231">#231</a>, <a href="https://github.com/sanelli/Mappa/pull/241">#241</a>) — Diagnose arbitrary integer <code class="language-plaintext highlighter-rouge">DateTimeStyles</code> / <code class="language-plaintext highlighter-rouge">NumberStyles</code> values in <code class="language-plaintext highlighter-rouge">[MappaSettings]</code>.</li>
  <li><strong>Test coverage improvements</strong> (<a href="https://github.com/sanelli/Mappa/issues/220">#220</a>, <a href="https://github.com/sanelli/Mappa/pull/239">#239</a>) — Additional generator, builder, and settings-stack tests for previously uncovered paths.</li>
  <li><strong>Fix <code class="language-plaintext highlighter-rouge">.editorconfig</code> <code class="language-plaintext highlighter-rouge">CurrentCulture</code> mapping</strong> (<a href="https://github.com/sanelli/Mappa/issues/229">#229</a>, <a href="https://github.com/sanelli/Mappa/pull/235">#235</a>) — Correct global culture resolution in <code class="language-plaintext highlighter-rouge">MappaGlobalOptions</code>.</li>
  <li><strong>Rename misleading local in <code class="language-plaintext highlighter-rouge">CanMapStringToNumber</code></strong> (<a href="https://github.com/sanelli/Mappa/issues/234">#234</a>, <a href="https://github.com/sanelli/Mappa/pull/242">#242</a>) — Internal readability fix in string strategy detection.</li>
</ul>

<h3 id="generated-code-safety">Generated code safety</h3>
<ul>
  <li><strong>Escape format and culture strings</strong> (<a href="https://github.com/sanelli/Mappa/issues/230">#230</a>, <a href="https://github.com/sanelli/Mappa/pull/236">#236</a>) — User-controlled format and culture strings are safely escaped in generated mapping code.</li>
  <li><strong>Escape attribute string literals</strong> (<a href="https://github.com/sanelli/Mappa/issues/232">#232</a>, <a href="https://github.com/sanelli/Mappa/pull/237">#237</a>) — User-controlled literals from mapping attributes are escaped in generated code.</li>
</ul>

<h3 id="documentation-and-samples">Documentation and samples</h3>
<ul>
  <li><strong>Feature catalog (<code class="language-plaintext highlighter-rouge">Documentation/features.md</code>)</strong> (<a href="https://github.com/sanelli/Mappa/issues/262">#262</a>, <a href="https://github.com/sanelli/Mappa/pull/263">#263</a>) — New page listing all Mappa features with links to tutorial, attributes, algorithm, and samples.</li>
  <li><strong>Generator algorithm documentation alignment</strong> (<a href="https://github.com/sanelli/Mappa/issues/227">#227</a>, <a href="https://github.com/sanelli/Mappa/pull/240">#240</a>) — Algorithm docs and generator README brought in line with the current implementation.</li>
  <li><strong>Suppress MP00039 in <code class="language-plaintext highlighter-rouge">EnumToEnumMapper</code> sample</strong> (<a href="https://github.com/sanelli/Mappa/issues/259">#259</a>, <a href="https://github.com/sanelli/Mappa/pull/261">#261</a>) — Intentional partial enum mapping demonstrated with <code class="language-plaintext highlighter-rouge">#pragma warning disable</code>.</li>
</ul>

<h2 id="whats-next">What’s next</h2>
<p>This is a tentative and non-exhaustive list of issues that I would like to cover in the upcoming version of Mappa:</p>

<h3 id="mapping--generator-features">Mapping / generator features</h3>
<ul>
  <li><a href="https://github.com/sanelli/Mappa/issues/255">#255</a> — Richer enum mapping configuration</li>
  <li><a href="https://github.com/sanelli/Mappa/issues/250">#250</a> — Before / after map hooks</li>
  <li><a href="https://github.com/sanelli/Mappa/issues/249">#249</a> — Circular reference / reference handling</li>
  <li><a href="https://github.com/sanelli/Mappa/issues/248">#248</a> — Generic mapping methods</li>
  <li><a href="https://github.com/sanelli/Mappa/issues/246">#246</a> — Reverse / bidirectional mapping</li>
  <li><a href="https://github.com/sanelli/Mappa/issues/245">#245</a> — IQueryable projection (<code class="language-plaintext highlighter-rouge">ProjectTo</code>)</li>
  <li><a href="https://github.com/sanelli/Mappa/issues/184">#184</a> — More relaxed nullability when matching methods</li>
  <li><a href="https://github.com/sanelli/Mappa/issues/120">#120</a> — Flattening and unflattening</li>
  <li><a href="https://github.com/sanelli/Mappa/issues/108">#108</a> — Allow preventing <code class="language-plaintext highlighter-rouge">Enumerable.Count</code> when targeting arrays, <code class="language-plaintext highlighter-rouge">Span</code>, and <code class="language-plaintext highlighter-rouge">Memory</code></li>
  <li><a href="https://github.com/sanelli/Mappa/issues/73">#73</a> — Support fields, not only properties</li>
  <li><a href="https://github.com/sanelli/Mappa/issues/34">#34</a> — Allow choosing <code class="language-plaintext highlighter-rouge">.Add</code> vs. the indexer for dictionary-to-dictionary mapping</li>
</ul>

<h3 id="language--platform">Language / platform</h3>
<ul>
  <li><a href="https://github.com/sanelli/Mappa/issues/174">#174</a> — Support C# 14 extension blocks in static classes (partial classes assumed)</li>
</ul>

<h3 id="diagnostics-and-maintainability">Diagnostics and maintainability</h3>
<ul>
  <li><a href="https://github.com/sanelli/Mappa/issues/141">#141</a> — Improved debug feature</li>
  <li><a href="https://github.com/sanelli/Mappa/issues/238">#238</a> — Reduce ReportGenerator CRAP score and cyclomatic complexity in <code class="language-plaintext highlighter-rouge">Mappa.Generator</code></li>
</ul>]]></content><author><name>Stefano Anelli</name></author><category term="projects" /><category term="csharp" /><category term="nuget" /><category term="source-generator" /><category term="mappa" /><summary type="html"><![CDATA[A new version of Mappa (v10.1.0) has been released.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://stefano.ie/assets/images/stefano.jpg" /><media:content medium="image" url="https://stefano.ie/assets/images/stefano.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Magia Bianca – Francesca Michielin</title><link href="https://stefano.ie/music/2026/07/03/magia-bianca.html" rel="alternate" type="text/html" title="Magia Bianca – Francesca Michielin" /><published>2026-07-03T19:00:00+00:00</published><updated>2026-07-03T19:00:00+00:00</updated><id>https://stefano.ie/music/2026/07/03/magia-bianca</id><content type="html" xml:base="https://stefano.ie/music/2026/07/03/magia-bianca.html"><![CDATA[<p>I was not expecting to like <a href="https://it.wikipedia.org/wiki/Magia_bianca_(album)">this album</a> so much. Finally a record that is not only about love love love. I am a guy, so I cannot really totally understand how it feels to be a woman, but I think <em>Magia Bianca</em> gave me a glimpse. I will probably listen to this over and over and over.</p>

<figure class="album-cover">
  <img src="/assets/images/posts/magia-bianca.jpg" alt="Cover of Magia Bianca by Francesca Michielin" width="640" height="640" />
  <figcaption>Cover painted by Danilo Bubani: a woman holding a scale with a dove and a raven.</figcaption>
</figure>

<p><strong>Favorite song.</strong> <em>Una donna non può.</em> “Forse sono pazza / Scontato che mi piaccia / La divinazione come pratica.” Those lines already say everything this album is about, and what I like to hear: something personal, something emotional, and not just love, or the emotions around love. Something about yourself. A masterpiece. It is also a feminist hymn, very vocal about what society does not want women to do. The whole record is a way of telling everyone those assumptions are wrong: what a woman can or cannot do, or should.</p>

<p><strong>Favorite intro.</strong> <em>1484.</em> I am not sure what instrument opens it (probably the harpsichord she has talked about), but it puts me at the court of a king, listening to medieval music, eating roast turkey cooked on an open fire, while jesters sing, dance, and play.</p>

<p><strong>Favorite lyrics.</strong> “Servirebbe un incantesimo contro il tecnofeudalesimo,” from <em>Feral Girl</em>. I am not sure what Francesca really wanted to say with that line. I read somewhere that she even thought of calling the album <em>Tecnofeudalesimo</em>. For me it strikes a chord because I am trying to use less technology, mainly to spend less time doomscrolling on the phone. These are the kind of lyrics I find myself humming on the way to work.</p>

<p><strong>Special mention.</strong> <em>Litha.</em> The repetitive “Vieni vieni intorno al fuoco / scordati chi eri quando inizia il gioco / vieni vieni intorno al fuoco / mescola anche tu le lacrime all’alloro” makes me feel like a witch jumping around a bonfire, in silky clothes, throwing bay leaves into the fire, under a full moon. This song is very, very evocative.</p>

<p><strong>The only one I cannot vibe with.</strong> Weirdly enough, the song that appeals to me the least is <em>Magia bianca, magia nera</em>, the one that gives the album its name. I kind of understand the point of the lyrics, I think: you do not have to sit in the box of what other people call white magic or black magic; you can decide for yourself. Musically, though, it feels less connected to the rest of the album.</p>

<aside class="album-facts">
  <p class="album-facts-label">Album information</p>
  <p><em>Magia Bianca</em> is Francesca Michielin's sixth studio album, released on 12 June 2026 by Columbia and Sony Music. She wrote and produced it with David Kosten, Rocco Rampino, Davide Simonetta, and others, as a short concept record about witches, folklore, and what a woman is allowed to be. The title, she has said, goes back to a conversation with Elisa about making music as white magic or as a commercial logic; she also called it a homage to her land around Bassano del Grappa, and "the album of my reconnection." Guest voices appear as "spettri": Patrizia Laquidara, Angelica, Veronica Lucchesi, Ceneri, and a nod to Caparezza.</p>
</aside>

<p class="listen-links">
  <a class="listen-link" href="https://open.spotify.com/album/0o4CGBDcEUP1S0ODvG9N8Z"><svg class="icon icon-spotify" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><use href="#icon-spotify"></use></svg>Spotify</a>
  <a class="listen-link" href="https://music.youtube.com/search?q=Magia+Bianca+Francesca+Michielin"><svg class="icon icon-youtube-music" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><use href="#icon-youtube-music"></use></svg>YouTube Music</a>
  <a class="listen-link" href="https://music.apple.com/album/magia-bianca/6771692760"><svg class="icon icon-apple-music" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><use href="#icon-apple-music"></use></svg>Apple Music</a>
</p>

<p class="made-with">— Made with<svg class="icon icon-cursor" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><use href="#icon-cursor"></use></svg><a href="https://cursor.com">Cursor</a></p>]]></content><author><name>Stefano Anelli</name></author><category term="music" /><summary type="html"><![CDATA[I was not expecting to like this album so much. Finally a record that is not only about love love love. I am a guy, so I cannot really totally understand how it feels to be a woman, but I think Magia Bianca gave me a glimpse. I will probably listen to this over and over and over.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://stefano.ie/assets/images/stefano.jpg" /><media:content medium="image" url="https://stefano.ie/assets/images/stefano.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Mappa v10.0.0</title><link href="https://stefano.ie/projects/csharp/nuget/source-generator/mappa/2026/06/11/Mappa-v10.0.0.html" rel="alternate" type="text/html" title="Mappa v10.0.0" /><published>2026-06-11T21:01:00+00:00</published><updated>2026-06-11T21:01:00+00:00</updated><id>https://stefano.ie/projects/csharp/nuget/source-generator/mappa/2026/06/11/Mappa-v10.0.0</id><content type="html" xml:base="https://stefano.ie/projects/csharp/nuget/source-generator/mappa/2026/06/11/Mappa-v10.0.0.html"><![CDATA[<p>A new version of <a href="https://github.com/sanelli/Mappa">Mappa</a> (v10.0.0) has been released.</p>

<p>Mappa <strong>10.0.0</strong> is a major release. It targets <strong>.NET 10</strong>, adds polymorphic mapping and richer configuration, and expands <code class="language-plaintext highlighter-rouge">MappaInvokeMethod</code>, constructor mapping, and collection support. Documentation and samples were reviewed end-to-end.
<strong>Full changelog:</strong> <a href="https://github.com/sanelli/Mappa/compare/v1.2.0...v10.0.0">v1.2.0…v10.0.0</a></p>

<h2 id="whats-new">What’s new</h2>

<h3 id="platform">Platform</h3>
<ul>
  <li><strong>Migrate to .NET 10</strong> (<a href="https://github.com/sanelli/Mappa/issues/178">#178</a>, <a href="https://github.com/sanelli/Mappa/pull/188">#188</a>) — Mappa now targets .NET 10; upgrade consuming projects accordingly.</li>
</ul>

<h3 id="new-features">New features</h3>
<ul>
  <li><strong>Polymorphic mapping</strong> (<a href="https://github.com/sanelli/Mappa/issues/49">#49</a>, <a href="https://github.com/sanelli/Mappa/pull/187">#187</a>) — Map base types to derived instances when the runtime type is known.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">MappaAssignToContext</code> attribute</strong> (<a href="https://github.com/sanelli/Mappa/issues/205">#205</a>, <a href="https://github.com/sanelli/Mappa/pull/207">#207</a>) — Assign mapped values into <code class="language-plaintext highlighter-rouge">MappaContext</code> during generation.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">MappaSettings</code> property name matching</strong> (<a href="https://github.com/sanelli/Mappa/issues/98">#98</a>, <a href="https://github.com/sanelli/Mappa/pull/211">#211</a>) — Configure how source and target property names are matched (e.g. case sensitivity).</li>
  <li><strong>Constructor strategy: ignore target properties</strong> (<a href="https://github.com/sanelli/Mappa/issues/3">#3</a>, <a href="https://github.com/sanelli/Mappa/pull/204">#204</a>) — Exclude specific target properties from constructor-based mapping via attribute.</li>
  <li><strong>String → <code class="language-plaintext highlighter-rouge">Parse(string)</code> mapping</strong> (<a href="https://github.com/sanelli/Mappa/issues/52">#52</a>, <a href="https://github.com/sanelli/Mappa/pull/177">#177</a>) — Map <code class="language-plaintext highlighter-rouge">string</code> to any type that exposes <code class="language-plaintext highlighter-rouge">static TTarget Parse(string)</code>.</li>
  <li><strong>Numeric format and <code class="language-plaintext highlighter-rouge">IFormatProvider</code></strong> (<a href="https://github.com/sanelli/Mappa/issues/76">#76</a>, <a href="https://github.com/sanelli/Mappa/pull/216">#216</a>) — Control culture and format for numeric <code class="language-plaintext highlighter-rouge">Parse</code> / <code class="language-plaintext highlighter-rouge">ToString</code> conversions.</li>
</ul>

<h3 id="mappainvokemethod-attribute"><code class="language-plaintext highlighter-rouge">[MappaInvokeMethod]</code> attribute</h3>
<ul>
  <li><strong><code class="language-plaintext highlighter-rouge">MappaContext</code> parameters</strong> (<a href="https://github.com/sanelli/Mappa/issues/70">#70</a>, <a href="https://github.com/sanelli/Mappa/pull/206">#206</a>) — Invoked methods can accept <code class="language-plaintext highlighter-rouge">MappaContext</code> arguments.</li>
  <li><strong>Hierarchy lookup</strong> (<a href="https://github.com/sanelli/Mappa/issues/179">#179</a>, <a href="https://github.com/sanelli/Mappa/pull/199">#199</a>) — Optional fields, properties, and methods are resolved up the class hierarchy.</li>
  <li><strong>Instance member access</strong> (<a href="https://github.com/sanelli/Mappa/issues/193">#193</a>, <a href="https://github.com/sanelli/Mappa/pull/195">#195</a>) — Non-static fields and properties are referenced with <code class="language-plaintext highlighter-rouge">this.</code> in generated code.</li>
  <li><strong>Static vs. instance safety</strong> (<a href="https://github.com/sanelli/Mappa/issues/190">#190</a>, <a href="https://github.com/sanelli/Mappa/pull/194">#194</a>) — A static mapping method cannot invoke a non-static method.</li>
  <li><strong>Non-static method dependencies</strong> (<a href="https://github.com/sanelli/Mappa/issues/185">#185</a>, <a href="https://github.com/sanelli/Mappa/pull/191">#191</a>) — Method dependency lookup can use accessible non-static methods where appropriate.</li>
</ul>

<h3 id="mapping-improvements">Mapping improvements</h3>
<ul>
  <li><strong>Collection concrete types with capacity constructors</strong> (<a href="https://github.com/sanelli/Mappa/issues/109">#109</a>, <a href="https://github.com/sanelli/Mappa/pull/176">#176</a>) — Support collection types that expose a capacity constructor.</li>
  <li><strong>Read-only collection properties</strong> (<a href="https://github.com/sanelli/Mappa/issues/110">#110</a>, <a href="https://github.com/sanelli/Mappa/pull/202">#202</a>) — Broader support when targeting read-only properties of collection types.</li>
  <li><strong>Inherited mapping methods</strong> (<a href="https://github.com/sanelli/Mappa/issues/186">#186</a>, <a href="https://github.com/sanelli/Mappa/pull/196">#196</a>) — Methods used for mapping are discovered in parent classes.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">MappaDependency</code> in base classes</strong> (<a href="https://github.com/sanelli/Mappa/issues/183">#183</a>, <a href="https://github.com/sanelli/Mappa/pull/197">#197</a>) — Fields and properties marked with <code class="language-plaintext highlighter-rouge">MappaDependency</code> are picked up from accessible members in parent classes.</li>
</ul>

<h3 id="diagnostics-and-quality">Diagnostics and quality</h3>
<ul>
  <li><strong>Missing attribute warnings</strong> (<a href="https://github.com/sanelli/Mappa/issues/154">#154</a>, <a href="https://github.com/sanelli/Mappa/pull/203">#203</a>) — Additional compiler warnings for misconfigured or incomplete attribute usage.</li>
  <li><strong>EditorConfig integration tests for <code class="language-plaintext highlighter-rouge">MappaSettings</code></strong> (<a href="https://github.com/sanelli/Mappa/issues/210">#210</a>, <a href="https://github.com/sanelli/Mappa/pull/213">#213</a>) — Settings behavior is validated against EditorConfig configuration.</li>
</ul>

<h3 id="documentation-and-samples">Documentation and samples</h3>
<ul>
  <li><strong>Tutorial and documentation review</strong> (<a href="https://github.com/sanelli/Mappa/issues/148">#148</a>, <a href="https://github.com/sanelli/Mappa/pull/217">#217</a>) — Tutorial advanced topics, attribute reference, error codes, and package READMEs updated and aligned with current behavior.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">MappaInvokeMethod</code> docs for <code class="language-plaintext highlighter-rouge">MappaContext</code></strong> (<a href="https://github.com/sanelli/Mappa/issues/209">#209</a>, <a href="https://github.com/sanelli/Mappa/pull/212">#212</a>) — Documented rules for <code class="language-plaintext highlighter-rouge">MappaContext</code> in invoked methods.</li>
  <li><strong>AOT samples coverage</strong> (<a href="https://github.com/sanelli/Mappa/issues/41">#41</a>, <a href="https://github.com/sanelli/Mappa/pull/198">#198</a>) — <code class="language-plaintext highlighter-rouge">Mappa.Samples.Aot</code> now runs all sample mappers for native/AOT validation.</li>
</ul>

<h3 id="maintenance">Maintenance</h3>
<ul>
  <li><strong>CI and tooling</strong> (<a href="https://github.com/sanelli/Mappa/issues/200">#200</a>, <a href="https://github.com/sanelli/Mappa/pull/201">#201</a>) — GitHub Actions dependencies bumped to current versions.</li>
  <li><strong>TODO hygiene</strong> (<a href="https://github.com/sanelli/Mappa/issues/182">#182</a>, <a href="https://github.com/sanelli/Mappa/pull/189">#189</a>) — Guard against leftover issue TODOs in the codebase.</li>
</ul>

<h2 id="whats-next">What’s next</h2>
<p>This is a tentative and non-exhaustive list of issues that I would like to cover in the upcoming version of Mappa:</p>

<h3 id="mapping--generator-features">Mapping / generator features</h3>
<ul>
  <li><a href="https://github.com/sanelli/Mappa/issues/215">#215</a> — Support <code class="language-plaintext highlighter-rouge">NumberStyles</code> for <code class="language-plaintext highlighter-rouge">Parse</code> on all numeric types</li>
  <li><a href="https://github.com/sanelli/Mappa/issues/214">#214</a> — Support <code class="language-plaintext highlighter-rouge">DateTimeStyle</code> for <code class="language-plaintext highlighter-rouge">Parse</code> / <code class="language-plaintext highlighter-rouge">ParseExact</code> on <code class="language-plaintext highlighter-rouge">DateTime</code>, <code class="language-plaintext highlighter-rouge">DateOnly</code>, <code class="language-plaintext highlighter-rouge">TimeOnly</code></li>
  <li><a href="https://github.com/sanelli/Mappa/issues/184">#184</a> — More relaxed nullability when matching methods</li>
  <li><a href="https://github.com/sanelli/Mappa/issues/181">#181</a> — Speed up enum mappings with <code class="language-plaintext highlighter-rouge">switch</code> expressions</li>
  <li><a href="https://github.com/sanelli/Mappa/issues/175">#175</a> — Support mapping empty → empty type</li>
  <li><a href="https://github.com/sanelli/Mappa/issues/155">#155</a> — Add <code class="language-plaintext highlighter-rouge">MappaUseConstructor</code> attribute to pick which constructor to use</li>
  <li><a href="https://github.com/sanelli/Mappa/issues/120">#120</a> — Allow mapping via nested source property chains</li>
  <li><a href="https://github.com/sanelli/Mappa/issues/73">#73</a> — Support fields, not only properties</li>
  <li><a href="https://github.com/sanelli/Mappa/issues/67">#67</a> — <code class="language-plaintext highlighter-rouge">MappaInvokeMethodAttribute</code>: add <code class="language-plaintext highlighter-rouge">SourceProperty</code> parameter</li>
  <li><a href="https://github.com/sanelli/Mappa/issues/29">#29</a> — Option to prefer arrays over lists in generated code</li>
  <li><a href="https://github.com/sanelli/Mappa/issues/19">#19</a> — Fail enum→enum maps when not all source values are mappable</li>
</ul>

<h3 id="language--platform">Language / platform</h3>
<ul>
  <li><a href="https://github.com/sanelli/Mappa/issues/174">#174</a> — Support C# 14 extension blocks in static classes (partial classes assumed)</li>
</ul>

<h3 id="protobuf">Protobuf</h3>
<ul>
  <li><a href="https://github.com/sanelli/Mappa/issues/89">#89</a> — Polymorphism via protobuf <code class="language-plaintext highlighter-rouge">oneof</code> for both source and target</li>
</ul>

<h3 id="testing--benchmarks--ci">Testing / benchmarks / CI</h3>
<ul>
  <li><a href="https://github.com/sanelli/Mappa/issues/208">#208</a> — Migrate away from FluentAssertions</li>
  <li><a href="https://github.com/sanelli/Mappa/issues/119">#119</a> — Migrate to xUnit v3</li>
  <li><a href="https://github.com/sanelli/Mappa/issues/134">#134</a> — Improve benchmarks</li>
  <li><a href="https://github.com/sanelli/Mappa/issues/152">#152</a> — Run benchmarks on CI/CD when merging to <code class="language-plaintext highlighter-rouge">main</code></li>
</ul>]]></content><author><name>Stefano Anelli</name></author><category term="projects" /><category term="csharp" /><category term="nuget" /><category term="source-generator" /><category term="mappa" /><summary type="html"><![CDATA[A new version of Mappa (v10.0.0) has been released.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://stefano.ie/assets/images/stefano.jpg" /><media:content medium="image" url="https://stefano.ie/assets/images/stefano.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">New Brainfuck interpreter implemented in Erlang</title><link href="https://stefano.ie/projects/brainfuck/interpreter/erlang/2026/01/04/brainfuck-erlang.html" rel="alternate" type="text/html" title="New Brainfuck interpreter implemented in Erlang" /><published>2026-01-04T12:08:00+00:00</published><updated>2026-01-04T12:08:00+00:00</updated><id>https://stefano.ie/projects/brainfuck/interpreter/erlang/2026/01/04/brainfuck-erlang</id><content type="html" xml:base="https://stefano.ie/projects/brainfuck/interpreter/erlang/2026/01/04/brainfuck-erlang.html"><![CDATA[<p>Added the <a href="https://github.com/sanelli/brainfuck/tree/main/erlang">Erlang</a> implementation to the <a href="https://github.com/sanelli/brainfuck">suite of Brainfuck interpreters</a>.</p>]]></content><author><name>Stefano Anelli</name></author><category term="projects" /><category term="brainfuck" /><category term="interpreter" /><category term="erlang" /><summary type="html"><![CDATA[Added the Erlang implementation to the suite of Brainfuck interpreters.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://stefano.ie/assets/images/stefano.jpg" /><media:content medium="image" url="https://stefano.ie/assets/images/stefano.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>