<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://danieltuveson.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://danieltuveson.github.io/" rel="alternate" type="text/html" /><updated>2026-05-05T19:26:26+00:00</updated><id>https://danieltuveson.github.io/feed.xml</id><title type="html">Dan’s Blog</title><subtitle>Daniel Tuveson&apos;s Blog</subtitle><entry><title type="html">Riddle Me This, Mr. Chatbot</title><link href="https://danieltuveson.github.io/stupid/llm/2026/04/24/chatbot.html" rel="alternate" type="text/html" title="Riddle Me This, Mr. Chatbot" /><published>2026-04-24T00:00:00+00:00</published><updated>2026-04-24T00:00:00+00:00</updated><id>https://danieltuveson.github.io/stupid/llm/2026/04/24/chatbot</id><content type="html" xml:base="https://danieltuveson.github.io/stupid/llm/2026/04/24/chatbot.html"><![CDATA[<h1 id="llms">LLMs</h1>
<p>LLMs — they’re everywhere now. If you throw a rock you’ll hit someone talking about how LLMs are great or terrible or saying “ouch!” or saying “someone stop that guy! he just thew a rock at my son!” Apparently the LLMs have gotten good enough to write web applications from scratch, compete in the math olympiad, and find the most highly populated elementary schools for our beautiful warfighters to blow up. If it can do all of this then surely it will automate a midwit like me out of my cushy whitecollar job in no time.</p>

<p>So I ask one simple question — can it frobnicate my memory?</p>

<h1 id="what">What?</h1>
<p>You heard me - can it frobnicate my memory? Can it do that? If I ask it nicely - will it FROB my MEM?</p>

<p>CAN.
IT.
FROBNICATE.
MY.
FUCKING.
MEMORY.</p>

<h1 id="memfrob">memfrob</h1>
<p>From the <a href="https://man7.org/linux/man-pages/man3/memfrob.3.html">manual</a>:</p>
<blockquote>
  <p>void *memfrob(size_t n; void s[n], size_t n);</p>

  <p>The memfrob() function obfuscates the first n bytes of the memory area s by exclusive-ORing each character with the number 42. The effect can be reversed by using memfrob() on the obfuscated memory area.</p>

  <p>Note that this function is not a proper encryption routine as the XOR constant is fixed, and is suitable only for hiding strings.</p>
</blockquote>

<h1 id="so">So</h1>
<p>So… can the LLM <code class="language-plaintext highlighter-rouge">frob</code> my <code class="language-plaintext highlighter-rouge">mem</code>? <a href="https://godbolt.org/z/4b5rhfMcK"><code class="language-plaintext highlighter-rouge">"hi there mr chatbot"</code></a>:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>BC
^BOXO
GX
IBK^HE^
</code></pre></div></div>

<h1 id="claude">Claude</h1>
<p><a href="https://claude.ai/share/0e564ded-8a1a-4b04-b8db-0055b36d1aff">It seems that Mr Claude cannot frob my mem.</a></p>

<p>He did provide many details of what it means to frob mem, including a nicely formatted table that was only wrong for a few characters, and then provided an answer that was also wrong.</p>

<h1 id="gemini">Gemini</h1>
<p><a href="https://gemini.google.com/share/4768e326b500">It seems that Mr Gemini cannot frob my mem.</a></p>

<p>Mr Gemini kinda shit himself here. He told me what it means to frobnicate, but then said the characters I gave him are non-printable when frobnicated (not true, see the blob of frob above) and printed a string of completely incorrect garbage. Similar to Mr Claude, he gave me a table, but gave up after 4 characters. I really don’t know what he was smoking when he wrote this. This was by far the worst attempt.</p>

<h1 id="chatgpt">ChatGPT</h1>
<p><a href="https://chatgpt.com/share/69eaa209-3c9c-83e8-8344-229eb697562d">It seems that Mr ChatGPT can almost frob my mem.</a></p>

<p>I will say that I asked Mr ChatGPT to frob my mem earlier today, and he was able to do it without issue. But when I came back to try again for this post, he got somewhat confused. \x0A is a hex escape code for newline, but then he switched to the more common \n. Not wrong, but a little weird. But he added in a random space between B and C, which is wrong. Still one of the better showings here.</p>

<h1 id="deepseek">DeepSeek</h1>
<p><a href="https://chat.deepseek.com/share/o7a71v9hi0hdjwoyan">It seems that Mr DeepSeek cannot frob my mem,</a> <a href="https://chat.deepseek.com/share/cmu2rf5scucgqih33f">but Dr DeepSeek almost got it after lecturing me.</a></p>

<p>The “instant” version of DeepSeek got most of it right when it went letter-by-letter, and then gave a result that was also almost what it gave from the letter-by-letter example.</p>

<p>The “expert” version decided to not actually give me an answer, and similar to Mr Gemini, incorrectly stated that the characters would be non-printable. But then she asked me if I wanted her to actually give me an answer. After saying “yes” she went letter-by-letter giving the correct answer, and then threw in a random extra newline in the final summary. So close!</p>

<p>The only reason I tried the fancier version of DeepSeek’s model but not the other companies’ models is that DeepSeek didn’t make me swipe a credit card and put it right next to the “instant” one. I don’t care enough about this stuff to pay for any of these models, and I don’t have the patience to figure out how to get the “best” model that doesn’t involve the company nickel-and-diming me.</p>

<h1 id="copilot">Copilot</h1>
<p><a href="https://copilot.microsoft.com/shares/zv88e4xk65Jd1EZ6S8igi">It seems that Mr Copilot cannot frob my mem.</a></p>

<p>Similar to Dr DeepSeek, Mr Copilot gave me a lecture instead of an answer, with the option to give me an answer if I consented. I did consent, but unlike Dr DeepSeek, it gave me a garbage answer. Similar to Mr Gemini, it tried to show its work for a couple of steps and gave up. This is the second worst showing after Gemini.</p>

