<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/default.xsl"?>
<fr:tree xmlns:fr="http://www.forester-notes.org" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:xml="http://www.w3.org/XML/1998/namespace" root="false" base-url="/">
  <fr:frontmatter>
    <fr:authors>
      <fr:author>
        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
      </fr:author>
    </fr:authors>
    <fr:date>
      <fr:year>2025</fr:year>
      <fr:month>5</fr:month>
      <fr:day>19</fr:day>
    </fr:date>
    <fr:uri>https://patrick.sirref.org/pouzin-shell/</fr:uri>
    <fr:display-uri>pouzin-shell</fr:display-uri>
    <fr:route>/pouzin-shell/</fr:route>
    <fr:title text="Metashells › Louis Pouzin's &quot;SHELL&quot; "><fr:link href="/weekly-2025-05-12/" title="Metashells" uri="https://patrick.sirref.org/weekly-2025-05-12/" display-uri="weekly-2025-05-12" type="local">Metashells</fr:link> › Louis Pouzin's "SHELL" </fr:title>
  </fr:frontmatter>
  <fr:mainmatter>
    <html:p>I spent some time reading <fr:link href="/pouzin-shell-2013/" title="The Origin of the Shell" uri="https://patrick.sirref.org/pouzin-shell-2013/" display-uri="pouzin-shell-2013" type="local">part of the multics design documentation</fr:link> this week. Louis Pouzin coined the term "SHELL" in this document, and I was reminded yet again just how important it is to be a good writer even as a "computer science researcher". For example, this excerpt from the requirements section of the document</html:p>
    <html:blockquote>
      <html:p>The previous definitions imply that a command MUST be designed while keeping in mind the user, sitting at his console, wondering about what might be going on, mistyping or forgetting arguments, even if fully aware of the conventions, and possibly interfering with the command by hasty quits, carriage returns, and other temperamental reactions.</html:p>
    </html:blockquote>
    <html:p>And then later, when defining the "SHELL".</html:p>
    <html:blockquote>
      <html:p>We may envision a common procedure called automatically by the supervisor whenever a user types in some message at his console, at a time when he has no other process in active execution under console control (presently called command level). This procedure acts as an interface between console messages and subroutine. The purpose of such a procedure is to create a medium of exchange into which one could activate any procedure, <html:em>inside of another program if it were called</html:em>. Hereafter, for simplification, we shall refer to that procedure as the "SHELL".</html:p>
    </html:blockquote>
    <html:p>It still surprises how little the undergraduate degree in computer science at <fr:link href="/ucam/" title="University of Cambridge" uri="https://patrick.sirref.org/ucam/" display-uri="ucam" type="local">Cambridge</fr:link> focuses on writing skills.</html:p>
  </fr:mainmatter>
  <fr:backmatter>
    <fr:tree show-metadata="false" hidden-when-empty="true">
      <fr:frontmatter>
        <fr:authors />
        <fr:title text="References">References</fr:title>
      </fr:frontmatter>
      <fr:mainmatter>
        <fr:tree show-metadata="true" expanded="false" toc="false" numbered="false">
          <fr:frontmatter>
            <fr:authors>
              <fr:author>
                <fr:link href="https://patrick.sirref.org/Louis Pouzin/" type="external">Louis Pouzin</fr:link>
              </fr:author>
            </fr:authors>
            <fr:date>
              <fr:year>2013</fr:year>
            </fr:date>
            <fr:uri>https://patrick.sirref.org/pouzin-shell-2013/</fr:uri>
            <fr:display-uri>pouzin-shell-2013</fr:display-uri>
            <fr:route>/pouzin-shell-2013/</fr:route>
            <fr:title text="The Origin of the Shell">The Origin of the Shell</fr:title>
            <fr:taxon>Reference</fr:taxon>
            <fr:meta name="external">https://people.csail.mit.edu/saltzer/Multics/Multics-Documents/MDN/MDN-4.pdf</fr:meta>
            <fr:meta name="journal">Multics Documents</fr:meta>
            <fr:meta name="doi" />
          </fr:frontmatter>
          <fr:mainmatter>
            <fr:tree show-metadata="false">
              <fr:frontmatter>
                <fr:authors>
                  <fr:author>
                    <fr:link href="https://patrick.sirref.org/Louis Pouzin/" type="external">Louis Pouzin</fr:link>
                  </fr:author>
                </fr:authors>
                <fr:date>
                  <fr:year>2013</fr:year>
                </fr:date>
                <fr:title text="Abstract">Abstract</fr:title>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p>How RUNCOM was created for CTSS and the shell was designed for Multics by Louis Pouzin.</html:p>
              </fr:mainmatter>
            </fr:tree>
          </fr:mainmatter>
        </fr:tree>
      </fr:mainmatter>
    </fr:tree>
    <fr:tree show-metadata="false" hidden-when-empty="true">
      <fr:frontmatter>
        <fr:authors />
        <fr:title text="Context">Context</fr:title>
      </fr:frontmatter>
      <fr:mainmatter>
        <fr:tree show-metadata="true" expanded="false" toc="false" numbered="false">
          <fr:frontmatter>
            <fr:authors>
              <fr:author>
                <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
              </fr:author>
            </fr:authors>
            <fr:date>
              <fr:year>2026</fr:year>
              <fr:month>3</fr:month>
              <fr:day>19</fr:day>
            </fr:date>
            <fr:uri>https://patrick.sirref.org/weekly-2026-w12/</fr:uri>
            <fr:display-uri>weekly-2026-w12</fr:display-uri>
            <fr:route>/weekly-2026-w12/</fr:route>
            <fr:title text="A POSIX Shell in OCaml">A POSIX Shell in OCaml</fr:title>
          </fr:frontmatter>
          <fr:mainmatter>
            <html:p>Long time, no weekly. Since the start of this year I have been building a POSIX shell in OCaml called <html:code>msh</html:code> (with the underlying library called <html:code>Merry</html:code>). <fr:link href="/merry/" title="Merry" uri="https://patrick.sirref.org/merry/" display-uri="merry" type="local">Merry</fr:link> is available online now.</html:p>
            <fr:tree show-metadata="false" numbered="false">
              <fr:frontmatter>
                <fr:authors>
                  <fr:author>
                    <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                  </fr:author>
                </fr:authors>
                <fr:date>
                  <fr:year>2026</fr:year>
                  <fr:month>3</fr:month>
                  <fr:day>19</fr:day>
                </fr:date>
                <fr:title text="A POSIX(ish) shell in OCaml">A POSIX(ish) shell in OCaml</fr:title>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p><fr:link href="/merry/" title="Merry" uri="https://patrick.sirref.org/merry/" display-uri="merry" type="local">Merry</fr:link> is a POSIX(ish) in OCaml. It uses  <fr:link href="/eio/" title="Eio" uri="https://patrick.sirref.org/eio/" display-uri="eio" type="local">Eio</fr:link> alongside <fr:link href="github.com/colis-anr/morbig" type="external">Morbig</fr:link> (a static parser for POSIX shell).</html:p>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:date>
                      <fr:year>2026</fr:year>
                      <fr:month>3</fr:month>
                      <fr:day>19</fr:day>
                    </fr:date>
                    <fr:title text="Why another (POSIX) shell?">Why another (POSIX) shell?</fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>Shells have been around for a long time. In my research on the notion of <html:em>metashell</html:em> I wrote about Louis Pouzin originally coining the term:</html:p>
                    <fr:tree show-metadata="false" numbered="false">
                      <fr:frontmatter>
                        <fr:authors>
                          <fr:author>
                            <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                          </fr:author>
                        </fr:authors>
                        <fr:date>
                          <fr:year>2025</fr:year>
                          <fr:month>5</fr:month>
                          <fr:day>19</fr:day>
                        </fr:date>
                        <fr:uri>https://patrick.sirref.org/pouzin-shell/</fr:uri>
                        <fr:display-uri>pouzin-shell</fr:display-uri>
                        <fr:route>/pouzin-shell/</fr:route>
                        <fr:title text="Metashells › Louis Pouzin's &quot;SHELL&quot; "><fr:link href="/weekly-2025-05-12/" title="Metashells" uri="https://patrick.sirref.org/weekly-2025-05-12/" display-uri="weekly-2025-05-12" type="local">Metashells</fr:link> › Louis Pouzin's "SHELL" </fr:title>
                      </fr:frontmatter>
                      <fr:mainmatter>
                        <html:p>I spent some time reading <fr:link href="/pouzin-shell-2013/" title="The Origin of the Shell" uri="https://patrick.sirref.org/pouzin-shell-2013/" display-uri="pouzin-shell-2013" type="local">part of the multics design documentation</fr:link> this week. Louis Pouzin coined the term "SHELL" in this document, and I was reminded yet again just how important it is to be a good writer even as a "computer science researcher". For example, this excerpt from the requirements section of the document</html:p>
                        <html:blockquote>
                          <html:p>The previous definitions imply that a command MUST be designed while keeping in mind the user, sitting at his console, wondering about what might be going on, mistyping or forgetting arguments, even if fully aware of the conventions, and possibly interfering with the command by hasty quits, carriage returns, and other temperamental reactions.</html:p>
                        </html:blockquote>
                        <html:p>And then later, when defining the "SHELL".</html:p>
                        <html:blockquote>
                          <html:p>We may envision a common procedure called automatically by the supervisor whenever a user types in some message at his console, at a time when he has no other process in active execution under console control (presently called command level). This procedure acts as an interface between console messages and subroutine. The purpose of such a procedure is to create a medium of exchange into which one could activate any procedure, <html:em>inside of another program if it were called</html:em>. Hereafter, for simplification, we shall refer to that procedure as the "SHELL".</html:p>
                        </html:blockquote>
                        <html:p>It still surprises how little the undergraduate degree in computer science at <fr:link href="/ucam/" title="University of Cambridge" uri="https://patrick.sirref.org/ucam/" display-uri="ucam" type="local">Cambridge</fr:link> focuses on writing skills.</html:p>
                      </fr:mainmatter>
                    </fr:tree>
                    <html:p>I built <fr:link href="/shelter/" title="Shelter" uri="https://patrick.sirref.org/shelter/" display-uri="shelter" type="local">Shelter</fr:link> exploring the idea of a shell-like interface that allowed users to <html:em>undo</html:em> their shell actions (amongst other cool tricks). Unfortunately <html:em>shell-like</html:em> is not enough. <fr:link href="/shelter/" title="Shelter" uri="https://patrick.sirref.org/shelter/" display-uri="shelter" type="local">Shelter</fr:link> cut many corners to masquerade as a shell (e.g. appending <html:code>env</html:code> to understand how a command may have altered the execution environment). I felt it was necessary to make <fr:link href="/shelter/" title="Shelter" uri="https://patrick.sirref.org/shelter/" display-uri="shelter" type="local">Shelter</fr:link> a "SHELL"! To do that, I needed a solid foundation to build on.</html:p>
                    <html:p><html:code>msh</html:code>, the POSIX shell that comes with <fr:link href="/merry/" title="Merry" uri="https://patrick.sirref.org/merry/" display-uri="merry" type="local">Merry</fr:link>, is by no means POSIX-complete in terms of features. But it is my <fr:link href="https://github.com/patricoferris/nixos/blob/e0faf870f76710d4a75ace775f333c88f1321c5a/modules/default.nix#L59" type="external">daily driver at this point</fr:link>. It includes a pure OCaml rewrite of <fr:link href="github.com/antirez/linenoise" type="external">linenoise</fr:link> (a small, self-contained alternative to the venerable <html:code>readline</html:code>) called <fr:link href="https://tangled.org/patrick.sirref.org/bruit" type="external">bruit</fr:link>.</html:p>
                    <html:p>If you have <html:code>docker</html:code> installed on your machine, you can take it for a spin today:</html:p>
                    <html:pre><![CDATA[docker run -it --rm patrickferris/msh]]></html:pre>
                    <html:p>The <html:code>patrickferris/msh</html:code> docker image is just for trying it out. It is based on the OCaml 5.3 alpine image.</html:p>
                    <html:p>Alternatively, you can build <html:code>msh</html:code> from source and have it available in your opam switch.</html:p>
                    <html:pre><![CDATA[opam pin git+https://tangled.org/patrick.sirref.org/merry]]></html:pre>
                    <html:p>There are many small paper cuts left to patch over, but most of it is porcelain (e.g. <html:code>ctrl+left-arrow</html:code> for moving in <fr:link href="https://tangled.org/patrick.sirref.org/bruit" type="external">bruit</fr:link>). Unfortunately, these are the kinds of things that you will <html:em>immediately</html:em> stumble upon.</html:p>
                  </fr:mainmatter>
                </fr:tree>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:date>
                      <fr:year>2026</fr:year>
                      <fr:month>3</fr:month>
                      <fr:day>19</fr:day>
                    </fr:date>
                    <fr:title text="What makes Merry different?">What makes Merry different?</fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>Nothing.</html:p>
                    <html:p><fr:link href="/merry/" title="Merry" uri="https://patrick.sirref.org/merry/" display-uri="merry" type="local">Merry</fr:link> is supposed to be a solid, POSIX-ish base to build on. Unfortunaltely, as it turns out, the subset of features from the POSIX specification that people <html:em>actually use</html:em>... is pretty much all of it. Every possible redirection, variable expansion, shell built-in and compound command make some appearance. Not to mention the non-POSIX bits of shell we all take for granted (e.g. <html:code>&amp;&gt;</html:code>-redirection).</html:p>
                    <html:p><fr:link href="/merry/" title="Merry" uri="https://patrick.sirref.org/merry/" display-uri="merry" type="local">Merry</fr:link> and <html:code>msh</html:code> are useable. You will most likely find bugs if you use them. If, when using <html:code>msh</html:code>, you find something obscure happening you can enable debug mode either my setting the variable <html:code>MSH_DEBUG</html:code> or by invoking <html:code>msh</html:code> with <html:code>-v -v</html:code>.</html:p>
                  </fr:mainmatter>
                </fr:tree>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:date>
                      <fr:year>2026</fr:year>
                      <fr:month>3</fr:month>
                      <fr:day>19</fr:day>
                    </fr:date>
                    <fr:title text="What's next?">What's next?</fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>It is soon time to combine <fr:link href="/shelter/" title="Shelter" uri="https://patrick.sirref.org/shelter/" display-uri="shelter" type="local">Shelter</fr:link> and <fr:link href="/merry/" title="Merry" uri="https://patrick.sirref.org/merry/" display-uri="merry" type="local">Merry</fr:link> into the time-travelling, POSIX-ish shell that I have been trying to build since I first started working on <fr:link href="/shelter/" title="Shelter" uri="https://patrick.sirref.org/shelter/" display-uri="shelter" type="local">Shelter</fr:link>.</html:p>
                    <html:p>For this to be successful, I need <fr:link href="/merry/" title="Merry" uri="https://patrick.sirref.org/merry/" display-uri="merry" type="local">Merry</fr:link> to be able to pass plenty of tests and right now that involves trying to install plenty of packages using tools like <html:code>apk</html:code> and <html:code>apt</html:code>.</html:p>
                    <fr:tree show-metadata="false" numbered="false">
                      <fr:frontmatter>
                        <fr:authors>
                          <fr:author>
                            <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                          </fr:author>
                        </fr:authors>
                        <fr:date>
                          <fr:year>2026</fr:year>
                          <fr:month>3</fr:month>
                          <fr:day>19</fr:day>
                        </fr:date>
                        <fr:title text="Shell MRDT">Shell MRDT</fr:title>
                      </fr:frontmatter>
                      <fr:mainmatter>
                        <html:p>What I am particularly interested in reasoning about, is the <fr:link href="https://tangled.org/patrick.sirref.org/merry/blob/main/src/lib/eval.ml#L22" type="external">execution context</fr:link> in <fr:link href="/merry/" title="Merry" uri="https://patrick.sirref.org/merry/" display-uri="merry" type="local">Merry</fr:link>. This value, alongside the file-system, constitutes a fairly deep understanding of the state that changes in each step of a shell's evaluation loop.</html:p>
                        <html:p>This was, in terms of <fr:link href="/shelter/" title="Shelter" uri="https://patrick.sirref.org/shelter/" display-uri="shelter" type="local">Shelter</fr:link>, the missing piece for truly building some kind of <fr:link href="/mrdts/" title="Mergeable Replicated Data Type Implementation" uri="https://patrick.sirref.org/mrdts/" display-uri="mrdts" type="local">MRDT</fr:link> across shell sessions.</html:p>
                      </fr:mainmatter>
                    </fr:tree>
                  </fr:mainmatter>
                </fr:tree>
              </fr:mainmatter>
            </fr:tree>
            <fr:tree show-metadata="false" numbered="false">
              <fr:frontmatter>
                <fr:authors>
                  <fr:author>
                    <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                  </fr:author>
                </fr:authors>
                <fr:date>
                  <fr:year>2026</fr:year>
                  <fr:month>3</fr:month>
                  <fr:day>19</fr:day>
                </fr:date>
                <fr:title text="TIFF in OCaml">TIFF in OCaml</fr:title>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p>I picked up from the excellent <fr:link href="/outreachy/" title="Outreachy" uri="https://patrick.sirref.org/outreachy/" display-uri="outreachy" type="local">Outreachy</fr:link> work of <fr:link href="https://patrick.sirref.org/tambe salome/" type="external">Tambe Salome</fr:link> in getting write-support in <fr:link href="/ocaml-tiff/" title="ocaml-tiff" uri="https://patrick.sirref.org/ocaml-tiff/" display-uri="ocaml-tiff" type="local">ocaml-tiff</fr:link>. We are getting closer to the kind of API I envisaged in this latest round of refinement and review.</html:p>
                <html:pre class="hilite">
                  <html:code>
                    <html:span class="ocaml-keyword-other">let</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">/</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">=</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Eio</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Path</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">/</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-keyword">let</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-entity-name-function-binding">checkerboard</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">~</html:span>
                    <html:span class="ocaml-source">size</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">=</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">  </html:span>
                    <html:span class="ocaml-keyword">let</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-entity-name-function-binding">v</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">=</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Nx</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source">zeros</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Nx</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source">uint8</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source"><![CDATA[[|]]></html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">size</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">size</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source"><![CDATA[|]]]></html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-other">in</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">  </html:span>
                    <html:span class="ocaml-keyword">for</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-entity-name-function-binding">row</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">=</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-numeric-decimal-integer">0</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-other">to</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">size</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">-</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-numeric-decimal-integer">1</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-other">do</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">    </html:span>
                    <html:span class="ocaml-keyword">for</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-entity-name-function-binding">col</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">=</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-numeric-decimal-integer">0</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-other">to</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">size</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">-</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-numeric-decimal-integer">1</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-other">do</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">      </html:span>
                    <html:span class="ocaml-keyword-other">if</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                    <html:span class="ocaml-source">row</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">+</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">col</html:span>
                    <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">mod</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-numeric-decimal-integer">2</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">=</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-numeric-decimal-integer">0</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-other">then</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Nx</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source">set_item</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source"><![CDATA[[]]></html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">row</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">col</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source"><![CDATA[]]]></html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-numeric-decimal-integer">254</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">v</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">    </html:span>
                    <html:span class="ocaml-keyword-other">done</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">  </html:span>
                    <html:span class="ocaml-keyword-other">done</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-separator-terminator punctuation-separator">;</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">  </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Nx</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source">to_bigarray</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">v</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-keyword-other">let</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-language-unit"><![CDATA[()]]></html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">=</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">  </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Eio_posix</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source">run</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">@@</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-other">fun</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">env</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">  </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Tiff_eio</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source">with_open_out</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                    <html:span class="ocaml-source">env</html:span>
                    <html:span class="ocaml-keyword-other">#</html:span>
                    <html:span class="ocaml-source">cwd</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">/</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-string-quoted-double">"</html:span>
                    <html:span class="ocaml-string-quoted-double">example.tiff</html:span>
                    <html:span class="ocaml-string-quoted-double">"</html:span>
                    <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">@@</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-other">fun</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">w</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">-&gt;</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">  </html:span>
                    <html:span class="ocaml-keyword">let</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-entity-name-function-binding">tif</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-operator">=</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Tiff</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source">make</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source"><![CDATA[(]]></html:span>
                    <html:span class="ocaml-source">checkerboard</html:span>
                    <html:span class="ocaml-source"> ~</html:span>
                    <html:span class="ocaml-source">size</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-colon punctuation">:</html:span>
                    <html:span class="ocaml-constant-numeric-decimal-integer">256</html:span>
                    <html:span class="ocaml-source"><![CDATA[)]]></html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-keyword-other">in</html:span>
                    <html:span class="ocaml-source">
