<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <updated>2026-03-05</updated>
  <title>Weeknotes</title>
  <id>https://forest.intgrah.com/weeknotes/</id>
  <link rel="alternate" href="https://forest.intgrah.com/weeknotes/" />
  <link rel="self" href="https://forest.intgrah.com/weeknotes/atom.xml" />
  <entry>
    <title>Weeknotes 2026-W10</title>
    <published>2026-03-05T00:00:00Z</published>
    <updated>2026-03-05T00:00:00Z</updated>
    <link rel="alternate" type="text/html" href="https://forest.intgrah.com/001A/" />
    <id>https://forest.intgrah.com/001A/</id>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <section>
          <header>
            <h2>Scoping in query-based elaboration</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
I am proposing a system in which one separates the question of "is this definition in scope" from "elaborate this definition".
</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
In my language, a project is a set of files, with a distinguished entry point. Files may import other files, but there must be no cycles. Imports are transitive: if A imports B, and B imports C, then A's definitions have access to those in C. The transitive closure of a directed acyclic graph is a partial order.
</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
Within a file, we have a list of commands, such as <code>def</code>, <code>axiom</code>, <code>inductive</code>. A command may produce one or more constants. For example, <code>inductive Nat | ...</code> produces four constants: the type former, zero, successor, and the dependent eliminator.
</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
What is not obvious is holes. In my elaborator, a hole, produced by the keyword <code>sorry</code>, is elaborated by creating a new axiom on the fly and abstracting over the context. So, if a <code>sorry</code> is written in a place which expects a <code>Nat</code>, given that <code>x : Nat</code> is in scope, it will generate something like
</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml"><![CDATA[axiom foo._sorry.1 (x : Nat) : Nat]]></pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
and then elaborate the <code>sorry</code> to <code>foo._sorry.1 x</code>.
</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
In practice, the name of the axiom is supposed to be inaccessible. Moreover, it should be unique in the whole project, and it must also be something that is a memoisable result. In Lean, uniqueness is achieved by tagging the sorry's source location to it. In my elaborator, I use a more abstract notion of "path" in the AST, which achieves a similar thing, but is stable under whitespace changes and reordering of commands within a file, hence memoisable.
</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
Suppose we are elaborating <code>foo</code>, and want to fetch a constant <code>bar</code>. We first have to determine: hypothetically, in a batch elaborator, would <code>bar</code> be in scope at the point of <code>foo</code>? The answer is given as follows. Determine where <code>foo</code> and <code>bar</code> are in the whole project (file and command index). If <code>foo</code> and <code>bar</code> are in the same file, does <code>bar</code> come before <code>foo</code>? If not, does <code>foo</code>'s file transitively import <code>bar</code>'s file? This requires an adjacency matrix of the transitive closure of the import graph. Luckily, we only need to do this query once per run, as it is always memoised for the second time onwards. So in some sense, the query-based elaborator is merely pretending to be like a batch elaborator.
</p>
        </section>
        <section>
          <header>
            <h2>Chomp</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
Fun little <a href="https://gist.github.com/intgrah/3776c91aa696a14b1c827c04a75667a2">Lean proof</a> that Player 1 is winning in <a href="https://en.wikipedia.org/wiki/Chomp">Chomp</a>. More generally:
</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
A subset <code>S</code> of a poset is <em>downward closed</em> if for all <code>x \in  S</code> and <code>y \le  x</code>, we have <code>y \in  S</code>. A <em>board</em> is a finite, downward-closed subset of a poset that contains a bottom element. A <em>move</em> consists of choosing a non-bottom element <code>p</code> of the board, and removing all elements <code>q \ge  p</code>. The game ends when only the bottom element remains, and the player who made the last move wins.
</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
If the board has a top element, then Player 1 wins. The proof is by a well-known strategy-stealing argument.
</p>
        </section>
      </div>
    </content>
  </entry>
  <entry>
    <title>Weeknotes 2026-W9</title>
    <published>2026-02-26T00:00:00Z</published>
    <updated>2026-02-26T00:00:00Z</updated>
    <link rel="alternate" type="text/html" href="https://forest.intgrah.com/0019/" />
    <id>https://forest.intgrah.com/0019/</id>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <section>
          <header>
            <h2>Green trees</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
The AST and CST are homogenous and the AST is indexed by its path in the tree. By homogenous, I mean that there is only one kind of internal node, and it carries a SyntaxNodeKind, and an Array of children.
Lean.SyntaxNodeKind is really just the same as Lean.Name. By using Lean.SyntaxNodeKind, I can piggy back off of Lean's parser even more: translating Lean's concrete syntax tree to mine is a five-line recursive function.
</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
Paths exist to have a stable notion of "relative location" without using absolute character positions in source files. Without a homogeneous tree, whitespace-only changes can cause cache invalidation. Paths are defined as <code>List Nat</code>, so a path of <code>[2, 0, 1]</code> means: "from the syntax node of this definition, take the third child, first child, second child." For example:

<code>(def foo^0 : Nat^1 := ((Nat.add^0 Bool.true^1)^0 Nat.zero^1)^2)</code>

identifies <code>Bool.true</code> relative to the beginning of <code>def foo</code>. It does not matter if <code>foo</code> is reordered in the file, or if other definitions are added before it. The type checker functions all have access to the current path in the AST, so error diagnostics can be emitted with a relative location.
</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml"><![CDATA[inductive Ast : Type
  | node (kind : SyntaxNodeKind) (children : Array Ast)
  | ident (name : Name)
  | missing]]></pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
Now it carries its path as an index:
</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml"><![CDATA[inductive Ast : Path → Type
  | node (kind : SyntaxNodeKind) (children : (i : Fin n) → Ast (i.val :: p)) : Ast p
  | ident (name : Name) : Ast p
  | missing : Ast p]]></pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
The reason for making the path intrinsic in the AST type is that when recursively descending into a subterm <code>e[i]</code>, someone has to update the context and cons <code>i</code> onto the path. This is prone to bugs. If the path is part of the type, the unifier does this automatically.
</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
The CST is a green tree in the sense of Roslyn and rust-analyzer: it stores no absolute positions, only token text. Positions are computed by summing widths when traversing the tree. This makes the CST stable under edits in other parts of the file.
</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
I have plans to make the parser output provably correct green concrete syntax trees.
</p>
        </section>
      </div>
    </content>
  </entry>
  <entry>
    <title>Weeknotes 2026-W8</title>
    <published>2026-02-19T00:00:00Z</published>
    <updated>2026-02-19T00:00:00Z</updated>
    <link rel="alternate" type="text/html" href="https://forest.intgrah.com/0018/" />
    <id>https://forest.intgrah.com/0018/</id>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <section>
          <header>
            <h2>Memoisation in query-based elaboration</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
To elaborate a definition, you generally need to fetch its dependencies, which are often just previous definitions. Unfortunately this makes memoisation hard.
</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
Suppose you are elaborating <code>foo</code>. The naive way would be to include "the entire global environment, prior to <code>foo</code>" in the dependencies of <code>foo</code>. This is very easy to invalidate. If one writes another definition before <code>foo</code>, then <code>foo</code>'s dependencies get invalidated.
</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
A less naive way is to track only those definitions which <code>foo</code> actually depends on. If <code>foo</code>'s definition depended on <code>bar</code> and <code>baz</code>, then as long as those have not changed, <code>foo</code> ought to stay the same. This falls into several traps.
</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
Suppose you have
</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml"><![CDATA[def bar := 0
def foo := bar]]></pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
and then you swap the lines in the editor:
</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml"><![CDATA[def foo := bar
def bar := 0]]></pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
A batch elaborator would process <code>foo</code> and reject it, as <code>bar</code> is not defined. A query-based elaborator might check whether <code>foo</code> was memoised, which it indeed is, and then check <code>bar</code> is defined, which it indeed is, and accept.
</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
Here is another example:
</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml"><![CDATA[def bar := 0
def foo := bar]]></pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
changed to
</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml"><![CDATA[def bar := foo
def foo := bar]]></pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
A batch elaborator would reject <code>bar</code>, as <code>foo</code> is not defined. A query-based elaborator would check <code>bar</code>, see that its definition changed, and then check <code>foo</code>. Then it would have to check whether <code>foo</code>'s dependencies changed, which includes <code>bar</code>. This is a cycle. Luckily, cycles can be caught in a query system. However, this is not exactly elegant.
</p>
        </section>
      </div>
    </content>
  </entry>
  <entry>
    <title>Weeknotes 2026-W6</title>
    <published>2026-02-06T00:00:00Z</published>
    <updated>2026-02-06T00:00:00Z</updated>
    <link rel="alternate" type="text/html" href="https://forest.intgrah.com/0010/" />
    <id>https://forest.intgrah.com/0010/</id>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <section>
          <header>
            <h2>Project update</h2>
          </header>
          <section>
            <header>
              <h3>Lean Port</h3>
            </header>
            <p xmlns:html="http://www.w3.org/1999/xhtml">The main motivation for porting the code to Lean: Lean's elaborator is highly extensible, and many features can be reused, such as <code>Lean.Name</code> for hierarchical names, and <code>Lean.SourceInfo</code> for tracking source positions of AST nodes. It is also possible to convert Lean's concrete syntax tree to my syntax through macros. This allows for inline tests, e.g.</p>
            <pre xmlns:html="http://www.w3.org/1999/xhtml">