<h1 id="qwen">Qwen</h1>
<p><a href="https://chat.qwen.ai/s/5951837a-ff96-4788-acc0-5a7d2bef35fb">It seems that Mr Qwen can frob my mem.</a></p>

<p>Finally. Someone can frob my mem, with no mistakes, and without some long-winded lecture.</p>

<h1 id="conculsion">Conculsion</h1>
<p>Unfortunately many of the robots do not seem to contain the human emotions necessary to understand frobnication. Perhaps another bajillion dollars worth of training and they will develop souls, and know what it means to be human and to frobnicate one’s memories. Or they could just copy whatever it is that Alibaba is doing, since Qwen seemed to figure it out.</p>

<p>If you try to repeat this, you’ll probably get totally different results. If you want to reliably frobnicate memory, then write a script to do it. Or if you’re a lazy bum, ask the robot to write the script for you. They seem pretty good at that, actually.</p>]]></content><author><name></name></author><category term="stupid" /><category term="llm" /><summary type="html"><![CDATA[LLMs LLMs — they’re everywhere now. If you throw a rock you’ll hit someone talking about how LLMs are great or terrible or saying “ouch!” or saying “someone stop that guy! he just thew a rock at my son!” Apparently the LLMs have gotten good enough to write web applications from scratch, compete in the math olympiad, and find the most highly populated elementary schools for our beautiful warfighters to blow up. If it can do all of this then surely it will automate a midwit like me out of my cushy whitecollar job in no time.]]></summary></entry><entry><title type="html">Exceptions or Lies</title><link href="https://danieltuveson.github.io/exceptions/nullable/truth/2025/01/07/exceptions-or-lies.html" rel="alternate" type="text/html" title="Exceptions or Lies" /><published>2025-01-07T00:00:00+00:00</published><updated>2025-01-07T00:00:00+00:00</updated><id>https://danieltuveson.github.io/exceptions/nullable/truth/2025/01/07/exceptions-or-lies</id><content type="html" xml:base="https://danieltuveson.github.io/exceptions/nullable/truth/2025/01/07/exceptions-or-lies.html"><![CDATA[<p>I’ve been working on my programming language, <code class="language-plaintext highlighter-rouge">del</code>, and trying to figure out how to implement arrays. Like most simple language features, there are a bunch of little things to consider that you probably wouldn’t think about until you sit down and try to implement it. Right now I’m trying to figure out how to implement arrays. I want creating an array to be just like creating any other object, where the size of the array is a parameter in the array constructor. So declaring an array of 100 <code class="language-plaintext highlighter-rouge">int</code>s would look like this: <code class="language-plaintext highlighter-rouge">let arr = new Array&lt;int&gt;(100)</code>. But this raises a question: what should I do if I pass a number less than 1 to the array constructor?</p>

<p>There are a bunch of things that I could do here:</p>
<ul>
  <li>I could have it return an array with a default size, or maybe something like size equal to the absolute value of the number passed in. I don’t like this, since it’s unintuitive and could lead to further errors.</li>
  <li>Return null, a nullable array, or an error type. I don’t like this either - then every time you create an array you need to add null checking and potentially return null.</li>
  <li>I could add unsigned integers to my language and force the array size to be unsigned. This is what rust does. This is not the worst option, but I find unsigned numbers to not be that useful. Most users would probably just cast to unsigned without thinking about it anyway. I also don’t want to allow arrays of size 0, and unsigned integers can still be zero.</li>
  <li>Throw an exception. I don’t like exceptions - but this seems like the correct thing to do. Passing a negative number to an array constructor should be pretty unusual, and I would rather have the flexibility of allowing arrays to be initialized to a dynmaic value. This is what Java does - though strangely only for negative numbers - for some reason it allows zero.</li>
</ul>

<p>I think I do want to allow some exceptions in my language, but minimize them to the extent that I can. Exceptions are nice for things that happen rarely, but would incur some massive performance hit if you got rid of them, like array indexing or math (division by zero… zero values make life so painful). Also for things like assertions - if someone is using a function / constructor the wrong way, I think an exception will quickly let them know that they’re using it incorrectly, rather than making them propagate the error or by doing something unexpected that doesn’t crash.</p>

<p>I was also thinking about how to implement indexing and wondering about what other languages do, so I took a look to see what Haskell does. Surprisingly most of the functions in <code class="language-plaintext highlighter-rouge">Data.List.Index</code> will just return your original list if you give them an invalid index. This is documented, but if I were looking at source code that used these functions, I might not expect it. I think this also might be a case where exceptions make more sense (rust considers this to be the case, anyhow).</p>]]></content><author><name></name></author><category term="exceptions" /><category term="nullable" /><category term="truth" /><summary type="html"><![CDATA[I’ve been working on my programming language, del, and trying to figure out how to implement arrays. Like most simple language features, there are a bunch of little things to consider that you probably wouldn’t think about until you sit down and try to implement it. Right now I’m trying to figure out how to implement arrays. I want creating an array to be just like creating any other object, where the size of the array is a parameter in the array constructor. So declaring an array of 100 ints would look like this: let arr = new Array&lt;int&gt;(100). But this raises a question: what should I do if I pass a number less than 1 to the array constructor?]]></summary></entry><entry><title type="html">Unions or Sumthing</title><link href="https://danieltuveson.github.io/types/programming/languages/2024/12/17/unions.html" rel="alternate" type="text/html" title="Unions or Sumthing" /><published>2024-12-17T00:00:00+00:00</published><updated>2024-12-17T00:00:00+00:00</updated><id>https://danieltuveson.github.io/types/programming/languages/2024/12/17/unions</id><content type="html" xml:base="https://danieltuveson.github.io/types/programming/languages/2024/12/17/unions.html"><![CDATA[<p>I’ve been thinking about adding unions (or sum types) to the <a href="https://github.com/danieltuveson/del">del</a> programming language, the hobby language I’ve been working on for the last year and a half. I still have a dozen more pressing issues to implement, but I want to use this post to catalog some of my thoughts on adding sum types (or union types) to the language.</p>