</html:span>
                    <html:span class="ocaml-source">  </html:span>
                    <html:span class="ocaml-constant-language-capital-identifier">Tiff</html:span>
                    <html:span class="ocaml-keyword-other-ocaml punctuation-other-period punctuation-separator">.</html:span>
                    <html:span class="ocaml-source">to_file</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">tif</html:span>
                    <html:span class="ocaml-source"> </html:span>
                    <html:span class="ocaml-source">w</html:span>
                    <html:span class="ocaml-source">
</html:span>
                  </html:code>
                </html:pre>
                <html:img src="/bafkrmiaqqczj5lemda5ijfjtjsyldbhmveu3btfvoa7rpt5k4dvdejjuhu.png" />
                <html:p>I have also been extremely pleased to see further external collaborators appearing:</html:p>
                <html:ul>
                  <html:li>
                    <html:p><fr:link href="https://github.com/geocaml/ocaml-tiff/pull/63" type="external">Nicolas</fr:link> helping out with metadata maintainence.</html:p>
                  </html:li>
                  <html:li>
                    <html:p><fr:link href="https://github.com/geocaml/ocaml-tiff/pull/62" type="external">Virgile</fr:link> adding support for reading multi-image TIFF files.</html:p>
                  </html:li>
                </html:ul>
              </fr:mainmatter>
            </fr:tree>
          </fr:mainmatter>
        </fr:tree>
        <fr:tree show-metadata="true" expanded="false" toc="false" numbered="false">
          <fr:frontmatter>
            <fr:authors>
              <fr:author>
                <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
              </fr:author>
            </fr:authors>
            <fr:date>
              <fr:year>2025</fr:year>
              <fr:month>5</fr:month>
              <fr:day>19</fr:day>
            </fr:date>
            <fr:uri>https://patrick.sirref.org/weekly-2025-05-12/</fr:uri>
            <fr:display-uri>weekly-2025-05-12</fr:display-uri>
            <fr:route>/weekly-2025-05-12/</fr:route>
            <fr:title text="Metashells">Metashells</fr:title>
          </fr:frontmatter>
          <fr:mainmatter>
            <html:p>This week, I feel I have been stuck fighting the OCaml ecosystem trying to keep my <fr:link href="/try-oxcaml/" title="Try OxCaml" uri="https://patrick.sirref.org/try-oxcaml/" display-uri="try-oxcaml" type="local">OxCaml work afloat</fr:link>. Aside from that, <fr:link href="/ryangibb/" title="Ryan Gibb" uri="https://patrick.sirref.org/ryangibb/" display-uri="ryangibb" type="local">Ryan</fr:link> and I made some really nice progress with Shelter, culminating in <fr:link href="/ryangibb/" title="Ryan Gibb" uri="https://patrick.sirref.org/ryangibb/" display-uri="ryangibb" type="local">Ryan</fr:link> describing it as a <html:em>metashell</html:em>.</html:p>
            <fr:tree show-metadata="false" numbered="false">
              <fr:frontmatter>
                <fr:authors>
                  <fr:author>
                    <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                  </fr:author>
                </fr:authors>
                <fr:date>
                  <fr:year>2025</fr:year>
                  <fr:month>5</fr:month>
                  <fr:day>19</fr:day>
                </fr:date>
                <fr:title text="Shelter the metashell">Shelter the metashell</fr:title>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p>The main progress this week with Shelter was composing <fr:link href="https://github.com/opencontainers/runc" type="external">runc</fr:link>'s <html:code>terminal</html:code> mode with entering raw terminal input mode on the Shelter side. This is inspired by <fr:link href="/ryangibb/" title="Ryan Gibb" uri="https://patrick.sirref.org/ryangibb/" display-uri="ryangibb" type="local">Ryan</fr:link>'s own work on <fr:link href="https://github.com/ryangibb/eon" type="external">capability interfaces</fr:link>.</html:p>
                <html:p>Shelter remains mostly intact, acting as an interactive shell. However, just before executing a command we switch to receiving and sending raw terminal inputs and outputs. This means tools like <html:code>vim</html:code> now work in Shelter! Not only that, but users can now <html:em>activate</html:em> an inner shell (e.g. <html:code>zsh</html:code>) and enjoy all the usual features of a fully-fledged shell (tab complete, fuzzy history search etc.) and upon exiting that shell, Shelter will snapshot the session. This lets you alter the granularity of snapshots from the command-line.</html:p>
              </fr:mainmatter>
            </fr:tree>
            <fr:tree show-metadata="false" numbered="false">
              <fr:frontmatter>
                <fr:authors>
                  <fr:author>
                    <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                  </fr:author>
                </fr:authors>
                <fr:date>
                  <fr:year>2025</fr:year>
                  <fr:month>5</fr:month>
                  <fr:day>19</fr:day>
                </fr:date>
                <fr:uri>https://patrick.sirref.org/pouzin-shell/</fr:uri>
                <fr:display-uri>pouzin-shell</fr:display-uri>
                <fr:route>/pouzin-shell/</fr:route>
                <fr:title text="Louis Pouzin's &quot;SHELL&quot; ">Louis Pouzin's "SHELL" </fr:title>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p>I spent some time reading <fr:link href="/pouzin-shell-2013/" title="The Origin of the Shell" uri="https://patrick.sirref.org/pouzin-shell-2013/" display-uri="pouzin-shell-2013" type="local">part of the multics design documentation</fr:link> this week. Louis Pouzin coined the term "SHELL" in this document, and I was reminded yet again just how important it is to be a good writer even as a "computer science researcher". For example, this excerpt from the requirements section of the document</html:p>
                <html:blockquote>
                  <html:p>The previous definitions imply that a command MUST be designed while keeping in mind the user, sitting at his console, wondering about what might be going on, mistyping or forgetting arguments, even if fully aware of the conventions, and possibly interfering with the command by hasty quits, carriage returns, and other temperamental reactions.</html:p>
                </html:blockquote>
                <html:p>And then later, when defining the "SHELL".</html:p>
                <html:blockquote>
                  <html:p>We may envision a common procedure called automatically by the supervisor whenever a user types in some message at his console, at a time when he has no other process in active execution under console control (presently called command level). This procedure acts as an interface between console messages and subroutine. The purpose of such a procedure is to create a medium of exchange into which one could activate any procedure, <html:em>inside of another program if it were called</html:em>. Hereafter, for simplification, we shall refer to that procedure as the "SHELL".</html:p>
                </html:blockquote>
                <html:p>It still surprises how little the undergraduate degree in computer science at <fr:link href="/ucam/" title="University of Cambridge" uri="https://patrick.sirref.org/ucam/" display-uri="ucam" type="local">Cambridge</fr:link> focuses on writing skills.</html:p>
              </fr:mainmatter>
            </fr:tree>
            <fr:tree show-metadata="false" numbered="false">
              <fr:frontmatter>
                <fr:authors>
                  <fr:author>
                    <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                  </fr:author>
                </fr:authors>
                <fr:date>
                  <fr:year>2025</fr:year>
                  <fr:month>5</fr:month>
                  <fr:day>19</fr:day>
                </fr:date>
                <fr:title text="OxCaml">OxCaml</fr:title>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p>Last week, I got a <fr:link href="/try-oxcaml/" title="Try OxCaml" uri="https://patrick.sirref.org/try-oxcaml/" display-uri="try-oxcaml" type="local">toplevel with OxCaml working</fr:link>. This required a serious amount of work to understand the changes Janestreet have made to obscure parts of the OCaml compiler and then working those into tools like <html:code>js_of_ocaml</html:code>.</html:p>
                <html:p>This week, Janestreet pushed their latest rounds of changes and of course everything broke! I spent some more time fixing it all back up. I'm not entirely sure how maintainable this is. The problem is that, whilst things compile, the programs do not work together! Only when someone uses the program do the bugs surface.</html:p>
              </fr:mainmatter>
            </fr:tree>
            <fr:tree show-metadata="false" numbered="false">
              <fr:frontmatter>
                <fr:authors>
                  <fr:author>
                    <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                  </fr:author>
                </fr:authors>
                <fr:date>
                  <fr:year>2025</fr:year>
                  <fr:month>5</fr:month>
                  <fr:day>19</fr:day>
                </fr:date>
                <fr:title text="Other OCaml Work">Other OCaml Work</fr:title>
              </fr:frontmatter>
              <fr:mainmatter>
                <html:p>I worked on some other parts of the ecosystem this week.</html:p>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>5</fr:month>
                      <fr:day>19</fr:day>
                    </fr:date>
                    <fr:title text="Ppxlib">Ppxlib</fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>I helped review some changes to enable Janestreet to have ppx rewriters via attributes (usually they are via extension points). It is a bit of a controversial change to <fr:link href="/ppxlib/" title="Ppxlib" uri="https://patrick.sirref.org/ppxlib/" display-uri="ppxlib" type="local">ppxlib</fr:link> as we try to keep the API predictable for users:</html:p>
                    <html:ol>
                      <html:li>
                        <html:p>Extension points are rewritten: this means the part that is rewritten is nicely delimited by the extension points start and end.</html:p>
                      </html:li>
                      <html:li>
                        <html:p>Attributes extend: attributes do not rewrite the code they are attached to but rather extend the code with new AST nodes.</html:p>
                      </html:li>
                    </html:ol>
                    <html:p><fr:link href="https://github.com/ocaml-ppx/ppxlib/pull/574" type="external">We will see what we decided to do (most likely provide the functionality behind some kind of "expert" interface)</fr:link>.</html:p>
                  </fr:mainmatter>
                </fr:tree>
                <fr:tree show-metadata="false" numbered="false">
                  <fr:frontmatter>
                    <fr:authors>
                      <fr:author>
                        <fr:link href="https://patrick.sirref.org/Patrick Ferris/" type="external">Patrick Ferris</fr:link>
                      </fr:author>
                    </fr:authors>
                    <fr:date>
                      <fr:year>2025</fr:year>
                      <fr:month>5</fr:month>
                      <fr:day>19</fr:day>
                    </fr:date>
                    <fr:title text="Tiff">Tiff</fr:title>
                  </fr:frontmatter>
                  <fr:mainmatter>
                    <html:p>See <fr:link href="/mdales/" title="Michael W. Dales" uri="https://patrick.sirref.org/mdales/" display-uri="mdales" type="local">Michael</fr:link>'s <fr:link href="https://digitalflapjack.com/weeknotes/2025-05-19b/" type="external">notes</fr:link>.</html:p>
                    <html:p>I spent some time trying to speedup the LZW decompression of TIFF files in the pure OCaml tiff library this week(end). The two big changes to help with this are pretty common when speeding up these parts OCaml programs:</html:p>
                    <html:ol>
                      <html:li>
                        <html:p>Allocate less</html:p>
                      </html:li>
                      <html:li>
                        <html:p>Does less work</html:p>
                      </html:li>
                    </html:ol>
                    <html:p>In terms of allocating less, the original implementation was using a <html:code>char list</html:code> to represent LZW strings. Manipulating these becomes quite costly, particularly since the most common operation is appending a single character to the end of a list. Converting this to use OCaml's immutable <html:code>string</html:code> saved a ton of allocations.</html:p>
                    <html:p>In terms of doing less work, I opted to bypass <html:code>Cstruct</html:code>s sane (but slow) bounds checks in some of the "hotter" parts of the code. In particular, LZW ends up reading potentially <html:em>huge</html:em> arrays full of bytes one-by-one. So reading each byte needs to be quite snappy. This is a bit of a trade-off in terms of "safety" but we are in control of this code so I'm not too worried about that.</html:p>
                    <html:p>Here are some results decompressing a fairly large array of some elevation data.</html:p>
                    <html:pre><![CDATA[before: | tiff/lzw/cea │ 523851.2259 mjw/run │ 3289761.5414 mnw/run │ 9806796.7121 ns/run│
after:  │ tiff/lzw/cea │  27846.2408 mjw/run │  587928.7527 mnw/run │ 8457161.3761 ns/run│]]></html:pre>
                  </fr:mainmatter>
                </fr:tree>
              </fr:mainmatter>
            </fr:tree>
          </fr:mainmatter>
        </fr:tree>
      </fr:mainmatter>
    </fr:tree>
    <fr:tree show-metadata="false" hidden-when-empty="true">
      <fr:frontmatter>
        <fr:authors />
        <fr:title text="Backlinks">Backlinks</fr:title>
      </fr:frontmatter>
      <fr:mainmatter />
    </fr:tree>
    <fr:tree show-metadata="false" hidden-when-empty="true">
      <fr:frontmatter>
        <fr:authors />
        <fr:title text="Related">Related</fr:title>
      </fr:frontmatter>
      <fr:mainmatter>
        <fr:tree show-metadata="true" expanded="false" toc="false" numbered="false">
          <fr:frontmatter>
            <fr:authors />
            <fr:uri>https://patrick.sirref.org/ucam/</fr:uri>
            <fr:display-uri>ucam</fr:display-uri>
            <fr:route>/ucam/</fr:route>
            <fr:title text="University of Cambridge">University of Cambridge</fr:title>
            <fr:taxon>institution</fr:taxon>
            <fr:meta name="external">https://www.cam.ac.uk/</fr:meta>
          </fr:frontmatter>
          <fr:mainmatter />
        </fr:tree>
      </fr:mainmatter>
    </fr:tree>
    <fr:tree show-metadata="false" hidden-when-empty="true">
      <fr:frontmatter>
        <fr:authors />
        <fr:title text="Contributions">Contributions</fr:title>
      </fr:frontmatter>
      <fr:mainmatter />
    </fr:tree>
  </fr:backmatter>
</fr:tree>