#fail (
  def foo : Type := bar
) with .unboundVariable ..
</pre>
            <p xmlns:html="http://www.w3.org/1999/xhtml">
Lean is dependently typed, which enables intrinsically well-scoped terms and types (<code>Tm : Nat → Type</code>). Additionally, the types of queries and their result types are now dependent: <code>(q : Q) → R q</code>. In OCaml this would be achieved with GADTs and runtime type identifiers (<code>module Type.Id</code>).
</p>
          </section>
          <section>
            <header>
              <h3>Incrementalisation</h3>
            </header>
            <p xmlns:html="http://www.w3.org/1999/xhtml">
Attempts to recreate Salsa in OCaml have been replaced with a Shake-style build system. Shake handles dynamic dependencies, discovered during execution, monadically. The system maintains a cache of <em>traces</em>, which are records of query, result, and hashes of dependencies. If the hashes are verified to be unchanged, it does early cutoff and returns the cached result.
</p>
            <p xmlns:html="http://www.w3.org/1999/xhtml">
Here is the definition of the <code>Task</code> monad, which provides a function with the ability to fetch queries.
</p>
            <pre xmlns:html="http://www.w3.org/1999/xhtml"><![CDATA[structure Task (α : Type) : Type 1 where
  run : ∀ {f} [Monad f], ReaderT (∀ q, f (R q)) f α]]></pre>
            <p xmlns:html="http://www.w3.org/1999/xhtml"><code>Task</code> is polymorphic in <code>f</code> according to <a href="https://forest.intgrah.com/mokhov-mitchell-peytonjones-2018/">reference mokhov-mitchell-peytonjones-2018/</a>.
</p>
          </section>
        </section>
      </div>
    </content>
  </entry>
  <entry>
    <title>Weeknotes 2025-W49</title>
    <published>2025-12-02T00:00:00Z</published>
    <updated>2025-12-02T00:00:00Z</updated>
    <link rel="alternate" type="text/html" href="https://forest.intgrah.com/000O/" />
    <id>https://forest.intgrah.com/000O/</id>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <section>
          <header>
            <h2>Bidirectional Elaboration for Tarski Universes</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
    Bidirectional type checking now works for this Tarski universe. All that has to be done is check whether a piece of syntax appears in term position or type position, and elaborate accordingly.
</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
    The <code>do_el</code> function implements the decoding of type codes during evaluation. When evaluating <code>TyEl t</code>, if <code>t</code> evaluates to a type code like <code>VTmPiHat</code>, it unfolds to the corresponding semantic type <code>VTyPi</code>. This implements the Tarski equations like <code>El(π(a, b)) ≡ Π(El(a), El(b))</code>.
</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml"><![CDATA[    and do_el (env : env) : vl_tm → vl_ty = function
    | VTmPiHat (x, a, ClosTm (env', b)) →
    VTyPi (x, do_el env a, ClosTy (env', TyEl b))
    | VTmUnitHat → VTyUnit
    | VTmNeutral n → VTyEl n
    | ...]]></pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
    For NbE, the semantic domains <code>vl_ty</code> and <code>vl_tm</code> represent weak head normal forms. A <code>neutral</code> is a head (a local or global variable) applied to a spine of eliminators (applications, projections), i.e. essentially a stuck computation that cannot reduce any further. The <code>neutral</code> type is shared between terms and types.
</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
    The only irreducible <code>El</code> is one applied to a neutral, <code>VTyEl of neutral</code>. Closures defer evaluation under binders until instantiation.
</p>
        </section>
        <section>
          <header>
            <h2>Incrementalisation with Jane Street Incremental</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
Integrated Jane Street's <a href="https://github.com/janestreet/incremental">Incremental</a> library as a proof of concept for reactive elaboration. The pipeline now watches source files and recomputes only invalidated stages when the source changes.
</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
    The architecture wraps each compilation stage (lexing, parsing, elaboration) as an incremental node with cutoffs based on structural equality. Changes propagate through the dependency graph, and observers log when stages are initialised, changed, or invalidated.
</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml"><![CDATA[    let create () =
    let source = Inc.Var.create "" in
    let chars = Inc.map (Inc.Var.watch source) ~f:... in
    let tokens = Inc.map chars ~f:try_lex in
    Inc.set_cutoff tokens (Inc.Cutoff.of_equal ( = ));
    let program = Inc.map tokens ~f:try_parse in
    Inc.set_cutoff program (Inc.Cutoff.of_equal ( = ));
    let elaborated = Inc.map program ~f:try_elaborate in
    ...]]></pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
    Currently the incrementality is at the file level only, because I am yet to figure out how to construct dependency graphs at runtime, probably using the <code>bind</code> functions.