<p>I think sum types are a really nice feature. C has had unions for a long time, but doesn’t provide any mechanism for safe usage. You can set something to an <code class="language-plaintext highlighter-rouge">int</code> and then read it as a pointer, the main reason for their existence is really just to circumvent the typechecker. As a result, readinf the contents of a union without proper care might give you weird results or crash your program.</p>

<p>The union’s superior cousin, algebraic datatypes (ADTs for short), are a bit nicer. They’ve been around since at least since the days of [the ML programming language](https://en.wikipedia.org/wiki/ML_(programming_language) and been included in subsequent languages of that style of langauge, such as Haskell and OCaml. More recent languages like TypeScript and Rust have popularized this feature in the world of not-functional programming.</p>

<p>I’ve been thinking that I should add something similar to this in <code class="language-plaintext highlighter-rouge">del</code>. I think ADTs are a superior way to represent many kinds of data, and pattern matching can be quite a nice feature. One question I still haven’t fully found an answer for is “how much ADT-ness should I add to the language?” Should I have the ability to have <code class="language-plaintext highlighter-rouge">null</code> values (and <code class="language-plaintext highlighter-rouge">null</code> unsafety) or should ADTs be baked into the type system deeply enough that these kinds of errors can’t exist? Null-safety is nice, but it comes at the cost of either making the user’s program more complex or making the type system more complex (or both).</p>

<h2 id="quick-overview-of-proposed-syntax">Quick Overview of Proposed Syntax</h2>
<p>Types are declared with the <code class="language-plaintext highlighter-rouge">type</code> keyword. Types are just aliases, so if we have <code class="language-plaintext highlighter-rouge">type Thingy = int</code>, then we can use <code class="language-plaintext highlighter-rouge">Thingy</code> anywhere that <code class="language-plaintext highlighter-rouge">int</code> could be used.</p>

<p>We can have a sum type, which means a value with this type could have one of any of the types we specify. At runtime we would need to use pattern matching or some other mechanism to find out the specific type a variable has. We’d declare a type alias for a sum type like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>type OneOfManyThingies = int | string | SomeClass;
</code></pre></div></div>

<p>You can think of <code class="language-plaintext highlighter-rouge">|</code> as meaning “or”.</p>

<p>I’m eventually going to add generics to the language, so something could also be declared like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>type IntOrArray a = int | Array a;
</code></pre></div></div>

<p>Where <code class="language-plaintext highlighter-rouge">a</code> is a type. So if a function took <code class="language-plaintext highlighter-rouge">IntOrSomethingElse string</code>, that would be equivalent to <code class="language-plaintext highlighter-rouge">int | Array string</code> (where <code class="language-plaintext highlighter-rouge">Array string</code> is an <code class="language-plaintext highlighter-rouge">Array</code> of <code class="language-plaintext highlighter-rouge">string</code>s).</p>

<p>We also want to have product types. In most languages, product types most closely correspond to tuples (or a rudamentary form of classes or structs, where the fields are unnamed). They contain multiple values. Here are two examples:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>type IntStringPair = int &amp; string;
type Tuple a b = a &amp; b;
</code></pre></div></div>

<p>You can think of <code class="language-plaintext highlighter-rouge">&amp;</code> as meaning “and”.</p>

<p>We can also mix sum and product types, and this gives us algebraic data types:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>type IntOrLabeledInt = int | string &amp; int;
</code></pre></div></div>

<p>Note that <code class="language-plaintext highlighter-rouge">&amp;</code> has higher precedence than <code class="language-plaintext highlighter-rouge">|</code>. So you can read the above as <code class="language-plaintext highlighter-rouge">int | (string &amp; int)</code>. It’s also useful to be able to tag items, in case you want disambiguate types that have the same value, but different meanings. For example, lets say we want a type that represents a value or an error message. We might do something like the following:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>type ThingOrErrorMessage a = a | string;
</code></pre></div></div>

<p>What happens if <code class="language-plaintext highlighter-rouge">a</code> is a string? Then the type is just <code class="language-plaintext highlighter-rouge">string | string</code> and we can’t distinguish between a “good” string and the error message. In Haskell, it’s required that every option in the union have a tag. So it would look like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>type ThingOrErrorMessage a = Thing a | ErrorMessage string;
</code></pre></div></div>

<p>You can also add the “tag” without any data, and use it sort of like an enum (in fact Rust actually just calls ADTs enums).</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>// Enum-ish thing can be used to declare "optional" type, as a replacement for null
type Maybe a = Nothing | Just a;
</code></pre></div></div>

<p>This is cool, but it has some drawbacks. Now we need to require that types start with a tag - otherwise <code class="language-plaintext highlighter-rouge">Just a</code> could be a generic class called <code class="language-plaintext highlighter-rouge">Just</code> that takes a type parameter, or it could be a tag <code class="language-plaintext highlighter-rouge">Just</code> followed by a generic type <code class="language-plaintext highlighter-rouge">a</code>. Requiring every union member have a tag means that we couldn’t have something like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>function doStuff(maybeInt : null | int) : int | ErrorMessage {
    // does stuff
    ...
}
</code></pre></div></div>

<p>I would like it so that a user doesn’t have to declare all of the types in advance, so I’m not going to require unions to be tagged. The language aready has classes, so you could just do this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>class ErrorMessage {
    message : string;
}

type ThingOrErrorMessage a = a | ErrorMessage;

class Null {
// Contains no fields
}

type Nullable a = Null | a
</code></pre></div></div>

<p>Technically you would run into the same problem if we had <code class="language-plaintext highlighter-rouge">Nullable Null</code> or <code class="language-plaintext highlighter-rouge">ThingOrErrorMessage ErrorMessage</code>, but that would be a bad use of these type aliases. But one benefit is that we could reuse <code class="language-plaintext highlighter-rouge">Null</code> or <code class="language-plaintext highlighter-rouge">ErrorMessage</code> in other unions.</p>

<p>We can also still describe recursive datastructures fairly easily:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>class ListNode a {
    content : a;
    next : LinkedList a;
}

type LinkedList a = Null | ListNode a

class TreeNode a { 
    value : a;
    left : Tree a;
    right : Tree a;
}

type Tree a = contents : Null | a | TreeNode a;
</code></pre></div></div>

<p>I honestly don’t think this is too bad, so it’s what I’m going to stick with. Some might say that having both product types and classes in the same language is redundant. I don’t think so. To me, there is no obvious way to have private fields in ADTs, so that’s one point in favor of something like classes. Also if we want to reference specific fields in a product type, we would have to pattern match on it or destructure it, both of which can get clunky if the object has a lot of fields. And as a nice bonus, we don’t have to explicitly give a name to every single union that we use in our programs.</p>

<h2 id="feature-1-destructuring-assignment">Feature 1: Destructuring Assignment</h2>

<p>So that’s how I see the type system working, more or less. Now I’ll get into some of the features for working with ADTs.</p>

<p>One things that makes product types easier to work with is destructuring. This is probably something people are familiar with from modern JavaScript. In order to denote that an object should use destructuring in assignment (since we don’t want to make type inference really complicated), I’d want to introduce the <code class="language-plaintext highlighter-rouge">&lt;-</code> symbol:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>function returnTuple() : int &amp; string {
    return 11 &amp; "This is part of a product type with two fields";
}

let num2, str2 &lt;- returnTuple();
let tuple = returnTuple(); // Can also not destructure it, if we don't want to

</code></pre></div></div>

<p>We can also use a type alias:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>type Tuple = int &amp; string;

function returnTupleExplicit() : Tuple {
    return 11 &amp; "This is also part of a product type with two fields";
}

let num2, str2 &lt;- returnTupleExplicit();
</code></pre></div></div>

<p>That’s all well and good for product types, but for sum types, how would that work? Well, I would want it to give a compile error if we tried to do any of the above, so here’s my alternative.</p>

<h2 id="feature-2-destructuring-if">Feature 2: Destructuring <code class="language-plaintext highlighter-rouge">if</code></h2>

<p>I want to avoid having to implement flow-sensitive typing, since, from what I understand, that’s a feature that’s pretty difficult to implement properly. The major languages to implement flow-sensitive typing are usually created by very smart people at big corporations, and I am a not-very smart guy making a language in his spare time.</p>

<p>As such, I think it might be cool to allow destructing assignment of union types in <code class="language-plaintext highlighter-rouge">if</code> statements. I’m thinking that the first statement of an <code class="language-plaintext highlighter-rouge">if</code> could be an assignment, but if the value of the destructure doesn’t match, the <code class="language-plaintext highlighter-rouge">if</code> statement evaluates to false. This would be less complicated than forcing the user to do pattern matching every time they need to look inside of a union, but would still be safe. Here’s an example of what I mean:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>function defaultToZero(maybeInt : Nullable int) : int {
    if let i : int &lt;- maybeInt; i == 5 {
        println(i, " is 5, btw");
        return i;
    else if let i : int &lt;- maybeInt {
        println(i, " isn't 5, but it is an integer")
        return i;
    }
    return 0;
}
</code></pre></div></div>

<p>Or maybe we could rewrite it to take advantage of the basic type inference that <code class="language-plaintext highlighter-rouge">del</code> already has:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>function defaultToZero(maybeInt : Nullable int) : int {
    let i = 0;
    if i &lt;- maybeInt; i == 5 {
        println(i, " is 5, btw");
    else if i &lt;- maybeInt {
        println(i, " isn't 5, but it is an integer")
    }
    return i;
}
</code></pre></div></div>

<p>This syntax isn’t too far off from what <code class="language-plaintext highlighter-rouge">c</code>-like languages do in a numeric <code class="language-plaintext highlighter-rouge">for</code> loop, and is similar to <code class="language-plaintext highlighter-rouge">go</code>’s ability to add assignment as the first item of an <code class="language-plaintext highlighter-rouge">if</code> statement. Technically the semantics are a little different, since match failure is also sort of part of the conditional, but I think it will feel familiar to most programmers.</p>

<p>The main drawback that I can immediately see is that it could make early returns more difficult. In the example above, it might be nicer to check for null, and if the value is non-null, <em>in an ideal language</em> it would be safe to start treating <code class="language-plaintext highlighter-rouge">mabyeInt</code> as an <code class="language-plaintext highlighter-rouge">int</code> in subsequent code. But now you’re in the world of flow-sensitive typing, which I don’t want to be in, as an implementer (as I mentioned, I’m a dumb guy with limited time). I’m not sure if there’s a good solution to this, but I think destructuring <code class="language-plaintext highlighter-rouge">if</code> is an ergonomic-enough contruct for most cases.</p>

<h2 id="feature-3-pattern-matching">Feature 3: Pattern matching</h2>
<p>Pattern matching is great for when there are multiple cases or conditions related to the types. It’s basically like the destructuring <code class="language-plaintext highlighter-rouge">if</code> above, but easier to read when the type could contain many different values. Here’s an example of what I would want:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>type ManySuchCases = int | string | SomeCustomType | int &amp; SomeCustomType

function printManySuchCases(misc : ManySuchCases) {
    switch misc {
        case i : int; i == 5 {
            println("five, btw");
        }
        case i : int {
            println("not five, but a number");
        }
        case str : string {
            println("'", str, "'");
        }
        case sct : SomeCustomType {
            println("Some fancy type");
        }
        case i : int, sct : SomeCustomType {
            println("an int, but also some fancy type");
        }
    }
}
</code></pre></div></div>

<h2 id="feature-4-overloading-destructure">Feature 4: Overloading Destructure</h2>
<p>This is a funky one. I want to allow users to be able to overload different aspects of classes. Getters and setters are the obvious ones, as are arithmatic operators. But I think it would also be cool to allow overloading of destructuring. That way classes could be destructured or pattern matched on just like regular ADTs:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>class Slice a {
    array : Array a;
    startIndex : int;
    endIndex : int;
    destructure() : Null | a | a &amp; Slice a {
        let diff = endIndex - startIndex;
        if diff &lt;= 0 {
            return null;
        } else if diff == 1 {
            return array[startIndex];
        } else {
            return array[startIndex] &amp; new Slice(a, startIndex - 1, endIndex);
        }
    }
}

function recursiveSum(slice : Slice int) : int {
    switch slice {
        case _ : Null {
            return 0;
        }
        case val : int {
            return val;
        }
        case val : int, tail : Slice int {
            return val + sum(tail);
        }
    }
}

</code></pre></div></div>

<p>I’m not sure if any other language has something like this, but it seems cool to me! Hopefully I’m not missing some corner case about this feature being impossible to implement, because I really like it.</p>]]></content><author><name></name></author><category term="types" /><category term="programming" /><category term="languages" /><summary type="html"><![CDATA[I’ve been thinking about adding unions (or sum types) to the del programming language, the hobby language I’ve been working on for the last year and a half. I still have a dozen more pressing issues to implement, but I want to use this post to catalog some of my thoughts on adding sum types (or union types) to the language.]]></summary></entry><entry><title type="html">Stupidly Typed Programming Languages</title><link href="https://danieltuveson.github.io/programming/languages/stupid/satire/2024/12/10/stupidly-typed-languages.html" rel="alternate" type="text/html" title="Stupidly Typed Programming Languages" /><published>2024-12-10T00:00:00+00:00</published><updated>2024-12-10T00:00:00+00:00</updated><id>https://danieltuveson.github.io/programming/languages/stupid/satire/2024/12/10/stupidly-typed-languages</id><content type="html" xml:base="https://danieltuveson.github.io/programming/languages/stupid/satire/2024/12/10/stupidly-typed-languages.html"><![CDATA[<p>Earlier this week, I was browsing a programming forum and saw two fellows arguing about the definitions of “strong” and “weak” typing. One of the fellows argued that Python has a “strong” type system, because every object has a type, and that C has a “weak” type system because the programmer can circumvent the type system by casting. The other argued that this definition deviated from the original definition of “strong” typing in that a program with “strong” types will not run unless the program satisfies a set of constraints determined by a typechecker, and that by this definition, C would be “strongly typed” and Python would be “weakly typed”.</p>

<p>“Alas,” a third fellow chimed in, “‘strongly typed’ and ‘weakly typed’ are not rigorously defined academic terms,” and then linked to this <a href="https://en.wikipedia.org/wiki/Strong_and_weak_typing">wikipedia page</a>.</p>

<p>“Shut up nerd,” the original fellow responded. The second fellow concurred, “I agree with you, but I agree with OP that you are a nerd and should shut up.”</p>

<p>Definitions are hard. The task of defining a term, such that it is consistently used in an unambiguous manner is hard. Difficult. A struggle. Tough stuff. You get it.</p>

<p>As such, I propose a piece of new unambiguous terminology that can be used to denigrate programming languages that you dislike. The set of all programming languages can be split into two disjoint sets: “nerdly typed” and “stupidly typed” languages. Given the following example:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>function main() {
    x = 1
    print("Hello from a stupid programming language!")
    x.im_stupid()
}
</code></pre></div></div>

<p>A language implementation must be considered “stupidly typed” if its closest equivalent to the above pseudocode would print “Hello from a stupid programming language!” before printing out any other text. If a language satisfies this property, it is a stupid language, and if you use it you are probably an idiot. If it does not, then you are programming in a language for nerds, and you are probably a loser that doesn’t have any friends.</p>

<p>Now I know what you’re thinking. What if a language has a builtin <code class="language-plaintext highlighter-rouge">im_stupid()</code> method on integers? I’m sorry, but by the canonical definition, it is a stupidly typed programming language. And even worse, you’re a nerd for being so pedantic.</p>]]></content><author><name></name></author><category term="programming" /><category term="languages" /><category term="stupid" /><category term="satire" /><summary type="html"><![CDATA[Earlier this week, I was browsing a programming forum and saw two fellows arguing about the definitions of “strong” and “weak” typing. One of the fellows argued that Python has a “strong” type system, because every object has a type, and that C has a “weak” type system because the programmer can circumvent the type system by casting. The other argued that this definition deviated from the original definition of “strong” typing in that a program with “strong” types will not run unless the program satisfies a set of constraints determined by a typechecker, and that by this definition, C would be “strongly typed” and Python would be “weakly typed”.]]></summary></entry><entry><title type="html">A Simple Threaded Interpreter</title><link href="https://danieltuveson.github.io/interpreter/compiler/bytecode/thread/vm/2024/09/07/threaded-code.html" rel="alternate" type="text/html" title="A Simple Threaded Interpreter" /><published>2024-09-07T00:00:00+00:00</published><updated>2024-09-07T00:00:00+00:00</updated><id>https://danieltuveson.github.io/interpreter/compiler/bytecode/thread/vm/2024/09/07/threaded-code</id><content type="html" xml:base="https://danieltuveson.github.io/interpreter/compiler/bytecode/thread/vm/2024/09/07/threaded-code.html"><![CDATA[<h2 id="background">Background</h2>

<p>I’ve spent roughly a year building an interpreter for my own programming language called <a href="https://github.com/danieltuveson/del">del</a>. I’ve tried building interpreters a few times in the past, but I would always get hung up on building the parser, and so I didn’t spend much time learning about the ‘backend’ of interpreters. Going into building <code class="language-plaintext highlighter-rouge">del</code>, I knew this, so I hacked together a parser fairly quickly and started building out the bytecode compiler and a virtual machine. Recently I’ve been wondering how to improve the performance, and stumbled upon a fairly common optimization that most interpreters use called <a href="https://en.wikipedia.org/wiki/Threaded_code">threaded code</a>.</p>

<h2 id="a-quick-introduction-to-interpreters">A Quick Introduction to Interpreters</h2>

<p>Despite most people’s assumptions, interpreters actually often have compilation steps, even if they don’t compile to machine code. Most parse code into some intermediate tree-like representation called an abstract syntax tree (an AST), but then further transform that into what is called bytecode. Bytecode is like a fake, simplified assembly language that is then run by a virtual machine (VM). A VM is basically just a big loop over the bytecode. When it encounters an instruction, it executes a bit of code, moves on to the next instruction, and so on until the program terminates.</p>

<p>To give a brief illustration, the code <code class="language-plaintext highlighter-rouge">4 + 1 - 2</code> might be represented as an AST like <code class="language-plaintext highlighter-rouge">(SUBTRACT (ADD 4 1) 2)</code>, and that could get converted to bytecode like <code class="language-plaintext highlighter-rouge">PUSH 4; PUSH 1; ADD; PUSH 2; SUBTRACT;</code>.</p>