</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
    Note: <a href="https://github.com/ollef/sixty">ollef/sixty</a> builds its query engine on the Haskell library <a href="https://hackage.haskell.org/package/rock">Rock</a>, which defines queries with GADTs.
</p>
        </section>
      </div>
    </content>
  </entry>
  <entry>
    <title>Weeknotes 2025-W46</title>
    <published>2025-11-11T00:00:00Z</published>
    <updated>2025-11-11T00:00:00Z</updated>
    <link rel="alternate" type="text/html" href="https://forest.intgrah.com/000G/" />
    <id>https://forest.intgrah.com/000G/</id>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <section>
          <header>
            <h2>Unifier</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
    Fixed a bug in the pattern unification algorithm. The spine inversion was processing arguments in the wrong order, causing incorrect variable mappings.
</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
    Added tests for the elaborator using Alcotest. Terms are compared up to structural equality, ignoring the variable names kept around for pretty printing.
</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
    I have added bisect_ppx to measure test coverage.
</p>
        </section>
        <section>
          <header>
            <h2>Elaborator and Unification</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
    The elaborator now handles metavariable inference in application contexts. When type checking <code>id _ ()</code>, the hole <code>_</code> in the type argument position gets correctly unified with <code>Unit</code> based on the argument type. This works through the application inference rules in <code>elab.ml</code>:
</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml"><![CDATA[    | App (f, a) ->
    let f', f_ty = infer ctx names f in
    let a_ty, b_clos =
    match Eval.force f_ty with
    | VPi (_, a, b) -> (a, b)
    | _ ->
    (* Not a Pi - insert metas and unify *)
    let a_val = Eval.eval ctx.env (fresh_meta_ctx ctx) in
    let b_tm = fresh_meta_ctx (Check.bind_var ctx a_val) in
    let pi_ty = VPi ("_", a_val, Closure (ctx.env, b_tm)) in
    unify_catch ctx pi_ty f_ty;
    (* ... *)]]></pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
    When the function type is not immediately a Pi type, the elaborator inserts metavariables for both the domain and codomain, then unifies. <code>check ctx names a a_ty</code> checks the argument against the expected type, and unification propagates constraints back to the metavariables.
</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
    Values need to be forced before pattern matching. The type system represents metavariables lazily (<code>VFlex</code>), so after inference you get something that <em>evaluates to</em> <code>VUnit</code> but isn't immediately <code>VUnit</code>. The <code>Eval.force</code> function follows the metavariable solution chain:
</p>
          <pre xmlns:html="http://www.w3.org/1999/xhtml"><![CDATA[    let rec force (v : val_ty) : val_ty =
    match v with
    | VFlex (m, sp) -> (
    match meta m with
    | VFlex (m', sp') -> force (apply_spine (VFlex (m', sp')) sp)
    | v -> force (apply_spine v sp))
    | v -> v]]></pre>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
    Metavariables need to be fully instantiated before structural inspection.
</p>
        </section>
        <section>
          <header>
            <h2>Incrementalisation Steps</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
    The elaborator seems to be in a reasonable state for simple dependent types.
</p>
          <ol xmlns:html="http://www.w3.org/1999/xhtml"><li>Identifying the natural query boundaries (probably at definition boundaries, and maybe at subterm granularity)</li>
    <li>Making the context explicit and immutable for each query</li>
    <li>Representing source positions and dependencies explicitly</li></ol>
        </section>
      </div>
    </content>
  </entry>
  <entry>
    <title>Weeknotes 2025-W42</title>
    <published>2025-10-14T00:00:00Z</published>
    <updated>2025-10-14T00:00:00Z</updated>
    <link rel="alternate" type="text/html" href="https://forest.intgrah.com/0002/" />
    <id>https://forest.intgrah.com/0002/</id>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <section>
          <header>
            <h2>Part II Project</h2>
          </header>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
    I started my Part II Project, titled <em>Query-based incremental Elaborator for a Dependently Typed Language</em>. The project is supervised by <a href="https://forest.intgrah.com/jonmsterling/">Jon Sterling</a>.
    To summarise, the goal of the project is implement an incremental, query-based elaborator for a dependently typed toy language, for efficient type checking in interactive development environments, such as proof assistants.
    The motivation for this, is that traditional type checkers for dependent types operate in batch mode, re-checking entire programs after each change.
    The project will investigate bringing query-based compilation techniques to dependent type elaboration.
</p>
          <p xmlns:html="http://www.w3.org/1999/xhtml">
    A query-based architecture decomposes type checking into <em>queries</em>, memoisable functions whose only effect is to fetch the results of other queries.
    By tracking dependencies for these queries, we can save a lot of work by recomputing only the affected parts of the type checking process.
</p>
        </section>
      </div>
    </content>
  </entry>
</feed>