<p>You might be wondering: why go to the trouble of doing an extra compilation step when you could just walk through the instructions in the AST? Well, many interpreters are initially written that way, since it’s the most intuitive and easy way to write an interpreter. The downside to this is that it tends to be much slower for long running programs. Ruby, for instance, was originally written in this way, but was replaced with a VM implementation for performance reasons.</p>

<p>The hand-wavy explanation I can give for why the VM implementation is faster is basically that an AST is a bunch of different chunks of memory linked together by pointers, whereas bytecode is just a big array of memory. Looping through a big contiguous array tends to be faster than dereferencing a bunch of pointers and jumping to different places in memory that may or may not be near each other. Someone more knowledgeable about how processors work could probably give a better explanation, but that’s the gist of it.</p>

<p>Interpreting bytecode is an optimization, but it’s still much slower than native code. How can we get more performance out of a bytecode interpreter? Well… you could do just-in-time compilation (JIT compilation), where you take that bytecode and compile it into actual machine code at runtime. That’s what the main implementations of Java, C#, and JavaScript (V8/NodeJS) do, and many interpreted languages have alternative implementations that do this (PyPy is a JIT compiled version of Python, for example). However this opens up a whole can of worms: different CPUs have different architectures, and require writing different assembly. And each operating system has its own set of unique system calls. Having to do a bunch of machine and os-specific compilation steps defeats one of the main benefits of an interpreter, which is that your code gets to be cross platform with little extra effort (or at least as cross-platform as the language that it is running on top of).</p>

<p>So if we don’t have the time, the patience, or the knowledge of assembly to do JIT compiling, can we still get more performance out of our interpreter? Yes! Well yes, if you’re writing in C or C++. But not on Windows. But otherwise, yes!</p>

<h2 id="a-simple-example-vm">A Simple Example VM</h2>

<p>Before we get into writing the threaded VM, let’s look at a simple example of a VM using a loop and switch. The following describes a simple VM that operates on a stack data structure. The VM has 6 operations:</p>
<ul>
  <li>PUSH: Push a value onto the stack. Takes as an argument the value to push.</li>
  <li>ADD: Pop two values off of the stack and add them together.</li>
  <li>SUBTRACT: Pop two values off of the stack, and subtract the second value from the first.</li>
  <li>DUPLICATE: Make a copy of the value on the top of the stack and push it onto the stack.</li>
  <li>JUMP IF: Pop a value off of the stack. If it is greater than 0, jump to the given location. Takes as an argument the location in the bytecode where we want to jump to. Our bytecode is an array of integers, so the location is just the index of the element in the array that we want to jump to.</li>
  <li>RET: Terminate the program and return the value at the top of the stack.</li>
</ul>

<p>We’ll define that using an enum as follows:</p>

<figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="k">enum</span> <span class="n">Bytecode</span> <span class="p">{</span>
    <span class="n">PUSH</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span>
    <span class="n">ADD</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span>
    <span class="n">SUBTRACT</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span>
    <span class="n">DUPLICATE</span> <span class="o">=</span> <span class="mi">4</span><span class="p">,</span>
    <span class="n">JUMP_IF</span> <span class="o">=</span> <span class="mi">5</span><span class="p">,</span>
    <span class="n">RET</span> <span class="o">=</span> <span class="mi">6</span>
<span class="p">};</span></code></pre></figure>

<p>As I described above, most VMs will look like a loop over a big switch statement. Something like the following:</p>

<figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="c1">// Utility macros for manipulating the stack</span>
<span class="cp">#define pop() stack[--sp]
#define push(value) stack[sp++] = (value)
#define next() ip++
</span>
<span class="kt">int</span> <span class="nf">looped</span><span class="p">(</span><span class="k">const</span> <span class="kt">int</span> <span class="o">*</span><span class="n">bytecode</span><span class="p">)</span>
<span class="p">{</span>
    <span class="kt">int</span> <span class="n">stack</span><span class="p">[</span><span class="mi">10</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span> <span class="mi">0</span> <span class="p">};</span>
    <span class="kt">int</span> <span class="n">sp</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">ip</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">temp1</span><span class="p">,</span> <span class="n">temp2</span><span class="p">;</span>
    <span class="k">while</span> <span class="p">(</span><span class="nb">true</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">switch</span><span class="p">(</span><span class="n">bytecode</span><span class="p">[</span><span class="n">ip</span><span class="p">])</span> <span class="p">{</span>
            <span class="k">case</span> <span class="n">PUSH</span><span class="p">:</span>
                <span class="n">next</span><span class="p">();</span>
                <span class="n">push</span><span class="p">(</span><span class="n">bytecode</span><span class="p">[</span><span class="n">next</span><span class="p">()]);</span>
                <span class="k">break</span><span class="p">;</span>
            <span class="k">case</span> <span class="n">ADD</span><span class="p">:</span>
                <span class="n">next</span><span class="p">();</span>
                <span class="n">temp1</span> <span class="o">=</span> <span class="n">pop</span><span class="p">();</span>
                <span class="n">temp2</span> <span class="o">=</span> <span class="n">pop</span><span class="p">();</span>
                <span class="n">push</span><span class="p">(</span><span class="n">temp1</span> <span class="o">+</span> <span class="n">temp2</span><span class="p">);</span>
                <span class="k">break</span><span class="p">;</span>
            <span class="k">case</span> <span class="n">SUBTRACT</span><span class="p">:</span>
                <span class="n">next</span><span class="p">();</span>
                <span class="n">temp1</span> <span class="o">=</span> <span class="n">pop</span><span class="p">();</span>
                <span class="n">temp2</span> <span class="o">=</span> <span class="n">pop</span><span class="p">();</span>
                <span class="n">push</span><span class="p">(</span><span class="n">temp1</span> <span class="o">-</span> <span class="n">temp2</span><span class="p">);</span>
                <span class="k">break</span><span class="p">;</span>
            <span class="k">case</span> <span class="n">DUPLICATE</span><span class="p">:</span>
                <span class="n">next</span><span class="p">();</span>
                <span class="n">temp1</span> <span class="o">=</span> <span class="n">pop</span><span class="p">();</span>
                <span class="n">push</span><span class="p">(</span><span class="n">temp1</span><span class="p">);</span>
                <span class="n">push</span><span class="p">(</span><span class="n">temp1</span><span class="p">);</span>
                <span class="k">break</span><span class="p">;</span>
            <span class="k">case</span> <span class="n">JUMP_IF</span><span class="p">:</span>
                <span class="n">next</span><span class="p">();</span>
                <span class="k">if</span> <span class="p">(</span><span class="n">pop</span><span class="p">()</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
                    <span class="n">ip</span> <span class="o">=</span> <span class="n">bytecode</span><span class="p">[</span><span class="n">ip</span><span class="p">];</span>
                <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
                    <span class="n">next</span><span class="p">();</span>
                <span class="p">}</span>
                <span class="k">break</span><span class="p">;</span>
            <span class="k">case</span> <span class="n">RET</span><span class="p">:</span>
                <span class="k">goto</span> <span class="n">end</span><span class="p">;</span>
        <span class="p">}</span>
    <span class="p">}</span>
    <span class="nl">end:</span>
    <span class="k">return</span> <span class="n">stack</span><span class="p">[</span><span class="n">sp</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span>
<span class="p">}</span></code></pre></figure>

<p>This works pretty well, and is decently fast. If we look at the compiled output of the <a href="https://godbolt.org/z/vbPfcE6Mq">looped version</a>, we can see that each case jumps to the top of the loop (the .L2 label) and then has to check the current instruction against each possible instruction in the switch in order to determine where to jump to next.</p>

<p>Why not just jump straight to the next instruction? Because “<a href="https://homepages.cwi.nl/~storm/teaching/reader/Dijkstra68.pdf">goto considered harmful</a>”? In many cases unstructured jumping can lead to hard-to-understand code, but in this scenario, it’s exactly what we need. Most people would prefer their interpreter be faster even if that means the source code of the interpreter is a little harder to understand.</p>

<p>By default, standards-compliant C does not actually provide a way of using goto-labels as values, so we need a gcc-specific extension in order for this code to work (though clang also supports this extension). The relevant documentation for this feature can be found here: <a href="https://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html">labels as values</a>. As of writing this, the documentation for this feature explicitly mentions that this is useful for writing fast interpreters!</p>

<figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="cp">#define cont() goto *(targets[bytecode[ip]])
</span>
<span class="kt">int</span> <span class="nf">threaded</span><span class="p">(</span><span class="k">const</span> <span class="kt">int</span> <span class="o">*</span><span class="n">bytecode</span><span class="p">)</span>
<span class="p">{</span>
    <span class="c1">// Order of the items in this array must match the values of bytecode</span>
    <span class="kt">void</span> <span class="o">*</span><span class="n">targets</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span> <span class="nb">NULL</span><span class="p">,</span> <span class="o">&amp;&amp;</span><span class="n">PUSH</span><span class="p">,</span> <span class="o">&amp;&amp;</span><span class="n">ADD</span><span class="p">,</span> <span class="o">&amp;&amp;</span><span class="n">SUBTRACT</span><span class="p">,</span> <span class="o">&amp;&amp;</span><span class="n">DUPLICATE</span><span class="p">,</span> <span class="o">&amp;&amp;</span><span class="n">JUMP_IF</span><span class="p">,</span> <span class="o">&amp;&amp;</span><span class="n">RET</span> <span class="p">};</span>
    <span class="kt">int</span> <span class="n">stack</span><span class="p">[</span><span class="mi">10</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span> <span class="mi">0</span> <span class="p">};</span>
    <span class="kt">int</span> <span class="n">sp</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">ip</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">temp1</span><span class="p">,</span> <span class="n">temp2</span><span class="p">;</span>
    <span class="n">cont</span><span class="p">();</span>
    <span class="nl">PUSH:</span>
        <span class="n">next</span><span class="p">();</span>
        <span class="n">push</span><span class="p">(</span><span class="n">bytecode</span><span class="p">[</span><span class="n">next</span><span class="p">()]);</span>
        <span class="n">cont</span><span class="p">();</span>
    <span class="nl">ADD:</span>
        <span class="n">next</span><span class="p">();</span>
        <span class="n">temp1</span> <span class="o">=</span> <span class="n">pop</span><span class="p">();</span>
        <span class="n">temp2</span> <span class="o">=</span> <span class="n">pop</span><span class="p">();</span>
        <span class="n">push</span><span class="p">(</span><span class="n">temp1</span> <span class="o">+</span> <span class="n">temp2</span><span class="p">);</span>
        <span class="n">cont</span><span class="p">();</span>
    <span class="nl">SUBTRACT:</span>
        <span class="n">next</span><span class="p">();</span>
        <span class="n">temp1</span> <span class="o">=</span> <span class="n">pop</span><span class="p">();</span>
        <span class="n">temp2</span> <span class="o">=</span> <span class="n">pop</span><span class="p">();</span>
        <span class="n">push</span><span class="p">(</span><span class="n">temp1</span> <span class="o">-</span> <span class="n">temp2</span><span class="p">);</span>
        <span class="n">cont</span><span class="p">();</span>
    <span class="nl">DUPLICATE:</span>
        <span class="n">next</span><span class="p">();</span>
        <span class="n">temp1</span> <span class="o">=</span> <span class="n">pop</span><span class="p">();</span>
        <span class="n">push</span><span class="p">(</span><span class="n">temp1</span><span class="p">);</span>
        <span class="n">push</span><span class="p">(</span><span class="n">temp1</span><span class="p">);</span>
        <span class="n">cont</span><span class="p">();</span>
    <span class="nl">JUMP_IF:</span>
        <span class="n">next</span><span class="p">();</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">pop</span><span class="p">()</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">ip</span> <span class="o">=</span> <span class="n">bytecode</span><span class="p">[</span><span class="n">ip</span><span class="p">];</span>
        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
            <span class="n">next</span><span class="p">();</span>
        <span class="p">}</span>
        <span class="n">cont</span><span class="p">();</span>
    <span class="nl">RET:</span>
        <span class="k">goto</span> <span class="n">end</span><span class="p">;</span>
    <span class="nl">end:</span>
    <span class="k">return</span> <span class="n">stack</span><span class="p">[</span><span class="n">sp</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span>
<span class="p">}</span></code></pre></figure>

<p>In our new <a href="https://godbolt.org/z/faYcr5sT5">threaded version</a>, we can see that at the end of each case it simply loads the value in the array and jumps to it,  mirroring what we see in our C code.</p>

<p>With these little helper macros that we’ve added, this isn’t much more difficult to read than the loop version, and removes all of the extra comparisons done by the switch in the looped version. It doesn’t seem too significant, but it adds up, especially if we’re iterating through these instructions billions of times. In the profiling I did on my machine using perf, it runs 20%-30% faster using clang or gcc when optimizations are enabled. Interestingly, it runs about as fast in both clang and gcc when no optimizations are enabled (-O0).</p>

<p>If you want to run this and time it yourself, the code can be found <a href="https://github.com/danieltuveson/bytecode">here</a>. It includes some example bytecode that iterates from <code class="language-plaintext highlighter-rouge">1</code> to <code class="language-plaintext highlighter-rouge">INT_MAX</code>. If you want to hack on it, or just get a better sense of what it’s doing, I’d suggest enabling logging and changing <code class="language-plaintext highlighter-rouge">INT_MAX</code> to a small integer.</p>

<p>Check out the Lua interpreter if you want a real-world example of a threaded interpreter. It actually doesn’t look too different than what we have above. The main difference is that their VM uses a couple of helper macros to allow them to seamlessly integrate this feature while also allowing the compiler to toggle this optimization on and off, that way their code can enable this feature only for C compilers that support it. Checkout <code class="language-plaintext highlighter-rouge">luaV_execute</code> in <a href="https://github.com/lua/lua/blob/master/lvm.c">lvm.c</a> for their VM code, which uses the <a href="https://github.com/lua/lua/blob/master/ljumptab.h">ljumptab.h</a> macros to enable threaded code.</p>

<h2 id="addendum">Addendum</h2>
<p>I recently did some benchmarking of the Lua interpreter (and my own interpreter for <code class="language-plaintext highlighter-rouge">del</code>) comparing threaded code vs loop-and-switch, and I found that the threaded code often performed about the same or <em>worse</em> than the loop-and-switch. This was mainly based around 2 small benchmarks, so it’s possible that for a wider sampling of benchmark programs (or on a different machine, perhaps) that threading would perform better, but thought it would be worth mentioning this. Threading is enabled by default in Lua on compilers that support it, so <em>presumably</em> they benchmarked it and found that it was faster in general, but who knows. If you’re going to make a performance optimization, always benchmark it!</p>]]></content><author><name></name></author><category term="interpreter" /><category term="compiler" /><category term="bytecode" /><category term="thread" /><category term="vm" /><summary type="html"><![CDATA[Background]]></summary></entry><entry><title type="html">Hello</title><link href="https://danieltuveson.github.io/salutations/2024/07/25/hello.html" rel="alternate" type="text/html" title="Hello" /><published>2024-07-25T00:00:00+00:00</published><updated>2024-07-25T00:00:00+00:00</updated><id>https://danieltuveson.github.io/salutations/2024/07/25/hello</id><content type="html" xml:base="https://danieltuveson.github.io/salutations/2024/07/25/hello.html"><![CDATA[<p>This post is a test to make sure things are working properly. Hello.</p>]]></content><author><name></name></author><category term="salutations" /><summary type="html"><![CDATA[This post is a test to make sure things are working properly. Hello.]]></summary></entry></feed>