<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:fh="http://purl.org/syndication/history/1.0"><channel><title>Modular Moose | Blog</title><description/><link>https://modularmoose.org/</link><language>en</language><atom:link rel="self" href="https://modularmoose.org/blog/rss.xml"/><atom:link rel="prev-archive" href="https://modularmoose.org/blog/rss/2026-10.xml"/><item><title>Building and sharing Moose models with MooseNexus</title><link>https://modularmoose.org/blog/2026-10-21-building-and-sharing-models-with-moosenexus/</link><guid isPermaLink="true">https://modularmoose.org/blog/2026-10-21-building-and-sharing-models-with-moosenexus/</guid><description>Build repeatable Moose models from source projects, automate them with the MooseNexus CLI, and share them through artifact registries.</description><pubDate>Wed, 21 Oct 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Building a Moose model is often only the first step of an analysis. We also need to know which source project produced it, which dependencies were used, which tools extracted it, and how another person can build or retrieve the same model.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/moosetechnology/MooseNexus&quot;&gt;MooseNexus&lt;/a&gt; brings these steps into one repeatable workflow. It builds Moose models, records how they were produced, stores them as versioned artifacts, and can share them through an artifact registry.&lt;/p&gt;
&lt;p&gt;This post first uses the MooseNexus API from a Moose image, then performs the same kind of build with the command-line interface. The final section explains how an artifact registry can store and distribute the resulting models and images.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;what-moosenexus-does&quot;&gt;What MooseNexus does&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;MooseNexus sits between a source project and the Moose model that we want to analyze.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A source project and build specification flow through model extraction into a versioned artifact, which can be stored locally or in a shared registry.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2086&quot; height=&quot;754&quot; src=&quot;https://modularmoose.org/_astro/moosenexus-workflow.5NVj3j7u_2t3pvL.webp&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;From source project to versioned model artifact: MooseNexus records the result locally and can publish it to a shared artifact registry.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;A build starts with two pieces of information:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the directory containing the source project;&lt;/li&gt;
&lt;li&gt;coordinates that identify it: a group, a name, and a version.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;MooseNexus then imports the project metadata, resolves the dependencies needed for extraction, runs the model extractor, and records the result. For Java projects it can recognize Maven and Gradle projects. Projects without a supported build descriptor can be described explicitly as unmanaged projects.&lt;/p&gt;
&lt;p&gt;The result is more than a model file. A model artifact also records its source-project identity, dependency-resolution result, and build provenance, including the Moose, Pharo, MooseNexus, and extractor versions. This information makes it possible to inspect how a model was produced and to select a compatible environment later.&lt;/p&gt;
&lt;p&gt;By default, projects and artifacts are kept in a local repository below &lt;code dir=&quot;auto&quot;&gt;~/.moose&lt;/code&gt;. The important principle is similar to Maven coordinates: &lt;code dir=&quot;auto&quot;&gt;com.example:demo:1.0.0&lt;/code&gt; identifies one version of a project independently of the machine on which it was analyzed.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;build-a-model-with-the-api&quot;&gt;Build a model with the API&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The main API entry point is &lt;code dir=&quot;auto&quot;&gt;MooseNexusBuildSpec&lt;/code&gt;. A build specification describes the intended result; MooseNexus handles the individual import, dependency, extraction, and storage steps.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;1-load-moosenexus&quot;&gt;1. Load MooseNexus&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;For a Java project, load the Java runtime group in a Moose image:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Metacello&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;githubUser:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;moosetechnology&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;project:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;MooseNexus&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;commitish:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;v1.x.x&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;path:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;src&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;baseline:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;MooseNexus&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;load:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;Java&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The floating &lt;code dir=&quot;auto&quot;&gt;v1.x.x&lt;/code&gt; tag selects the newest compatible version in the MooseNexus 1.x series. Use an exact release tag when the build must be fully reproducible.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;2-identify-the-source-project&quot;&gt;2. Identify the source project&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Let us build a model for a project located at &lt;code dir=&quot;auto&quot;&gt;/path/to/demo&lt;/code&gt;. We first give it stable coordinates:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;coordinates&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MooseNexusCoordinates&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;group:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;com.example&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;name:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;demo&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;version:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;1.0.0&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The coordinates identify the project in the local repository and, later, in an artifact registry. They do not need to be the same as Maven or Gradle coordinates, although using the same identity can be convenient.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;3-describe-the-build&quot;&gt;3. Describe the build&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Create a build specification from the coordinates and source directory:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;spec&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MooseNexusBuildSpec&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;coordinates:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;coordinates&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;sourceDirectory:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;/path/to/demo&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;asFileReference&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;spec&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;modelName:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;demo-model&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;modelComment:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;Model used for the architecture analysis&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The source directory can be anywhere; it does not have to be a Git checkout. For a Maven or Gradle project, MooseNexus detects the appropriate importer from the directory. The explicit coordinates remain the identity of the MooseNexus artifact.&lt;/p&gt;
&lt;p&gt;This separation is useful: the build tool describes how the software project is assembled, while the build specification describes the model artifact that we want MooseNexus to produce.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;4-execute-the-build&quot;&gt;4. Execute the build&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Execute the specification in the default repository:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;spec&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;execute&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This performs the complete workflow and records the project below the default &lt;code dir=&quot;auto&quot;&gt;~/.moose&lt;/code&gt; repository. The result gives access to three useful objects:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;project&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;modelArtifact&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dependencyResolutionResult&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Use &lt;code dir=&quot;auto&quot;&gt;executeIn:&lt;/code&gt; with a &lt;code dir=&quot;auto&quot;&gt;MooseNexusRepository&lt;/code&gt; when the artifact should be stored elsewhere:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;repository&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MooseNexusRepository&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;localDirectory:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;/path/to/model-repository&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;asFileReference&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;spec&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;executeIn:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;repository&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;5-load-the-model-in-moose&quot;&gt;5. Load the model in Moose&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Building records the artifact but does not force it into the current image. Import it explicitly when it is time to analyze it:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;project&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;importModel:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;modelArtifact&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The imported model is registered in &lt;code dir=&quot;auto&quot;&gt;MooseModel root&lt;/code&gt;. Keeping the build and import steps separate also lets headless jobs produce artifacts without retaining a full analysis image.&lt;/p&gt;
&lt;p&gt;For most clients, &lt;code dir=&quot;auto&quot;&gt;execute&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;executeIn:&lt;/code&gt; is the API to keep. MooseNexus also exposes the individual build phases, but those are mainly useful when an application needs custom orchestration.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;build-from-the-command-line&quot;&gt;Build from the command line&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/moosetechnology/MooseNexus-CLI&quot;&gt;MooseNexus CLI&lt;/a&gt; runs the same ideas without requiring us to prepare a Moose image by hand. It creates an isolated workspace, provisions a compatible Moose/Pharo runtime, loads MooseNexus, executes a build specification, and stores the result.&lt;/p&gt;
&lt;p&gt;Install it with npm. The CLI requires Node.js 22 or later:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--global&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;@moosetechnology/moosenexus&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;For Java extraction, the default setup also requires Docker. We can check the available tools before starting a build:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;moosenexus&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;doctor&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The interactive wizard is the easiest way to discover the commands:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;moosenexus&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--wizard&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;For a Maven or Gradle project, a direct build can be as small as:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;moosenexus&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;build-model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;com.example:demo:1.0.0&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;/path/to/demo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This creates a model artifact and installs it in the local MooseNexus repository. To create a ready-to-open Moose image containing the imported model instead, use &lt;code dir=&quot;auto&quot;&gt;build-image&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;moosenexus&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;build-image&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;com.example:demo:1.0.0&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;/path/to/demo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;--adopt&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The built image is first stored as an immutable artifact. &lt;code dir=&quot;auto&quot;&gt;--adopt&lt;/code&gt; also copies it to the standard Pharo images directory, where it becomes a working image that we can open and modify.&lt;/p&gt;
&lt;p&gt;The two outputs serve different needs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a &lt;strong&gt;model artifact&lt;/strong&gt; is smaller and can be imported into a compatible existing Moose image;&lt;/li&gt;
&lt;li&gt;an &lt;strong&gt;image artifact&lt;/strong&gt; is a ready-to-open environment containing the model and its compatible runtime.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;what-an-image-artifact-contains&quot;&gt;What an image artifact contains&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;An image artifact is selective rather than a copy of the complete build workspace. Its portable ZIP contains:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;at its root, the &lt;code dir=&quot;auto&quot;&gt;.image&lt;/code&gt; file, its &lt;code dir=&quot;auto&quot;&gt;.changes&lt;/code&gt; file when available, the available Pharo &lt;code dir=&quot;auto&quot;&gt;.sources&lt;/code&gt; files, &lt;code dir=&quot;auto&quot;&gt;meta-inf.ston&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;pharo.version&lt;/code&gt;, and a CLI build report;&lt;/li&gt;
&lt;li&gt;under &lt;code dir=&quot;auto&quot;&gt;pharo-local/MooseNexus/&lt;/code&gt;, the recorded project metadata, model artifact, and a copy of the analyzed source project.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other image-local directories, such as &lt;code dir=&quot;auto&quot;&gt;pharo-local/iceberg&lt;/code&gt;, and the Pharo VM are not included. MooseNexus does not scan these files for credentials or remove secrets: the source copy, saved image, or changes file may contain sensitive information. Review an artifact before publishing it.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;reuse-an-image-artifact&quot;&gt;Reuse an image artifact&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;An installed image artifact can be adopted several times, much like making working copies from a template. Each adoption creates a separate writable image while leaving the repository artifact unchanged:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;moosenexus&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;adopt-image&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;com.example:demo:1.0.0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;moosenexus&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;adopt-image&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;com.example:demo:1.0.0&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--adopt-as&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;demo-alice&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;By default, these copies are placed in the standard Pharo images directory and appear in Pharo Launcher. This is not a Launcher template: MooseNexus copies the image files and launcher metadata from an installed artifact. The recorded project and source copy remain in the local MooseNexus repository rather than being duplicated into every adopted image.&lt;/p&gt;
&lt;p&gt;Use &lt;code dir=&quot;auto&quot;&gt;moosenexus artifacts&lt;/code&gt; to see what is installed locally. Build options can also be kept in a YAML file and passed with &lt;code dir=&quot;auto&quot;&gt;--config&lt;/code&gt;, which is preferable for repeatable scripts and continuous integration. &lt;code dir=&quot;auto&quot;&gt;--dry-run&lt;/code&gt; shows the resolved workflow without executing it, and &lt;code dir=&quot;auto&quot;&gt;--json&lt;/code&gt; produces machine-readable output for automation.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;share-artifacts-through-a-registry&quot;&gt;Share artifacts through a registry&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The important need here is artifact storage and distribution: a shared place where versioned Moose models and images can be published, found, and retrieved.&lt;/p&gt;
&lt;p&gt;MooseNexus currently implements this with the &lt;a href=&quot;https://opencontainers.org/&quot;&gt;Open Container Initiative&lt;/a&gt; distribution conventions. Although OCI is best known for container images, its registries can store other versioned artifacts as well. Reusing that standard gives MooseNexus an existing upload, download, authentication, and access-control ecosystem instead of inventing a Moose-specific artifact server.&lt;/p&gt;
&lt;p&gt;An organization can therefore use infrastructure it may already have—such as Harbor, Sonatype Nexus, Artifactory, or another OCI-compatible registry—to distribute Moose models and images. MooseNexus defines what goes into the artifact, while &lt;a href=&quot;https://oras.land/&quot;&gt;ORAS&lt;/a&gt; performs the standard registry upload and download.&lt;/p&gt;
&lt;p&gt;A MooseNexus model bundle contains:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the exported model;&lt;/li&gt;
&lt;li&gt;an archive of the analyzed sources;&lt;/li&gt;
&lt;li&gt;the project metadata;&lt;/li&gt;
&lt;li&gt;the model manifest, including build and extractor provenance.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Including the sources makes the artifact inspectable and helps reproduce the model, but it is also important to remember before publishing: a model bundle can contain proprietary source code. Use a registry and access policy appropriate for the project.&lt;/p&gt;
&lt;p&gt;First authenticate ORAS with the target registry:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;oras&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;login&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;registry.example.com&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Then add a registry and namespace to the build command:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;moosenexus&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;build-model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;com.example:demo:1.0.0&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;/path/to/demo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;--registry&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;registry.example.com&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;--namespace&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;team/models&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;MooseNexus still installs the artifact locally and also publishes it under a reference derived from the project coordinates, for example:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;registry.example.com/team/models/moosenexus/com.example/demo:1.0.0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Another machine can retrieve the model with the same coordinates:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;moosenexus&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pull-model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;com.example:demo:1.0.0&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;--registry&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;registry.example.com&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;--namespace&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;team/models&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;pull-model&lt;/code&gt; installs the artifact in the local MooseNexus repository. It can then be imported through the API shown earlier. Use &lt;code dir=&quot;auto&quot;&gt;pull-image ... --adopt&lt;/code&gt; when the published artifact is a Moose image and a ready-to-open copy is wanted instead.&lt;/p&gt;
&lt;p&gt;Publication is always explicit: building locally does not silently upload anything. MooseNexus also keeps registry credentials outside its own configuration and relies on the authenticated ORAS installation.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;api-or-cli&quot;&gt;API or CLI?&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Both interfaces use the same project coordinates, build specification, repository, and artifact concepts.&lt;/p&gt;





















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Use the API when…&lt;/th&gt;&lt;th&gt;Use the CLI when…&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;the build is part of a Moose application&lt;/td&gt;&lt;td&gt;the build should start from a clean, isolated runtime&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;an image needs custom import or extraction policy&lt;/td&gt;&lt;td&gt;a shell script or CI job should run the build&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;the resulting model will be analyzed immediately&lt;/td&gt;&lt;td&gt;a model or ready-to-open image should be produced and shared&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The API is the stable foundation, and the CLI automates the surrounding runtime setup. Starting with the CLI is often easier; moving to a Smalltalk build specification gives more control without changing the underlying model-artifact workflow.&lt;/p&gt;
&lt;p&gt;MooseNexus therefore turns a one-off model extraction into a named, versioned, and shareable build result. That becomes especially valuable when a model must outlive the image in which it was first created—or when another person, machine, or CI job needs to produce the same analysis input.&lt;/p&gt;</content:encoded><category>Moose</category><category>Famix</category><category>infrastructure</category></item><item><title>Setup MooseCI on your repository with GitHub Actions</title><link>https://modularmoose.org/blog/2026-10-06-setup-mooseci-with-github-actions/</link><guid isPermaLink="true">https://modularmoose.org/blog/2026-10-06-setup-mooseci-with-github-actions/</guid><description>Run MooseCI code-quality analyses on your repository with GitHub Actions.</description><pubDate>Mon, 05 Oct 2026 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;h1 id=&quot;setup-mooseci-on-your-repository-with-github-actions&quot;&gt;Setup MooseCI on your repository with GitHub Actions&lt;/h1&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;what-is-mooseci&quot;&gt;What is MooseCI?&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/moosetechnology/MooseCI&quot;&gt;MooseCI&lt;/a&gt; is a tool that runs automatic analyses on your code. It looks for code quality problems and writes a report for you.&lt;/p&gt;
&lt;p&gt;MooseCI is built on top of Moose. It can run in headless mode, so you can use it on a CI server.&lt;/p&gt;
&lt;p&gt;You can use MooseCI in two ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;as a command line tool, with Docker&lt;/li&gt;
&lt;li&gt;inside a CI, with its GitHub Action for example&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For now, MooseCI supports Java and Python.&lt;/p&gt;
&lt;p&gt;MooseCI runs its analyses on the &lt;a href=&quot;https://github.com/moosetechnology/Famix&quot;&gt;Famix&lt;/a&gt; model of your project, not on the FAST model.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;run-mooseci-with-docker&quot;&gt;Run MooseCI with Docker&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The easiest way to try MooseCI is with Docker.&lt;/p&gt;
&lt;p&gt;First, pull the image for your language. For Java, use the &lt;code dir=&quot;auto&quot;&gt;latest&lt;/code&gt; image, and for Python, use the &lt;code dir=&quot;auto&quot;&gt;python&lt;/code&gt; image:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pull&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ghcr.io/moosetechnology/moose-ci:latest&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pull&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ghcr.io/moosetechnology/moose-ci:python&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Go to the folder you want to analyze, and create a configuration file with the &lt;code dir=&quot;auto&quot;&gt;init&lt;/code&gt; command:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-v&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;$(&lt;/span&gt;&lt;span&gt;pwd&lt;/span&gt;&lt;span&gt;):/src&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ghcr.io/moosetechnology/moose-ci:latest&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;init&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This creates a &lt;code dir=&quot;auto&quot;&gt;moose-ci.ston&lt;/code&gt; file. You can edit it to choose the rules and the metrics.&lt;/p&gt;
&lt;p&gt;Then run the analysis:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-v&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;$(&lt;/span&gt;&lt;span&gt;pwd&lt;/span&gt;&lt;span&gt;):/src&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ghcr.io/moosetechnology/moose-ci:latest&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;analyze&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;MooseCI prints the report in the console and writes a JSON report in &lt;code dir=&quot;auto&quot;&gt;.moose-ci/report&lt;/code&gt;.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;run-mooseci-in-a-ci-with-github-actions&quot;&gt;Run MooseCI in a CI with GitHub Actions&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;MooseCI is also available as a &lt;a href=&quot;https://github.com/moosetechnology/setup-MooseCI&quot;&gt;GitHub Action&lt;/a&gt;. Add it to a repository, and it runs on every pull request.&lt;/p&gt;
&lt;p&gt;The Action:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;runs MooseCI on your project&lt;/li&gt;
&lt;li&gt;uploads the report as an artifact&lt;/li&gt;
&lt;li&gt;comments on the pull request with a download link and a short summary of the analysis&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;example-with-verveinej&quot;&gt;Example with VerveineJ&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Let’s take &lt;a href=&quot;https://github.com/moosetechnology/VerveineJ&quot;&gt;VerveineJ&lt;/a&gt; as an example. VerveineJ is a Java project that parses Java code and exports it to JSON/MSE for Moose.&lt;/p&gt;
&lt;p&gt;We added MooseCI to VerveineJ. You can see the result in this &lt;a href=&quot;https://github.com/moosetechnology/VerveineJ/pull/275&quot;&gt;pull request&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;First, create the configuration file. Go to the folder you want to analyze, and run &lt;code dir=&quot;auto&quot;&gt;init&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;cd&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;app/src/main/java/fr&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-v&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;$(&lt;/span&gt;&lt;span&gt;pwd&lt;/span&gt;&lt;span&gt;):/src&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ghcr.io/moosetechnology/moose-ci:latest&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;init&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This creates &lt;code dir=&quot;auto&quot;&gt;app/src/main/java/fr/moose-ci.ston&lt;/code&gt;. The file looks like this:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;MooseCIConfig&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;#projectLanguage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#java&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;#metrics&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;#packages&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;#classes&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;#rules&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;#too_many_parameters&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;#large_class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;#unused_local_variable&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;#unused_parameter&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;#outputFormats&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;#json&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;#outputPath&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;.moose-ci/report&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;#visualizations&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;#isRemote&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;In this file, you can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;set the language with &lt;code dir=&quot;auto&quot;&gt;#projectLanguage&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;choose the metrics to compute with &lt;code dir=&quot;auto&quot;&gt;#metrics&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;choose the quality rules with &lt;code dir=&quot;auto&quot;&gt;#rules&lt;/code&gt;, and give a threshold to some rules (for example &lt;code dir=&quot;auto&quot;&gt;#too_many_parameters : 10&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;choose the report format and location with &lt;code dir=&quot;auto&quot;&gt;#outputFormats&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;#outputPath&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Then add the workflow. Create &lt;code dir=&quot;auto&quot;&gt;.github/workflows/moose-ci.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;MooseCI&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;on&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;pull_request&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;permissions&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;contents&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;read&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;actions&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;write&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;pull-requests&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;write&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;jobs&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;analyze&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;runs-on&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;ubuntu-latest&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;steps&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;uses&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;actions/checkout@v4&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;uses&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;moosetechnology/setup-MooseCI@v1.0.0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;with&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;project-path&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;./app/src/main/java/fr&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;project-language&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;java&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Some details:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;on: pull_request&lt;/code&gt; runs the workflow on every pull request.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;actions: write&lt;/code&gt; is needed to upload the report.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;pull-requests: write&lt;/code&gt; is needed to write the comment.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;project-path&lt;/code&gt; is the folder to analyze. It must contain &lt;code dir=&quot;auto&quot;&gt;moose-ci.ston&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;project-language&lt;/code&gt; selects the image. Use &lt;code dir=&quot;auto&quot;&gt;java&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;python&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On each pull request, MooseCI comments with the analysis. For VerveineJ, the summary looks like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;MooseCI comment on a pull request&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;902&quot; height=&quot;473&quot; src=&quot;https://modularmoose.org/_astro/setup-mooseci-vvj-pr-comment.DAppiwtz_Z1BCAx8.webp&quot;&gt;&lt;/p&gt;
&lt;p&gt;The report also contains the list of rule violations, with the location of each problem in the source code.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Content of the downloaded JSON report&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1796&quot; height=&quot;1166&quot; src=&quot;https://modularmoose.org/_astro/setup-mooseci-vvj-report-json.BzZhFCaC_1Ho42Q.webp&quot;&gt;&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;use-mooseci-in-another-ci&quot;&gt;Use MooseCI in another CI&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;MooseCI is not limited to GitHub. In any other CI, you can run the same Docker image and the same commands as the CLI, for example:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-v&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;$(&lt;/span&gt;&lt;span&gt;pwd&lt;/span&gt;&lt;span&gt;):/src&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ghcr.io/moosetechnology/moose-ci:latest&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;analyze&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The report is written in the MooseCI report folder (&lt;code dir=&quot;auto&quot;&gt;.moose-ci/report&lt;/code&gt;). Your CI can then publish it as an artifact.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;MooseCI is easy to use. You can run it locally with Docker, or on every pull request with the GitHub Action. You only need a configuration file and a small workflow.&lt;/p&gt;</content:encoded><category>CI</category><category>Moose</category><category>Java</category></item><item><title>Implementing a Static Single Assigment (SSA) in FAST-Python</title><link>https://modularmoose.org/blog/2026-09-29-ssa-python/</link><guid isPermaLink="true">https://modularmoose.org/blog/2026-09-29-ssa-python/</guid><description>Implement a Static Single Assignment (SSA) representation on top of FAST-Python.</description><pubDate>Tue, 29 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;h1 id=&quot;implementing-the-ssa-of-python-in-fast-python&quot;&gt;Implementing the SSA of Python in FAST-Python&lt;/h1&gt;&lt;/div&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h2 id=&quot;what-is-ssa&quot;&gt;What is SSA?&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Static Single Assignment is a program representation where &lt;strong&gt;every variable is assigned exactly once&lt;/strong&gt;. The same logical variable &lt;code dir=&quot;auto&quot;&gt;x&lt;/code&gt; is renamed into several &lt;em&gt;versions&lt;/em&gt; &lt;code dir=&quot;auto&quot;&gt;x_1&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;x_2&lt;/code&gt;, … — one per assignment — and each &lt;strong&gt;use&lt;/strong&gt; points to the version that can actually provide its value.&lt;/p&gt;
&lt;p&gt;The goal is to make &lt;em&gt;data flow&lt;/em&gt; explicit in the AST: instead of “this &lt;code dir=&quot;auto&quot;&gt;x&lt;/code&gt; is assigned somewhere before”, we get “this &lt;code dir=&quot;auto&quot;&gt;x&lt;/code&gt; is exactly the value produced by that assignment”.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;# x_1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;)     &lt;/span&gt;&lt;span&gt;# uses x_1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;# x_2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;)     &lt;/span&gt;&lt;span&gt;# uses x_2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The hard part starts when the value of a variable can come from &lt;strong&gt;several&lt;/strong&gt; assignments depending on the control flow:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; z &lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;# x_1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;# x_2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;)      &lt;/span&gt;&lt;span&gt;# uses phi(x_1, x_2)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;After the merge of the two branches there is no single assignment that produced &lt;code dir=&quot;auto&quot;&gt;x&lt;/code&gt;: we say &lt;code dir=&quot;auto&quot;&gt;x&lt;/code&gt; has a &lt;strong&gt;phi version&lt;/strong&gt; &lt;code dir=&quot;auto&quot;&gt;phi(x_1, x_2)&lt;/code&gt;, a virtual assignment stating “the value is &lt;code dir=&quot;auto&quot;&gt;x_1&lt;/code&gt; if we came from the first branch, &lt;code dir=&quot;auto&quot;&gt;x_2&lt;/code&gt; if we came from the second”. An analysis consuming the SSA can then explore both possible values.&lt;/p&gt;
&lt;p&gt;For us, the SSA is the third stage of the pipeline, sitting on top of the two previous stages:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Import → Local resolution → CFG → SSA&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It has a hard prerequisite: we must know, for each use, &lt;em&gt;which declaration&lt;/em&gt; it refers to (the &lt;a href=&quot;https://github.com/moosetechnology/FAST-Python/blob/main/resources/doc/analysis.md#local-resolution&quot;&gt;local resolution&lt;/a&gt; stage) and &lt;em&gt;which control-flow paths&lt;/em&gt; exist (the CFG stage). If you have not read about the FAST CFG and its visitor, I strongly recommend the &lt;a href=&quot;https://modularmoose.org/developers/fast-cfg/&quot;&gt;&lt;em&gt;Visiting the control-flow graph&lt;/em&gt; article&lt;/a&gt; first — this blog post is the direct continuation.&lt;/p&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h2 id=&quot;architecture-one-visitor-on-top-of-the-cfg&quot;&gt;Architecture: one visitor on top of the CFG&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The whole transform lives in a single class, &lt;code dir=&quot;auto&quot;&gt;FASTPythonSSAVisitor&lt;/code&gt;. Its declaration shows the trick that makes it work: it combines &lt;strong&gt;two&lt;/strong&gt; visiting abilities—&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPythonVisitor&lt;/span&gt;&lt;span&gt; &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span&gt;#FASTPythonSSAVisitor&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;traits:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;FASTCFGTVisitor&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;slots:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#newVariablesMap&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#localDeclarations&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;tag:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;CFG/LocalResolver/SSA&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;package:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;FAST-Python-Tools&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;the superclass &lt;code dir=&quot;auto&quot;&gt;FASTPythonVisitor&lt;/code&gt; brings the &lt;strong&gt;language visitor&lt;/strong&gt; (the &lt;code dir=&quot;auto&quot;&gt;visitFASTPyXxx:&lt;/code&gt; methods generated from the model, through &lt;code dir=&quot;auto&quot;&gt;FASTPyTVisitor&lt;/code&gt;);&lt;/li&gt;
&lt;li&gt;the trait &lt;code dir=&quot;auto&quot;&gt;FASTCFGTVisitor&lt;/code&gt; brings the &lt;strong&gt;CFG visitor&lt;/strong&gt; (the &lt;code dir=&quot;auto&quot;&gt;visitCFGXxxBlock:&lt;/code&gt; methods that walk the blocks of the CFG, plus the conditional-branch hooks).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So a single &lt;code dir=&quot;auto&quot;&gt;accept:&lt;/code&gt; can traverse the CFG (&lt;code dir=&quot;auto&quot;&gt;visitCFGBlock:&lt;/code&gt; and friends) and, when a block contains Python statements, dispatch back to the language-specific visit methods (&lt;code dir=&quot;auto&quot;&gt;visitFASTPyAssignment:&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;visitFASTTCanBeVariable:&lt;/code&gt;, …).&lt;/p&gt;
&lt;p&gt;The trait is generic and lives in the base FAST project (&lt;code dir=&quot;auto&quot;&gt;FAST-Core-Tools&lt;/code&gt;), which means any language model can reuse it the same way. It is the same trait-based composition idea as the local resolver, but applied to the CFG.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;the-state&quot;&gt;The state&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The visitor has only two instance variables:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;localDeclarations&lt;/code&gt; — an &lt;code dir=&quot;auto&quot;&gt;IdentitySet&lt;/code&gt; of every local declaration that received at least one SSA version while walking the entity. It is the source of the “current active versions” snapshot (see below).&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;newVariablesMap&lt;/code&gt; — an &lt;code dir=&quot;auto&quot;&gt;IdentityDictionary&lt;/code&gt; used &lt;strong&gt;only during the merge of conditional branches&lt;/strong&gt;, to accumulate, per branch, the versions that were created inside that branch.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And the entry point is a class-side convenience:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPythonSSAVisitor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;resolve:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aPythonEntity&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;resolve:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aPythonEntity&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;the-three-ssa-value-classes&quot;&gt;The three SSA value classes&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The versions are not strings, they are &lt;strong&gt;first-class objects&lt;/strong&gt; living in &lt;code dir=&quot;auto&quot;&gt;FAST-Core-Tools&lt;/code&gt; (again reusable across languages), and they are &lt;strong&gt;Moose entities&lt;/strong&gt;: each version is added to the model, so it is persisted and exported with it.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;FASTAbstractVariableVersionSSA&lt;/code&gt; — abstract root. It holds the &lt;code dir=&quot;auto&quot;&gt;localDeclaration&lt;/code&gt; the version belongs to, and offers the queries we need once the SSA is built: &lt;code dir=&quot;auto&quot;&gt;nodes&lt;/code&gt; (the accesses directly linked to this version, the bidirectional opposite of &lt;code dir=&quot;auto&quot;&gt;ssaVersion&lt;/code&gt;), &lt;code dir=&quot;auto&quot;&gt;localUses&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;readAccesses&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;writeAccesses&lt;/code&gt; (restricted to this version), &lt;code dir=&quot;auto&quot;&gt;name&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;isPhi&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;ssaVariables&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;FASTVariableVersionSSA&lt;/code&gt; — a &lt;strong&gt;basic version&lt;/strong&gt; for one assignment. It carries an integer &lt;code dir=&quot;auto&quot;&gt;version&lt;/code&gt; number, so &lt;code dir=&quot;auto&quot;&gt;name&lt;/code&gt; answers &lt;code dir=&quot;auto&quot;&gt;x_1&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;x.y_1&lt;/code&gt;…&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;FASTVariablePhiVersionSSA&lt;/code&gt; — a &lt;strong&gt;phi version&lt;/strong&gt;. It carries &lt;code dir=&quot;auto&quot;&gt;choices&lt;/code&gt;, the collection of versions being merged, so &lt;code dir=&quot;auto&quot;&gt;name&lt;/code&gt; answers &lt;code dir=&quot;auto&quot;&gt;phi(x_1, x_2)&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;isPhi&lt;/code&gt; answers &lt;code dir=&quot;auto&quot;&gt;true&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTVariableVersionSSA&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;streamContents:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;s&lt;/span&gt;&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;s&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;              &lt;/span&gt;&lt;span&gt;nextPutAll:&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;localDeclarationName&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;              &lt;/span&gt;&lt;span&gt;nextPut:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;$_&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;              &lt;/span&gt;&lt;span&gt;nextPutAll:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;asString&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTVariablePhiVersionSSA&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;phi(&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; , &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;join:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;choices&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;collect:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#name&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;span&gt; , &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Nested merges flatten themselves: the phi’s &lt;code dir=&quot;auto&quot;&gt;addChoiceToPhi:&lt;/code&gt; re-dispatches each choice into the receiving phi, so a phi inside a branch ultimately contributes its own choices to the outer phi.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;the-links-carried-on-the-model&quot;&gt;The links carried on the model&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The SSA result is attached to the model through &lt;strong&gt;two links&lt;/strong&gt; defined in FAST-Core-Tools on the trait &lt;code dir=&quot;auto&quot;&gt;FASTTCanBeLocalDeclaration&lt;/code&gt; (used by &lt;code dir=&quot;auto&quot;&gt;FASTTEntity&lt;/code&gt;, so available on every FAST entity):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;entity ssaVersion&lt;/code&gt; — on any &lt;em&gt;access&lt;/em&gt; (read or write) to a variable, the version it is linked to. This is a bidirectional relation: each version exposes the accesses linked to it through its &lt;code dir=&quot;auto&quot;&gt;nodes&lt;/code&gt; collection.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;declaration activeVersion&lt;/code&gt; — on the local &lt;em&gt;declaration&lt;/em&gt;, the current version at the current point of the traversal. This is the internal “state variable” of the algorithm: it is bumped at each assignment and replaced by a phi at each merge. It stays a plain attribute.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTTCanBeLocalDeclaration&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;activeVersion&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;attributeAt:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#activeVersion&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifAbsent:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTTCanBeLocalDeclaration&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;ssaVersion&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;FMProperty:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#ssaVersion&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#FASTAbstractVariableVersionSSA&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;opposite:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#nodes&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;attributeAt:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#ssaVersion&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifAbsent:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The SSA is then a traversal that, at every write, creates a version, adds it to the model, and sets it as &lt;code dir=&quot;auto&quot;&gt;activeVersion&lt;/code&gt;; at every read, copies &lt;code dir=&quot;auto&quot;&gt;activeVersion&lt;/code&gt; into &lt;code dir=&quot;auto&quot;&gt;ssaVersion&lt;/code&gt; of the access.&lt;/p&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h3 id=&quot;the-pipeline-inside-resolve&quot;&gt;The pipeline inside &lt;code dir=&quot;auto&quot;&gt;resolve:&lt;/code&gt;&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;FASTPythonSSAVisitor&gt;&gt;#resolve:&lt;/code&gt; is deliberately buildable in your own project step by step:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPythonSSAVisitor&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;resolve:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFASTBehaviouralEntity&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;First we do a local resolution so that each entity is linked to its&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;local declaration.&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;FASTPythonLocalResolverVisitor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;resolve:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFASTBehaviouralEntity&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;Then we build the CFG to know the different paths in the entity.&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cfg&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFASTBehaviouralEntity&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cfg&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;And lastly, I can build the SSA now that I have the CFG and the&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;local declarations.&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visit:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cfg&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Three stages, three small lines. The local resolution is done &lt;em&gt;inside&lt;/em&gt; the SSA visitor only for convenience; you can equally run it beforehand.&lt;/p&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h2 id=&quot;producing-the-ssa-versions&quot;&gt;Producing the SSA versions&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;the-core-visitfasttcanbevariable&quot;&gt;The core: &lt;code dir=&quot;auto&quot;&gt;visitFASTTCanBeVariable:&lt;/code&gt;&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Just like the local resolver, the SSA logic is concentrated on the trait &lt;code dir=&quot;auto&quot;&gt;FASTTCanBeVariable&lt;/code&gt;, caught in a &lt;em&gt;single&lt;/em&gt; visit method for every node kind that can be a variable (identifier, attribute access, subscript, walrus):&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPythonSSAVisitor&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;visitFASTTCanBeVariable:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTCanBeVariable&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;aTCanBeVariable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;isVariableWriteAccess&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;ifTrue:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;handleNewAssignemntTo:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTCanBeVariable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;ifFalse:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;aTCanBeVariable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;localDeclaration&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;isNonLocalDeclaration&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifFalse:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;&quot;Subscript is a special case since it is not directly assigned.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                 &lt;/span&gt;&lt;/span&gt;&lt;span&gt;So the first read acts as a new declaration.&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;aTCanBeVariable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;isSubscript&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                     &lt;/span&gt;&lt;span&gt;and:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTCanBeVariable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;localDeclaration&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;activeVersion&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;isNil&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;])&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                    &lt;/span&gt;&lt;span&gt;ifTrue:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;handleNewAssignemntTo:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTCanBeVariable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                    &lt;/span&gt;&lt;span&gt;ifFalse:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTCanBeVariable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ssaVersion:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTCanBeVariable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;localDeclaration&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;activeVersion&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;super &lt;/span&gt;&lt;span&gt;visitFASTTCanBeVariable:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTCanBeVariable&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The rule is a direct SSA translation of the local resolver’s “write declares, read binds”:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;write access&lt;/strong&gt; → create a new version (&lt;code dir=&quot;auto&quot;&gt;handleNewAssignemntTo:&lt;/code&gt;);&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;read access&lt;/strong&gt; → copy the declaration’s &lt;code dir=&quot;auto&quot;&gt;activeVersion&lt;/code&gt; into the access’s &lt;code dir=&quot;auto&quot;&gt;ssaVersion&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;read of an unresolved name&lt;/strong&gt; (&lt;code dir=&quot;auto&quot;&gt;localDeclaration isNonLocalDeclaration&lt;/code&gt;) → nothing. &lt;code dir=&quot;auto&quot;&gt;print&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;len&lt;/code&gt;, imported functions and variables have no declaration in the model, so they get no version (&lt;code dir=&quot;auto&quot;&gt;ssaVersion&lt;/code&gt; stays &lt;code dir=&quot;auto&quot;&gt;nil&lt;/code&gt;);&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;first read of a subscript&lt;/strong&gt; whose declaration has no version yet → &lt;em&gt;it behaves like a declaration&lt;/em&gt;: the first &lt;code dir=&quot;auto&quot;&gt;x[3]&lt;/code&gt; read is treated as an assignment (mirroring the local-resolver convention), so its version is created there.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;creating-a-version&quot;&gt;Creating a version&lt;/h3&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPythonSSAVisitor&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;handleNewAssignemntTo:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFASTEntity&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;aFASTEntity&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ssaVersion:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;((&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;createVariableVersionFor:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFASTEntity&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                 &lt;/span&gt;&lt;span&gt;newVersionNumber&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                 &lt;/span&gt;&lt;span&gt;yourself&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPythonSSAVisitor&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;createVariableVersionFor:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFASTEntity&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;newSSA&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;newSSA&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FASTVariableVersionSSA&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;for:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFASTEntity&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;aFASTEntity&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;mooseModel&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;add:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;newSSA&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;aFASTEntity&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;lastSSAVersion&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifNotNil:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;lastSSA&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;newSSA&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;version:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;lastSSA&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;aFASTEntity&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;localDeclaration&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;activeVersion:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;newSSA&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;localDeclarations&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;add:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFASTEntity&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;localDeclaration&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;newSSA&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;FASTVariableVersionSSA for: aFASTEntity&lt;/code&gt; records &lt;code dir=&quot;auto&quot;&gt;aFASTEntity localDeclaration&lt;/code&gt; as the declaration the version belongs to. Then:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;the new version is &lt;strong&gt;added to the model&lt;/strong&gt; — the versions are Moose entities, so this makes them persistent and exported with the model;&lt;/li&gt;
&lt;li&gt;the version &lt;strong&gt;number&lt;/strong&gt; is seeded from &lt;code dir=&quot;auto&quot;&gt;lastSSAVersion&lt;/code&gt; — the active version of the &lt;em&gt;previous&lt;/em&gt; declaration of the same name, chased through the local-resolver shadowing chain: it is what makes &lt;code dir=&quot;auto&quot;&gt;x_1&lt;/code&gt; then &lt;code dir=&quot;auto&quot;&gt;x_2&lt;/code&gt; even when an unrelated &lt;code dir=&quot;auto&quot;&gt;def x():&lt;/code&gt; was declared in between;&lt;/li&gt;
&lt;li&gt;the new version becomes the &lt;code dir=&quot;auto&quot;&gt;activeVersion&lt;/code&gt; of the declaration;&lt;/li&gt;
&lt;li&gt;the declaration is added to &lt;code dir=&quot;auto&quot;&gt;localDeclarations&lt;/code&gt; (so the “snapshot” of active versions, used for the branches, sees it);&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;newVersionNumber&lt;/code&gt; bumps the integer — &lt;code dir=&quot;auto&quot;&gt;version := version + 1&lt;/code&gt; — and the result is stored as the write access’s &lt;code dir=&quot;auto&quot;&gt;ssaVersion&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPyEntity&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;lastSSAVersion&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;scrolling the shadowing chain of the declaration to find a previous version&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;entity&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;entity&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;localDeclaration&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;entity&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;isNotNil&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;whileTrue:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;entity&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;activeVersion&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifNotNil:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;entity&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;entity&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;shadowing&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h2 id=&quot;reordering-the-visits-the-order-matters-for-ssa&quot;&gt;Reordering the visits: the order matters for SSA&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The generated visitor visits the children of a node in &lt;em&gt;metamodel&lt;/em&gt; order. For the SSA, that order is often wrong because &lt;strong&gt;a read must be resolved against the versions before the node, and a write must only bump the version after its right-hand side has been read&lt;/strong&gt;. We overwrite the generated visit methods in four places.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;assignments-the-right-side-comes-first&quot;&gt;Assignments: the right side comes first&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;This is the most important one. In the metamodel, the &lt;code dir=&quot;auto&quot;&gt;left&lt;/code&gt; of an assignment comes before its &lt;code dir=&quot;auto&quot;&gt;right&lt;/code&gt;. For the SSA we must invert:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;visitFASTPyAssignment:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;anAssignment&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;Visiting the right field before the left because the variables at the&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;right should be linked to the previous assignment.&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitFASTPyTAssignable:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;anAssignment&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitFASTPyExpression:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;anAssignment&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitEntity:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;anAssignment&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;right&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitEntity:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;anAssignment&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;left&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitEntity:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;anAssignment&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Consider &lt;code dir=&quot;auto&quot;&gt;x = x + 1&lt;/code&gt;. In metamodel order we would visit the left &lt;code dir=&quot;auto&quot;&gt;x&lt;/code&gt; first: it would create &lt;code dir=&quot;auto&quot;&gt;x_2&lt;/code&gt; and set it as &lt;code dir=&quot;auto&quot;&gt;activeVersion&lt;/code&gt;, and &lt;em&gt;then&lt;/em&gt; the &lt;code dir=&quot;auto&quot;&gt;x&lt;/code&gt; in &lt;code dir=&quot;auto&quot;&gt;x + 1&lt;/code&gt; would read — wrongly — the new &lt;code dir=&quot;auto&quot;&gt;x_2&lt;/code&gt;. By visiting &lt;code dir=&quot;auto&quot;&gt;right&lt;/code&gt; before &lt;code dir=&quot;auto&quot;&gt;left&lt;/code&gt;, the read sees &lt;code dir=&quot;auto&quot;&gt;x_1&lt;/code&gt; and the write bumps afterwards.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;function-definitions-parameters-before-the-body&quot;&gt;Function definitions: parameters before the body&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Parameters are declarations that the body reads, so they have to be visited before the body:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;visitFASTPyFunctionDefinition:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFunctionDefinition&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;Reordering so parameters are visited before the statements, in order&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;to have all the declarations.&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitFASTTWithParameters:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFunctionDefinition&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitEntity:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFunctionDefinition&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;returnType&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitFASTPyTDefinition:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFunctionDefinition&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitFASTPyTWithTypeParameters:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFunctionDefinition&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitFASTPyStatement:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFunctionDefinition&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;visitFASTPyMethodDefinition:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aMethodDefinition&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;We resolve in the same way as functions.&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitFASTPyFunctionDefinition:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aMethodDefinition&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;definitions-rebuild-their-own-cfg&quot;&gt;Definitions rebuild their own CFG&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;A function definition appearing as a statement of the module is &lt;em&gt;inside&lt;/em&gt; the module CFG. But the function’s body is a separate control-flow world. When we reach a definition, we therefore &lt;strong&gt;rebuild a fresh CFG and restart the traversal on it&lt;/strong&gt;, so each definition is turned into its own SSA form:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;visitFASTPyTDefinition:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTDefinition&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;We need to redo the CFG for definitions.&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;cfg&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitFASTTNamedEntity:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTDefinition&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitCollection:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTDefinition&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;decorators&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cfg&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTDefinition&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cfg&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visit:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cfg&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h2 id=&quot;building-the-phi-versions&quot;&gt;Building the phi versions&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Where do phi versions come from? The CFG visitor. When &lt;code dir=&quot;auto&quot;&gt;FASTCFGTVisitor&lt;/code&gt; visits a conditional block, it visits &lt;strong&gt;all the branches before the merge&lt;/strong&gt;, and during that it calls &lt;strong&gt;four hooks&lt;/strong&gt; you can override. Their default implementation in the trait is empty:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;preConditionalsBranchesVisitOf:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aConditionalBlock&lt;/span&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;before the first branch&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;preConditionalsBranchVisitOf:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;block&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;conditional:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aConditionalBlock&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;&quot;before each branch&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;postConditionalsBranchVisitOf:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;block&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;conditional:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aConditionalBlock&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;after each branch&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;postConditionalsBranchesVisitOf:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aConditionalBlock&lt;/span&gt;&lt;span&gt;         &lt;/span&gt;&lt;span&gt;&quot;after all branches, before the merge&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;That is exactly the machinery we fill in to build phis. The idea is a three-step protocol:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;before the branches&lt;/strong&gt;: snapshot the active versions;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;after each branch&lt;/strong&gt;: record which &lt;em&gt;new&lt;/em&gt; versions were created by that branch;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;after all branches&lt;/strong&gt;: merge, per variable, one version per branch (plus the snapshot version for branches that did not assign it) into a phi.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;h3 id=&quot;step-1--snapshot-before-the-branches&quot;&gt;Step 1 — snapshot before the branches&lt;/h3&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPythonSSAVisitor&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;preConditionalsBranchesVisitOf:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aConditionalBlock&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;When we start to visit the branches of a conditional, we create an&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;entry for this conditional in the new variables map and we save the&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;active versions present before visiting the children.&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;newVariablesMap&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;at:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aConditionalBlock&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;put:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(IdentityDictionary&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;with:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#previousVariables&lt;/span&gt;&lt;span&gt; -&gt; self &lt;/span&gt;&lt;span&gt;currentActiveVersions&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;currentActiveVersions&lt;/code&gt; is a snapshot of every declaration’s active version at this point:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;currentActiveVersions&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;localDeclarations&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;collect:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#activeVersion&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;step-2--record-the-new-versions-of-each-branch&quot;&gt;Step 2 — record the new versions of each branch&lt;/h3&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPythonSSAVisitor&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;postConditionalsBranchVisitOf:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;firstBranchBlock&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;conditional:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aConditionalBlock&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;Once we visited a conditional branch, we save the current active&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;versions for this branch.&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;mapForConditional&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;mapForConditional&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;newVariablesMap&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;at:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aConditionalBlock&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;mapForConditional&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;at:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;firstBranchBlock&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;put:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;currentActiveVersions&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;difference:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;mapForConditional&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;at:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#previousVariables&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;difference&lt;/code&gt; is atomic: subtracting the snapshot (&lt;code dir=&quot;auto&quot;&gt;#previousVariables&lt;/code&gt;) from the current active versions leaves exactly the versions &lt;strong&gt;created inside this branch&lt;/strong&gt; (the ones that were not there before). We store them per branch block.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;step-3--build-the-phis-and-merge&quot;&gt;Step 3 — build the phis and merge&lt;/h3&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPythonSSAVisitor&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;postConditionalsBranchesVisitOf:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aConditionalBlock&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;Once we are done visiting a conditional block we can clean the map and build the Phi variables.&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;mapForConditional&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;previousVariables&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;mapForConditional&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;newVariablesMap&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;at:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aConditionalBlock&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;previousVariables&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;mapForConditional&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;at:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#previousVariables&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;mapForConditional&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;removeKey:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#previousVariables&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;producePhiVersionBasedOnPreviousVariables:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;previousVariables&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;andNewVariableMap:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;mapForConditional&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;newVariablesMap&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;removeKey:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aConditionalBlock&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The heavy lifting is in &lt;code dir=&quot;auto&quot;&gt;producePhiVersionBasedOnPreviousVariables:andNewVariableMap:&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPythonSSAVisitor&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;producePhiVersionBasedOnPreviousVariables:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;previousVariables&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;andNewVariableMap:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;newVariablesMap&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;declarationsToMerge&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;declarationsToMerge&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;newVariablesMap&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;values&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;flatten&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;collectAsSet:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#localDeclaration&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;declarationsToMerge&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;do:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;localDeclaration&lt;/span&gt;&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;allVersions&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;First we collect all the versions to use to produce a new Phi version&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;         &lt;/span&gt;&lt;/span&gt;&lt;span&gt;for the current local declaration.&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;allVersions&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Set&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;newVariablesMap&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;valuesDo:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;variables&lt;/span&gt;&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;variables&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;detect:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;variable&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;variable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;localDeclaration&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;localDeclaration&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;ifFound:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;variable&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;allVersions&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;add:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;variable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;If not all branches create a new version, we need to add the previous&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;         &lt;/span&gt;&lt;/span&gt;&lt;span&gt;version also to the list of variables for the Phi variable. Note that&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;         &lt;/span&gt;&lt;/span&gt;&lt;span&gt;it is possible it did not exist before.&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;allVersions&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;newVariablesMap&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifFalse:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;previousVariables&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;detect:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;variable&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;variable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;localDeclaration&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;localDeclaration&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;ifFound:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;variable&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;allVersions&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;add:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;variable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;createPhiVersionFor:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;localDeclaration&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;versions:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;allVersions&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Decoding it:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;declarationsToMerge&lt;/code&gt; — the set of &lt;em&gt;distinct local declarations&lt;/em&gt; that received at least one new version in some branch;&lt;/li&gt;
&lt;li&gt;for each such declaration, walk the branch map and gather the &lt;strong&gt;one version per branch&lt;/strong&gt; that belongs to it;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;if not every branch created a version&lt;/strong&gt; for it, a branch may fall straight through with the &lt;em&gt;old&lt;/em&gt; value — so we also merge in the version that was active &lt;strong&gt;before&lt;/strong&gt; the conditional (from the &lt;code dir=&quot;auto&quot;&gt;previousVariables&lt;/code&gt; snapshot), if it existed;&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;createPhiVersionFor:versions:&lt;/code&gt; then decides.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPythonSSAVisitor&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;createPhiVersionFor:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;localDeclaration&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;versions:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;allVersions&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;No need to add it to the versions since it was already added by the&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;previous versions.&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;phiVersion&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;allVersions&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt; &amp;#x3C; &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifTrue:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;No phi if we do not have at least 2 versions&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;phiVersion&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FASTVariablePhiVersionSSA&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;for:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;allVersions&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;allVersions&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;anyOne&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;mooseModel&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;add:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;phiVersion&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;localDeclaration&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;activeVersion:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;phiVersion&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;phiVersion&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Two guard rails:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;if a single candidate version remains (e.g. only one branch assigns, and merging the previous version produces a single version) there is &lt;strong&gt;nothing to merge&lt;/strong&gt;, so no phi is created — the single version just stays active;&lt;/li&gt;
&lt;li&gt;otherwise a &lt;code dir=&quot;auto&quot;&gt;FASTVariablePhiVersionSSA&lt;/code&gt; is created with the candidate versions as &lt;code dir=&quot;auto&quot;&gt;choices&lt;/code&gt;, and becomes the new &lt;code dir=&quot;auto&quot;&gt;activeVersion&lt;/code&gt; of the declaration — so the reads right after the merge pick it up via the normal “copy &lt;code dir=&quot;auto&quot;&gt;activeVersion&lt;/code&gt; into &lt;code dir=&quot;auto&quot;&gt;ssaVersion&lt;/code&gt;” rule.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;No need to “attach” anything else: the phi inherits from the version classes, so it knows its &lt;code dir=&quot;auto&quot;&gt;localDeclaration&lt;/code&gt; and exposes &lt;code dir=&quot;auto&quot;&gt;localUses&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;readAccesses&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;writeAccesses&lt;/code&gt; restricted to the merged versions.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;traced-example&quot;&gt;Traced example&lt;/h3&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; y &lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;# x_1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;# x_2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;)      &lt;/span&gt;&lt;span&gt;# phi(x_1, x_2)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Walked by the visitor:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;preConditionalsBranchesVisitOf:&lt;/code&gt; → &lt;code dir=&quot;auto&quot;&gt;previousVariables&lt;/code&gt; snapshot is empty (no version yet).&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;then&lt;/code&gt; branch: &lt;code dir=&quot;auto&quot;&gt;x = 4&lt;/code&gt; → &lt;code dir=&quot;auto&quot;&gt;handleNewAssignemntTo:&lt;/code&gt; creates &lt;code dir=&quot;auto&quot;&gt;x_1&lt;/code&gt;, becomes active.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;postConditionalsBranchVisitOf:&lt;/code&gt; → branch recorded with &lt;code dir=&quot;auto&quot;&gt;{x_1}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;else&lt;/code&gt; branch: &lt;code dir=&quot;auto&quot;&gt;x = 5&lt;/code&gt; → creates &lt;code dir=&quot;auto&quot;&gt;x_2&lt;/code&gt;, becomes active.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;postConditionalsBranchVisitOf:&lt;/code&gt; → branch recorded with &lt;code dir=&quot;auto&quot;&gt;{x_2}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;postConditionalsBranchesVisitOf:&lt;/code&gt; → declaration merged: &lt;code dir=&quot;auto&quot;&gt;{x_1}&lt;/code&gt; from branch 1, &lt;code dir=&quot;auto&quot;&gt;{x_2}&lt;/code&gt; from branch 2 → both branches assigned, so no previous version added → &lt;code dir=&quot;auto&quot;&gt;allVersions = {x_1, x_2}&lt;/code&gt; → phi created, becomes active.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;print(x)&lt;/code&gt; is read after the merge → &lt;code dir=&quot;auto&quot;&gt;ssaVersion := activeVersion&lt;/code&gt; → &lt;code dir=&quot;auto&quot;&gt;phi(x_1, x_2)&lt;/code&gt;. The use is linked to both possible values.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And the case where a branch does &lt;strong&gt;not&lt;/strong&gt; assign the variable:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;       &lt;/span&gt;&lt;span&gt;# x_1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; y &lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt;()   &lt;/span&gt;&lt;span&gt;# no assignment of x&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;# x_2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;)    &lt;/span&gt;&lt;span&gt;# phi(x_1, x_2)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Step 6 here: branch 2 introduced &lt;code dir=&quot;auto&quot;&gt;x_2&lt;/code&gt; only, and branch 1 introduced none for &lt;code dir=&quot;auto&quot;&gt;x&lt;/code&gt; → &lt;code dir=&quot;auto&quot;&gt;allVersions&lt;/code&gt; starts as &lt;code dir=&quot;auto&quot;&gt;{x_2}&lt;/code&gt;, its size (1) is &lt;em&gt;not&lt;/em&gt; the number of branches (2) → we add the previous version &lt;code dir=&quot;auto&quot;&gt;x_1&lt;/code&gt; from the snapshot → &lt;code dir=&quot;auto&quot;&gt;allVersions = {x_1, x_2}&lt;/code&gt; → phi. Correct: if the first branch is taken, &lt;code dir=&quot;auto&quot;&gt;x&lt;/code&gt; still holds the old value.&lt;/p&gt;
&lt;p&gt;If the assignment happens in a single branch and no previous version exists, then &lt;code dir=&quot;auto&quot;&gt;allVersions&lt;/code&gt; ends up with a single element → &lt;strong&gt;no phi&lt;/strong&gt;, and the reads just use that single version — matching the (correct) semantics that the variable is simply that assignment in all reachable paths.&lt;/p&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h2 id=&quot;querying-the-result&quot;&gt;Querying the result&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Once the SSA is built, the model can be queried directly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;access ssaVersion&lt;/code&gt; — the version of the access: a &lt;code dir=&quot;auto&quot;&gt;FASTVariableVersionSSA&lt;/code&gt; or a &lt;code dir=&quot;auto&quot;&gt;FASTVariablePhiVersionSSA&lt;/code&gt; (or &lt;code dir=&quot;auto&quot;&gt;nil&lt;/code&gt; for unresolved names and non-local declarations).&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;access ssaName&lt;/code&gt; — its pretty name, e.g. &lt;code dir=&quot;auto&quot;&gt;x_1&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;x.y_2&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;phi(x_1, x_2)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;version nodes&lt;/code&gt; — the accesses directly linked to this version through &lt;code dir=&quot;auto&quot;&gt;ssaVersion&lt;/code&gt; (the bidirectional opposite).&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;version localUses&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;version readAccesses&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;version writeAccesses&lt;/code&gt; — the accesses &lt;strong&gt;for this specific version&lt;/strong&gt; (in the phi case, over all its choices).&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;model allSSAVersions&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;model allResolvedVariableVersions&lt;/code&gt; — all the versions of the model, the latter without duplicates.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;variable allSSAVersions&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;variable allSSABasicVersions&lt;/code&gt; — all versions of one variable, the latter without the phis.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;printCall&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;arguments&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;first&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ssaVersion&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;phi(x_1, x_2)&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;printCall&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;arguments&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;first&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ssaVersion&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;localUses&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The full API is documented in the &lt;a href=&quot;https://github.com/moosetechnology/FAST-Python/blob/main/resources/doc/analysis.md#exploiting-the-ssa&quot;&gt;&lt;em&gt;Exploiting the SSA&lt;/em&gt; section of &lt;code dir=&quot;auto&quot;&gt;analysis.md&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h2 id=&quot;known-limits&quot;&gt;Known limits&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The SSA inherits the limitations of the two stages it sits on:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Instance variables&lt;/strong&gt; (&lt;code dir=&quot;auto&quot;&gt;self.x&lt;/code&gt;) cannot be treated correctly: there is no declaration of them, and we do not know the order in which methods are invoked.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subscripts are matched by their source code&lt;/strong&gt;, so &lt;code dir=&quot;auto&quot;&gt;x[a]&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;x[b]&lt;/code&gt; are conflated — and the whole “first read acts as a declaration” convention is a workaround, not a real answer.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Non-local declarations get no version&lt;/strong&gt;: unresolved and imported names are invisible to the SSA.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Attribute access chains&lt;/strong&gt; are not tracked (&lt;code dir=&quot;auto&quot;&gt;a = x.y&lt;/code&gt; then &lt;code dir=&quot;auto&quot;&gt;a.z&lt;/code&gt; is not linked to &lt;code dir=&quot;auto&quot;&gt;x.y.z&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You will find these documented in the &lt;a href=&quot;https://github.com/moosetechnology/FAST-Python/blob/main/resources/doc/analysis.md#limitations-of-local-resolver-and-ssa&quot;&gt;&lt;em&gt;Limitations&lt;/em&gt; section&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h2 id=&quot;quick-start&quot;&gt;Quick start&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&quot;Import&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FASTPythonImporter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;parseFile:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFile&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&quot;Full pipeline: local resolution is done inside&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPythonSSAVisitor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;resolve:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;allFunctionDefinitions&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;first&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&quot;Or explicitly, step by step&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FASTPythonImporter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;parseFile:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFile&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPythonLocalResolverVisitor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;resolve:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;module&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;allFunctionDefinitions&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;first&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cfg&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPythonSSAVisitor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;resolve:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;allFunctionDefinitions&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;first&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The SSA requires &lt;strong&gt;Python 3&lt;/strong&gt; scoping, like the local resolver it builds on.&lt;/p&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h2 id=&quot;advice-for-implementing-ssa-in-your-own-fast-project&quot;&gt;Advice for implementing SSA in your own FAST project&lt;/h2&gt;&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Reuse the generic machinery.&lt;/strong&gt; &lt;code dir=&quot;auto&quot;&gt;FASTCFGTVisitor&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;FASTVariableVersionSSA&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;FASTVariablePhiVersionSSA&lt;/code&gt; and the version queries live in the base FAST project (&lt;code dir=&quot;auto&quot;&gt;FAST-Core-Tools&lt;/code&gt;). You should only have to write the language-specific part: the &lt;code dir=&quot;auto&quot;&gt;visitX:&lt;/code&gt; rules for your nodes and the branch hooks.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The write/read rule is your whole core.&lt;/strong&gt; One visit on the trait “can be a variable” (read → copy active version, write → create version) is enough, provided the local resolution already linked uses to declarations.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Drive phis from the CFG hooks, not by scanning.&lt;/strong&gt; The four &lt;code dir=&quot;auto&quot;&gt;pre/postConditionals*&lt;/code&gt; hooks give you the branch boundaries for free. Snapshot before, record per branch, merge after — that protocol is generic.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Order your visits so reads see the old version.&lt;/strong&gt; The metamodel order is a trap: reorder assignments (right before left), functions (parameters before body), and anything that mixes declaration and use.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Give each access a version and each declaration a “current version” attribute.&lt;/strong&gt; A &lt;code dir=&quot;auto&quot;&gt;ssaVersion&lt;/code&gt; relation (bidirectional with &lt;code dir=&quot;auto&quot;&gt;nodes&lt;/code&gt;) and an &lt;code dir=&quot;auto&quot;&gt;activeVersion&lt;/code&gt; attribute on &lt;code dir=&quot;auto&quot;&gt;FASTTCanBeLocalDeclaration&lt;/code&gt; were enough. Make the versions Moose entities and add them to the model so they are persisted and exported.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Make the versions first-class objects, not strings.&lt;/strong&gt; Give them a &lt;code dir=&quot;auto&quot;&gt;localDeclaration&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;name&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;ssaVariables&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;choices&lt;/code&gt;; the query API (&lt;code dir=&quot;auto&quot;&gt;localUses&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;readAccesses&lt;/code&gt;, …) then comes almost for free on the abstract root.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Handle your “no declaration” case explicitly.&lt;/strong&gt; In Python, unresolved/imported names simply get no version. Decide early what your language’s equivalent is (a non-local placeholder, an explicit global scope…).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;FAST-Python&lt;/code&gt; sources you will want to look at: &lt;code dir=&quot;auto&quot;&gt;FASTPythonSSAVisitor&lt;/code&gt; (this post is a guided read of it), the &lt;code dir=&quot;auto&quot;&gt;FASTCFGTVisitor&lt;/code&gt; trait and the &lt;code dir=&quot;auto&quot;&gt;FAST*VersionSSA&lt;/code&gt; classes in &lt;code dir=&quot;auto&quot;&gt;FAST-Core-Tools&lt;/code&gt;, and the SSA tests in &lt;code dir=&quot;auto&quot;&gt;FASTPythonSSATest&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h2 id=&quot;moving-this-implementation-to-fast&quot;&gt;Moving this implementation to FAST&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This implementation currently lives in &lt;code dir=&quot;auto&quot;&gt;FAST-Python&lt;/code&gt;, but almost everything in it could move to the base FAST project in the future.&lt;/p&gt;
&lt;p&gt;The language-specific part is surprisingly thin. Given a &lt;strong&gt;CFG&lt;/strong&gt;, a &lt;strong&gt;local resolution&lt;/strong&gt;, and a model whose variables use the &lt;code dir=&quot;auto&quot;&gt;FASTTCanBeVariable&lt;/code&gt; trait, this SSA implementation gives you almost everything for free:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the version classes (&lt;code dir=&quot;auto&quot;&gt;FASTVariableVersionSSA&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;FASTVariablePhiVersionSSA&lt;/code&gt;) and the &lt;code dir=&quot;auto&quot;&gt;FASTCFGTVisitor&lt;/code&gt; trait already live in &lt;code dir=&quot;auto&quot;&gt;FAST-Core-Tools&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;the write/read rule is a single visit method on &lt;code dir=&quot;auto&quot;&gt;FASTTCanBeVariable&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;the phi building runs on the generic CFG hooks.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, for a new language, there is almost nothing more to do: mostly override the few &lt;code dir=&quot;auto&quot;&gt;visitX:&lt;/code&gt; methods where the &lt;em&gt;metamodel order&lt;/em&gt; is wrong for SSA — assignments (right before left), functions (parameters before body), and definitions (rebuild their own CFG) — to reorder the visits.&lt;/p&gt;</content:encoded><category>FAST</category><category>SSA</category><category>Python</category></item><item><title>Implementing the Local Resolver of Python in FAST-Python</title><link>https://modularmoose.org/blog/2026-09-16-local-resolver-python/</link><guid isPermaLink="true">https://modularmoose.org/blog/2026-09-16-local-resolver-python/</guid><description>Why the hell is python so bad?</description><pubDate>Wed, 16 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;h1 id=&quot;implementing-the-local-resolver-of-python-in-fast-python&quot;&gt;Implementing the Local Resolver of Python in FAST-Python&lt;/h1&gt;&lt;/div&gt;
&lt;p&gt;The goal of this blog post is to explain how I implemented a local resolver for FAST-Python. FAST-Python is on of the hardest project to implement this kind of algo, so reading this should help implementing any other local resolver for other languages.&lt;/p&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h2 id=&quot;what-is-local-resolution&quot;&gt;What is local resolution?&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Local resolution is a &lt;em&gt;symbol resolution&lt;/em&gt; pass: it links each named entity to the entity that &lt;strong&gt;declares&lt;/strong&gt; it. In other words, for every occurrence of a name — read, write, call, import — it answers the question &lt;em&gt;“where does this name come from?”&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;In &lt;code dir=&quot;auto&quot;&gt;FAST-Python&lt;/code&gt;, after the model is imported from source, running the local resolver produces a model where every name usage points to its &lt;strong&gt;local declaration&lt;/strong&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;# this is the declaration of `x`&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;)     &lt;/span&gt;&lt;span&gt;# this use of `x` is linked to the declaration above&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;It is called &lt;em&gt;local&lt;/em&gt; because it only resolves declarations that live &lt;strong&gt;in the same file/model&lt;/strong&gt; (in contrast to a global/system resolution that would also resolve calls to external libraries, standard modules, etc.). Once we went through the file, a name that is not declared anywhere in the file gets bound to a special &lt;code dir=&quot;auto&quot;&gt;FASTNonLocalDeclaration&lt;/code&gt; placeholder — it &lt;em&gt;is&lt;/em&gt; a declaration for the model, but we know it refers to something outside.&lt;/p&gt;
&lt;p&gt;Local resolution is the foundation on top of which our other analyses are built such as the &lt;a href=&quot;https://github.com/moosetechnology/FAST-Python/blob/main/resources/doc/analysis.md#static-single-assignment-ssa&quot;&gt;Static Single Assignment (SSA)&lt;/a&gt;. Without it, you cannot even tell whether two &lt;code dir=&quot;auto&quot;&gt;x&lt;/code&gt; in the code are the same variable. You can’t even say if a &lt;code dir=&quot;auto&quot;&gt;FASTPyIdentifier&lt;/code&gt; is a variable or not.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;the-api&quot;&gt;The API&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The result of the resolution is exposed through two accessors available on every FAST entity (they live in the &lt;code dir=&quot;auto&quot;&gt;FAST-Core-Tools&lt;/code&gt; package of the base FAST project, so they are reusable across languages):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;entity localDeclaration&lt;/code&gt; — from any &lt;strong&gt;use&lt;/strong&gt; of a name, returns the entity that declares it (the first assignment, a &lt;code dir=&quot;auto&quot;&gt;FASTPyFunctionDefinition&lt;/code&gt;, a loop variable, an import…). If the name was not declared in the file, it returns a &lt;code dir=&quot;auto&quot;&gt;FASTNonLocalDeclaration&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;declaration localUses&lt;/code&gt; — from a &lt;strong&gt;declaration&lt;/strong&gt;, returns all the entities that resolve to it (usages and other declarations that share it).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is a bidirectional relationship: &lt;code dir=&quot;auto&quot;&gt;localUses&lt;/code&gt; is the exact inverse information of &lt;code dir=&quot;auto&quot;&gt;localDeclaration&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;On top of those two, &lt;code dir=&quot;auto&quot;&gt;FAST-Python&lt;/code&gt; adds a set of convenience queries that only make sense once the resolution is done — and only for nodes that represent variables:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;access allAccesses&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;allReadAccesses&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;allWriteAccesses&lt;/code&gt; — all the read/write accesses to the same variable.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;access internalAccesses&lt;/code&gt; — the attribute accesses and subscripts on the variable (&lt;code dir=&quot;auto&quot;&gt;x.y&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;x[3]&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;access allNodesUsingMe&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;access allStatementsUsingMe&lt;/code&gt; — the statements that use the variable.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;variable isResolvedVariable&lt;/code&gt; — &lt;code dir=&quot;auto&quot;&gt;true&lt;/code&gt; if the node resolves to a local variable declaration (and is not a function, method, import or unresolved name).&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;node usedVariables&lt;/code&gt; — all the entities in the subtree of the node that resolve to local variables.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The full list is documented in the &lt;a href=&quot;https://github.com/moosetechnology/FAST-Python/blob/main/resources/doc/analysis.md#querying-local-resolver-information&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;analysis.md&lt;/code&gt; “Querying local resolver information” section&lt;/a&gt;.&lt;/p&gt;
&lt;aside aria-label=&quot;The accessors above are expressed as #localDeclaration, #localUses, they are attributes in Moose.&quot;&gt;&lt;p aria-hidden=&quot;true&quot;&gt;The accessors above are expressed as &lt;code dir=&quot;auto&quot;&gt;#localDeclaration&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;#localUses&lt;/code&gt;, they are &lt;strong&gt;attributes&lt;/strong&gt; in Moose.&lt;/p&gt;&lt;div&gt;&lt;p&gt;For those new to attributes, it’s a way to add data in a MooseEntity even if we do not have a slot for it.&lt;/p&gt;&lt;/div&gt;&lt;/aside&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h2 id=&quot;implementation-a-moose-visitor&quot;&gt;Implementation: a Moose visitor&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The resolver is implemented as &lt;strong&gt;a Moose/FAST visitor&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;FASTPythonLocalResolverVisitor&lt;/code&gt;. It visits a FAST model (a &lt;code dir=&quot;auto&quot;&gt;FASTPythonVisitor&lt;/code&gt; built on the generated visitor trait &lt;code dir=&quot;auto&quot;&gt;FASTPyTVisitor&lt;/code&gt;) and inspects/annotates the nodes in place.&lt;/p&gt;
&lt;p&gt;If you are not familiar with how the visitor is generated from the model, I strongly recommend reading &lt;em&gt;&lt;a href=&quot;https://modularmoose.org/blog/2026-05-20-improving-visitor-generator-copy/&quot;&gt;Improving the Visitor Generator&lt;/a&gt;&lt;/em&gt; first: it explains how &lt;code dir=&quot;auto&quot;&gt;FASTPyTVisitor&lt;/code&gt; is produced and how you can override the generated &lt;code dir=&quot;auto&quot;&gt;visitX:&lt;/code&gt; methods.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;the-python-problem-there-is-no-declaration-of-variables&quot;&gt;The Python problem: there is no declaration of variables&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Before we can write a single line of the algorithm, we have to deal with the first (and deepest) Python quirk: &lt;strong&gt;there is no declaration of variables&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;In Java you get a real declaration:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;;   &lt;/span&gt;&lt;span&gt;// I declare and type `x`&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;In Python, &lt;em&gt;an assignment is the declaration&lt;/em&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;# this IS the declaration of `x`&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;There is no keyword, no type, no way to distinguish “declare a fresh variable” from “reassign an existing one” syntactically — the same syntax &lt;code dir=&quot;auto&quot;&gt;x = ...&lt;/code&gt; does both. The resolver has to decide, and the decision is purely &lt;strong&gt;lexical reasoning about scopes and order&lt;/strong&gt;, with no syntactic marker to lean on. Concretely:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The first assignment in a scope is the declaration.&lt;/strong&gt; The resolver must therefore know the &lt;em&gt;order&lt;/em&gt; in which things appear, and which construct “creates” a scope.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Parameters&lt;/strong&gt; are declarations: &lt;code dir=&quot;auto&quot;&gt;def f(x): ...&lt;/code&gt; declares &lt;code dir=&quot;auto&quot;&gt;x&lt;/code&gt; as the function’s parameter. They are semantically the first assignment in the function’s scope.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Walrus operators&lt;/strong&gt; (&lt;code dir=&quot;auto&quot;&gt;x := ...&lt;/code&gt;) declare &lt;code dir=&quot;auto&quot;&gt;x&lt;/code&gt; inline, even inside an expression or an &lt;code dir=&quot;auto&quot;&gt;if&lt;/code&gt; condition.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A &lt;code dir=&quot;auto&quot;&gt;for ... in ...&lt;/code&gt; loop declares its target variable&lt;/strong&gt; — but only the first time; it must be a declaration when the variable is not already known in the scope.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Augmented assignments&lt;/strong&gt; (&lt;code dir=&quot;auto&quot;&gt;x += 1&lt;/code&gt;) are &lt;strong&gt;uses + writes&lt;/strong&gt; to the same variable.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;For clauses&lt;/strong&gt; in a list comprehension.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In our implementation this all boils down to a single rule expressed in &lt;code dir=&quot;auto&quot;&gt;visitFASTTCanBeVariable:&lt;/code&gt; (see &lt;a href=&quot;#the-heart-visitfasttcanbevariable&quot;&gt;below&lt;/a&gt;): &lt;strong&gt;a write access declares and bind, a read access binds&lt;/strong&gt;. Everything else is scope management around that rule.&lt;/p&gt;
&lt;aside aria-label=&quot;Note&quot;&gt;&lt;p aria-hidden=&quot;true&quot;&gt;Note&lt;/p&gt;&lt;div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;A note on “first write access”&lt;/strong&gt;: the “declaration” is the &lt;em&gt;lexically&lt;/em&gt; first write access (or parameter, or walrus) in a scope — but not necessarily the first at runtime.A variable assigned inside a branch that is not taken, or behind a condition that is false, is still the declaration for the resolver. This may sound wrong if you think of declarations as a runtime concept, but local resolution is not about execution semantics: its purpose is to &lt;strong&gt;link all the entities that represent the same variable in the source&lt;/strong&gt;. For that purpose, the lexically first declaration is a good enough anchor — it gives us a stable, deterministic reference point for every name in a scope, regardless of control flow.&lt;/p&gt;&lt;/div&gt;&lt;/aside&gt;
&lt;div&gt;&lt;h3 id=&quot;a-scope-stack&quot;&gt;A scope stack&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The whole state of the algorithm is a single instance variable — and the class itself is tiny. Here is the complete class declaration:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPythonVisitor&lt;/span&gt;&lt;span&gt; &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span&gt;#FASTPythonLocalResolverVisitor&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;slots:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#namesContext&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;tag:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;CFG/LocalResolver/SSA&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;package:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;FAST-Python-Tools&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The superclass is &lt;code dir=&quot;auto&quot;&gt;FASTPythonVisitor&lt;/code&gt; (from the generated &lt;code dir=&quot;auto&quot;&gt;FASTPyTVisitor&lt;/code&gt; trait), so all the &lt;code dir=&quot;auto&quot;&gt;visitX:&lt;/code&gt; methods come for free: we only override the ones where the metamodel visit order differs from the resolution order.&lt;/p&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;namesContext&lt;/code&gt; is a &lt;strong&gt;stack of scopes&lt;/strong&gt; (a &lt;code dir=&quot;auto&quot;&gt;Stack&lt;/code&gt; of &lt;code dir=&quot;auto&quot;&gt;Dictionary&lt;/code&gt;s, mapping &lt;code dir=&quot;auto&quot;&gt;name -&gt; declaration&lt;/code&gt;). It is initialized in &lt;code dir=&quot;auto&quot;&gt;initialize&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;initialize&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;super &lt;/span&gt;&lt;span&gt;initialize&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;namesContext&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Stack&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The class entry point is trivial:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPythonLocalResolverVisitor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;resolve:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aModule&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;resolve:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aModule&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;and the instance &lt;code dir=&quot;auto&quot;&gt;resolve:&lt;/code&gt; wraps everything in one scope and runs the visitor:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;resolve:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFASTBehaviouralEntity&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;useNewScopeDuring:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;flush attributes in case this is not the first resolution&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;aFASTBehaviouralEntity&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;withAllContainedEntities&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;do:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;entity&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;entity&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;resetLocalResolution&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;aFASTBehaviouralEntity&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;accept:&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&amp;#x3C;== Launch the resolution on the tree&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Scopes are pushed/popped around the constructs that define a new scope (module, function, comprehension), through &lt;code dir=&quot;auto&quot;&gt;useNewScopeDuring:&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;useNewScopeDuring:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aBlock&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;namesContext&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;push:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Dictionary&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aBlock&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ensure:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;namesContext&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pop&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;the-core-operations&quot;&gt;The core operations&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The algorithm is three small operations combined:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;get&lt;/code&gt;&lt;/strong&gt; — look a name up in the stack of scopes (from top to bottom):&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;declarationNamed:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aName&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;namesContext&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;do:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;at:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aName&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifPresent:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;declaration&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;declaration&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;set&lt;/code&gt; / ensure a declaration&lt;/strong&gt; — put a declaration in the current scope, handling re-declaration and shadowing (see &lt;a href=&quot;#shadowing-in-python&quot;&gt;Shadowing&lt;/a&gt;):&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ensureDeclarationOf:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aName&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;declaration:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFASTNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;in:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;at:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aName&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;ifPresent:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;declaration&lt;/span&gt;&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;declaration&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;localResolverKind&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;aFASTNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;localResolverKind&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;ifTrue:&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;declaration&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;ifFalse:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;declaration&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;shadowedBy:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFASTNode&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                           &lt;/span&gt;&lt;span&gt;aFASTNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ensureLocalUses&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                           &lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;at:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aName&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;put:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFASTNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;ifAbsentPut:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFASTNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ensureLocalUses&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;yourself&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;bind&lt;/code&gt;&lt;/strong&gt; — link a use to the existing declaration (creating a &lt;code dir=&quot;auto&quot;&gt;FASTNonLocalDeclaration&lt;/code&gt; if none is found):&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;bind:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFASTNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;toDeclarationNamed:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aName&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;bind:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFASTNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;toDeclarationNamed:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aName&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;              &lt;/span&gt;&lt;span&gt;ifAbsentUse:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;ensureNonlocalDeclarationNamed:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aName&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;bind:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFASTNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;toDeclarationNamed:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aName&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifAbsentUse:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aBlock&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;declaration&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;declaration&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;declarationNamed:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aName&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifNil:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aBlock&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cull:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFASTNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cull:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aName&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;aFASTNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;localDeclaration:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;declaration&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;declaration&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;addLocalUse:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFASTNode&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h4 id=&quot;what-happens-when-no-declaration-is-found&quot;&gt;What happens when no declaration is found&lt;/h4&gt;&lt;/div&gt;
&lt;p&gt;When a read has no matching declaration in any scope, &lt;code dir=&quot;auto&quot;&gt;bind:...ifAbsentUse:&lt;/code&gt; falls back to &lt;code dir=&quot;auto&quot;&gt;ensureNonlocalDeclarationNamed:&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;ensureNonlocalDeclarationNamed:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aName&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; self&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;ensureDeclarationOf:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aName&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;declaration:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(FASTNonLocalDeclaration&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                   &lt;/span&gt;&lt;span&gt;name:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aName&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                   &lt;/span&gt;&lt;span&gt;yourself&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;in:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;namesContext&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;first&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Note the scope: &lt;code dir=&quot;auto&quot;&gt;namesContext first&lt;/code&gt; is the &lt;strong&gt;bottom&lt;/strong&gt; of the stack, so a &lt;code dir=&quot;auto&quot;&gt;FASTNonLocalDeclaration&lt;/code&gt; behaves as if it were declared at module level — reads of an undeclared name in a function and at module level end up in the same place. Also note that the fallback for attribute accesses and subscripts is slightly different (see &lt;a href=&quot;#the-heart-visitfasttcanbevariable&quot;&gt;the heart&lt;/a&gt;): &lt;code dir=&quot;auto&quot;&gt;declarationForUndeclaredNode:named:&lt;/code&gt; creates a local declaration on the &lt;em&gt;first read&lt;/em&gt; of a subscript when the receiving variable has a declaration, and only resorts to the non-local declaration otherwise:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;declarationForUndeclaredNode:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;named:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aName&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;In case of a subscript, if the receiving variable exists, we consider&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;that the first read access to the subscript is the declaration.&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;isSubscript&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifTrue:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;localDeclarationifPresent:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;decl&lt;/span&gt;&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;ensureDeclarationOf:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aName&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                                &lt;/span&gt;&lt;span&gt;declaration:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                                &lt;/span&gt;&lt;span&gt;in:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;namesContext&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;top&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;ifAbsent:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Nothing, just let the non local declaration.&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;ensureNonlocalDeclarationNamed:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aName&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;the-heart-visitfasttcanbevariable&quot;&gt;The heart: &lt;code dir=&quot;auto&quot;&gt;visitFASTTCanBeVariable:&lt;/code&gt;&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Everything that &lt;em&gt;can be a variable&lt;/em&gt; in FAST-Python implements the trait &lt;code dir=&quot;auto&quot;&gt;FASTTCanBeVariable&lt;/code&gt; (identifiers, attribute accesses, subscripts, walrus…). The visitor intercepts them in one place, and this is where “write declares / read binds” lives:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;visitFASTTCanBeVariable:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTCanBeVariable&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;aTCanBeVariable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;isVariableWriteAccess&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;ifTrue:&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;ensureDeclarationOf:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTCanBeVariable&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                            &lt;/span&gt;&lt;span&gt;named:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTCanBeVariable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;localDeclarationName&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                            &lt;/span&gt;&lt;span&gt;declaration:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTCanBeVariable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;ifFalse:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;bind:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTCanBeVariable&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                            &lt;/span&gt;&lt;span&gt;toDeclarationNamed:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTCanBeVariable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;localDeclarationName&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                            &lt;/span&gt;&lt;span&gt;ifAbsentUse:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;node&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;declarationForUndeclaredNode:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;node&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;named:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;super &lt;/span&gt;&lt;span&gt;visitFASTTCanBeVariable:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTCanBeVariable&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Two details make Python specific here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;localDeclarationName&lt;/code&gt;&lt;/strong&gt; is the name that will be used for scope lookup. It is not always the identifier text: an &lt;em&gt;attribute access&lt;/em&gt; and a &lt;em&gt;subscript&lt;/em&gt; use their &lt;strong&gt;source code&lt;/strong&gt; as their name, so &lt;code dir=&quot;auto&quot;&gt;x.y&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;x[3]&lt;/code&gt; are treated as first-class “variables” (with known limits, see &lt;a href=&quot;#known-limits-and-what-is-left-to-do&quot;&gt;Limitations&lt;/a&gt;). Every named entity gets a default from the base FAST project (&lt;code dir=&quot;auto&quot;&gt;FASTTNamedEntity&gt;&gt;localDeclarationName&lt;/code&gt; returns &lt;code dir=&quot;auto&quot;&gt;#name&lt;/code&gt;); the Python classes only override it where the name is not the identifier:&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&quot;from FAST, the default for any named entity:&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTTNamedEntity &gt;&gt; &lt;/span&gt;&lt;span&gt;localDeclarationName&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&quot;Python overrides:&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPyAttributeAccess &gt;&gt; &lt;/span&gt;&lt;span&gt;localDeclarationName&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;sourceCode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPySubscript       &gt;&gt; &lt;/span&gt;&lt;span&gt;localDeclarationName&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;sourceCode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;isVariableWriteAccess&lt;/code&gt;&lt;/strong&gt; decides whether a node is a write access or a read access. It comes from FAST (&lt;code dir=&quot;auto&quot;&gt;FASTTEntity&gt;&gt;isVariableWriteAccess&lt;/code&gt;), but it delegates to &lt;code dir=&quot;auto&quot;&gt;variableDeclaration&lt;/code&gt; which is an &lt;code dir=&quot;auto&quot;&gt;explicitRequirement&lt;/code&gt; — every FAST project must implement it for the node kinds that can be variable write accesses. In FAST-Python, each relevant class provides its own logic to walk up the AST and check whether it sits in a write position:&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&quot;FAST core — the API:&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTTEntity &gt;&gt; &lt;/span&gt;&lt;span&gt;isVariableWriteAccess&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;variableDeclaration&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;isNotNil&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTTEntity &gt;&gt; &lt;/span&gt;&lt;span&gt;variableDeclaration&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;If I am a node representing a write access, I return the node&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;assigning me. Else I return nil.&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;explicitRequirement&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&quot;FAST-Python — an identifier checks whether it is the left side of&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;an assignment, a for-loop target, etc.:&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPyIdentifier &gt;&gt; &lt;/span&gt;&lt;span&gt;variableDeclaration&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;assignedNode&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;assignedNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;selfOrTopmostAssignableCollection&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;assignedNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;parentAssignmentLeft&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifNotNil:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;assignment&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;assignment&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;assignedNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;parentForStatementLeft&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifNotNil:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;assignedNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;parentForInClauseLeft&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifNotNil:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;clause&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;clause&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; super &lt;/span&gt;&lt;span&gt;variableDeclaration&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&quot;Parameters and walrus are their own declarator:&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPyParameter &gt;&gt; &lt;/span&gt;&lt;span&gt;variableDeclaration&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPyWalrus    &gt;&gt; &lt;/span&gt;&lt;span&gt;variableDeclaration&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&quot;Attribute accesses and subscripts check for parentAssignmentLeft:&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPyAttributeAccess &gt;&gt; &lt;/span&gt;&lt;span&gt;variableDeclaration&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;selfOrTopmostAssignableCollection&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;parentAssignmentLeft&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;ifNotNil:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;assignment&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;assignment&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; super &lt;/span&gt;&lt;span&gt;variableDeclaration&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&quot;The default on FASTPyEntity returns nil (not a write access):&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPyEntity &gt;&gt; &lt;/span&gt;&lt;span&gt;variableDeclaration&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The interesting bit: for identifiers, &lt;code dir=&quot;auto&quot;&gt;variableDeclaration&lt;/code&gt; does not just check the immediate parent — it first walks through tuple/destructuring parents via &lt;code dir=&quot;auto&quot;&gt;selfOrTopmostAssignableCollection&lt;/code&gt;, so that in &lt;code dir=&quot;auto&quot;&gt;(a, b) = (1, 2)&lt;/code&gt; the individual &lt;code dir=&quot;auto&quot;&gt;a&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;b&lt;/code&gt; correctly return the tuple assignment as their declaration.&lt;/p&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h2 id=&quot;reordering-the-visit-or-dealing-with-python-scoping&quot;&gt;Reordering the visit, or dealing with Python scoping&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Because the visitor is generated (see the &lt;a href=&quot;https://modularmoose.org/blog/2026-05-20-improving-visitor-generator-copy/&quot;&gt;visitor generator blog post&lt;/a&gt;), it visits the children of a node in the metamodel order. For a resolver, &lt;strong&gt;metamodel order is not always resolution order&lt;/strong&gt;: a construct may &lt;em&gt;declare&lt;/em&gt; a name in a part of the syntax that the generated visitor reaches too late (or too early) relative to its uses.&lt;/p&gt;
&lt;p&gt;Our main tool is therefore: &lt;strong&gt;override the generated &lt;code dir=&quot;auto&quot;&gt;visitX:&lt;/code&gt; with a manual ordering of a few &lt;code dir=&quot;auto&quot;&gt;visitEntity:&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;visitCollection:&lt;/code&gt; calls&lt;/strong&gt; — and be very careful about when to open a scope, because Python does not create a scope where you would expect one.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;block-scoping-is-inconsistent-if-and-while&quot;&gt;Block scoping is inconsistent: &lt;code dir=&quot;auto&quot;&gt;if&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;while&lt;/code&gt;&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;In most block-structured languages you expect:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;if (cond) { let y = 3; }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;use(y);   // Compile error: y does not exist&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Python &lt;strong&gt;does not create a scope for blocks&lt;/strong&gt;. An &lt;code dir=&quot;auto&quot;&gt;if&lt;/code&gt;, a &lt;code dir=&quot;auto&quot;&gt;while&lt;/code&gt;, a &lt;code dir=&quot;auto&quot;&gt;for&lt;/code&gt; body do not introduce a new scope:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; cond:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;y &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt;)      &lt;/span&gt;&lt;span&gt;# 3, perfectly valid Python&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Combine that with “assignment is the declaration” and you get &lt;em&gt;leaks&lt;/em&gt;: a variable assigned inside an &lt;code dir=&quot;auto&quot;&gt;if&lt;/code&gt; branch or a loop is visible after the block. For the resolver this means &lt;strong&gt;no &lt;code dir=&quot;auto&quot;&gt;useNewScopeDuring:&lt;/code&gt; around branches&lt;/strong&gt; — a name assigned in the &lt;code dir=&quot;auto&quot;&gt;then&lt;/code&gt; must be visible in the &lt;code dir=&quot;auto&quot;&gt;else&lt;/code&gt; and after the whole statement. What we &lt;em&gt;do&lt;/em&gt; control is the order, which is important for shadowing: in an &lt;code dir=&quot;auto&quot;&gt;if&lt;/code&gt;, the semantics are&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;the &lt;strong&gt;condition&lt;/strong&gt; (can use outer variables, and &lt;code dir=&quot;auto&quot;&gt;walrus&lt;/code&gt; operators can even &lt;em&gt;declare&lt;/em&gt; variables!),&lt;/li&gt;
&lt;li&gt;the &lt;strong&gt;then&lt;/strong&gt; clause,&lt;/li&gt;
&lt;li&gt;the &lt;strong&gt;elif&lt;/strong&gt; clauses (in order),&lt;/li&gt;
&lt;li&gt;the &lt;strong&gt;else&lt;/strong&gt; clause.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;visitFASTPyIfStatement:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;anIfStatement&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;visit then - elif(s) -&gt; else&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitFASTTConditionalStatement:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;anIfStatement&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitFASTPyStatement:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;anIfStatement&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitEntity:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;anIfStatement&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;thenClause&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitCollection:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;anIfStatement&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;elifClauses&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitFASTPyTWithElseClause:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;anIfStatement&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Note that we do &lt;strong&gt;not&lt;/strong&gt; call &lt;code dir=&quot;auto&quot;&gt;super&lt;/code&gt; here: the point is precisely to produce our own child order instead of the metamodel one.&lt;/p&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;while&lt;/code&gt; statements are similar, but the &lt;code dir=&quot;auto&quot;&gt;else&lt;/code&gt; clause has to go &lt;strong&gt;last&lt;/strong&gt; (it runs when the loop condition becomes false):&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;visitFASTPyWhileStatement:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aWhileStatement&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitFASTTConditionalStatement:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aWhileStatement&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitFASTTStatementBlock:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aWhileStatement&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitFASTPyStatement:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aWhileStatement&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitFASTPyTWithElseClause:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aWhileStatement&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;for-loops-leak-their-variable&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;for&lt;/code&gt; loops leak their variable&lt;/h3&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; i &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;range&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;):&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;pass&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;)      &lt;/span&gt;&lt;span&gt;# 9 — the loop variable is still there!&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;for ... in ...&lt;/code&gt; statement declares its loop variable in the &lt;strong&gt;enclosing scope&lt;/strong&gt; (there is no loop scope). &lt;code dir=&quot;auto&quot;&gt;i&lt;/code&gt; survives after the loop. So a &lt;code dir=&quot;auto&quot;&gt;for&lt;/code&gt; is simultaneously a &lt;em&gt;scoping&lt;/em&gt; and a &lt;em&gt;declaring&lt;/em&gt; construct: the resolver must declare the target (&lt;code dir=&quot;auto&quot;&gt;left&lt;/code&gt;) in the &lt;strong&gt;current scope&lt;/strong&gt; — no push — and, since that is the declaration, visit it &lt;strong&gt;before&lt;/strong&gt; the iterable and the body:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;visitFASTPyForStatement:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aForStatement&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitEntity:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aForStatement&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;left&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitEntity:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aForStatement&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;right&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitFASTPyTWithElseClause:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aForStatement&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitFASTTStatementBlock:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aForStatement&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitFASTPyStatement:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aForStatement&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;function-and-method-definitions-parameters-are-declarations&quot;&gt;Function and method definitions: parameters are declarations&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The generated visitor does not visit the &lt;strong&gt;parameters&lt;/strong&gt; before the body — but the parameters are declarations that the body uses. So &lt;code dir=&quot;auto&quot;&gt;visitFASTPyFunctionDefinition:&lt;/code&gt; manually visits parameters first, wrapped in a &lt;strong&gt;new scope&lt;/strong&gt;, and &lt;em&gt;does not&lt;/em&gt; use &lt;code dir=&quot;auto&quot;&gt;super&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;visitFASTPyFunctionDefinition:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFunctionDefinition&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;ensureDeclarationOf:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFunctionDefinition&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;named:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFunctionDefinition&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;declaration:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFunctionDefinition&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;useNewScopeDuring:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;do not use super: parameters must be visited before the body&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitFASTTWithParameters:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFunctionDefinition&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitFASTPyTWithTypeParameters:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFunctionDefinition&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitFASTPyStatement:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFunctionDefinition&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitEntity:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFunctionDefinition&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;returnType&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitFASTPyTDefinition:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFunctionDefinition&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;visitFASTPyMethodDefinition:&lt;/code&gt; simply delegates to the function one.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;comprehensions-a-scope-that-leaks-itself-but-not-its-body&quot;&gt;Comprehensions: a scope that leaks &lt;em&gt;itself&lt;/em&gt;, but not its body&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Comprehensions are Python 3’s attempt at “introduce an expression-level scope”, and they only partially succeed:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;x &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; x &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; coll&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;)      &lt;/span&gt;&lt;span&gt;# NameError in Python 3 — x does not leak OUT of the comprehension&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;In Python 3, the comprehension has its &lt;strong&gt;own scope&lt;/strong&gt;, so the loop variable of its &lt;code dir=&quot;auto&quot;&gt;for&lt;/code&gt; clause does not escape. But the &lt;code dir=&quot;auto&quot;&gt;for&lt;/code&gt; clause(s) and the &lt;code dir=&quot;auto&quot;&gt;if&lt;/code&gt; condition(s) can still &lt;em&gt;see and use&lt;/em&gt; variables from the enclosing scope, and the comprehension’s own variable is in scope through the whole comprehension (the body and the conditions can refer to the &lt;code dir=&quot;auto&quot;&gt;for&lt;/code&gt; clause variables).&lt;/p&gt;
&lt;p&gt;That gives you a scope that is neither fully lexical like a function, nor absent like a block. In our implementation, &lt;code dir=&quot;auto&quot;&gt;visitFASTPyComprehension:&lt;/code&gt; opens a dedicated scope and &lt;strong&gt;reorders the visit&lt;/strong&gt; so that the &lt;code dir=&quot;auto&quot;&gt;for&lt;/code&gt; clauses are processed &lt;em&gt;before&lt;/em&gt; the conditions and the body (otherwise the conditions/body would be visited against the wrong scope):&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;visitFASTPyComprehension:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aComprehension&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;useNewScopeDuring:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitFASTPyTSplatExpression:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aComprehension&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitFASTPyExpression:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aComprehension&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitCollection:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aComprehension&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;forClauses&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitCollection:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aComprehension&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;conditions&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitEntity:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aComprehension&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;body&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;We also had to choose a Python version:&lt;/p&gt;
&lt;aside aria-label=&quot;Note&quot;&gt;&lt;p aria-hidden=&quot;true&quot;&gt;Note&lt;/p&gt;&lt;div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;The resolver is implemented for &lt;strong&gt;Python 3&lt;/strong&gt; semantics. In Python 2, comprehensions had &lt;em&gt;no&lt;/em&gt; scope at all and their variable leaked to the enclosing scope. We explicitly did not support Python 2 scoping; supporting both would require making the comprehension scoping rule configurable.&lt;/p&gt;&lt;/div&gt;&lt;/aside&gt;
&lt;div&gt;&lt;h3 id=&quot;other-constructs-that-declare-names&quot;&gt;Other constructs that declare names&lt;/h3&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Imports&lt;/strong&gt; declare the imported name (or its alias) in the current scope — &lt;code dir=&quot;auto&quot;&gt;visitFASTPyImport:&lt;/code&gt; ensures a declaration for each imported entity (using &lt;code dir=&quot;auto&quot;&gt;alias&lt;/code&gt; if present, source code otherwise).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Walrus operator&lt;/strong&gt; &lt;code dir=&quot;auto&quot;&gt;(x := ...)&lt;/code&gt; declares &lt;code dir=&quot;auto&quot;&gt;x&lt;/code&gt; — &lt;code dir=&quot;auto&quot;&gt;visitFASTPyWalrus:&lt;/code&gt; ensures its declaration (it can even appear in an &lt;code dir=&quot;auto&quot;&gt;if&lt;/code&gt; condition).&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;global-and-nonlocal-statements&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;global&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;nonlocal&lt;/code&gt; statements&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Python is one of the rare languages where a function can explicitly opt out of local scoping:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;global&lt;/span&gt;&lt;span&gt; x      &lt;/span&gt;&lt;span&gt;# `x` is the module-level x, not a local one&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;y &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;h&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;nonlocal&lt;/span&gt;&lt;span&gt; y    &lt;/span&gt;&lt;span&gt;# `y` is the `y` of `g`, not a new local&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;y &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;These two statements redirect resolution &lt;em&gt;away from the current scope&lt;/em&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a &lt;code dir=&quot;auto&quot;&gt;global x&lt;/code&gt; means: “in this scope, &lt;code dir=&quot;auto&quot;&gt;x&lt;/code&gt; is the module-scope &lt;code dir=&quot;auto&quot;&gt;x&lt;/code&gt;”. Writes here target the global declaration, they must not create a new local declaration.&lt;/li&gt;
&lt;li&gt;a &lt;code dir=&quot;auto&quot;&gt;nonlocal x&lt;/code&gt; means: “&lt;code dir=&quot;auto&quot;&gt;x&lt;/code&gt; is the variable of the nearest enclosing function that defines it”. It is similar to &lt;code dir=&quot;auto&quot;&gt;global&lt;/code&gt; but with a different target scope.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the model, a &lt;code dir=&quot;auto&quot;&gt;FASTPyGlobalStatement&lt;/code&gt; (resp. &lt;code dir=&quot;auto&quot;&gt;FASTPyNonlocalStatement&lt;/code&gt;) contains a collection of &lt;code dir=&quot;auto&quot;&gt;variables&lt;/code&gt;, and each &lt;code dir=&quot;auto&quot;&gt;FASTPyVariable&lt;/code&gt; keeps the inverse &lt;code dir=&quot;auto&quot;&gt;parentGlobalStatement&lt;/code&gt; / &lt;code dir=&quot;auto&quot;&gt;parentNonlocalStatement&lt;/code&gt; pointer. That is what the visitor checks in &lt;code dir=&quot;auto&quot;&gt;FASTPythonLocalResolverVisitor&gt;&gt;#visitFASTPyVariable:&lt;/code&gt; — when visiting a variable that is the target of one of these statements, we change &lt;strong&gt;which scope the write will land in&lt;/strong&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;visitFASTPyVariable:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aVariable&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;We handle two specific cases here.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- global: the variables impacted should act as if they were in the&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;       &lt;/span&gt;&lt;/span&gt;&lt;span&gt;global scope. I ensure the variable is in the bottom scope and add&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;       &lt;/span&gt;&lt;/span&gt;&lt;span&gt;a copy in the current scope (so that if we assign it, it goes in&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;       &lt;/span&gt;&lt;/span&gt;&lt;span&gt;the global and does not create a new local).&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- nonlocal: the variables impacted should act as if they were in the&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;       &lt;/span&gt;&lt;/span&gt;&lt;span&gt;first parent scope defining the variable.&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;aVariable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;parentGlobalStatement&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifNotNil:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;namesContext&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;top&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;at:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aVariable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;localDeclarationName&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;ifAbsentPut:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;ensureDeclarationOf:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aVariable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;localDeclarationName&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;declaration:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aVariable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;in:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;namesContext&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;last&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;aVariable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;parentNonlocalStatement&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifNotNil:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;namesContext&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;allButFirst&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;detect:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;includesKey:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aVariable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;localDeclarationName&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;ifFound:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;namesContext&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;top&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;at:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aVariable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;localDeclarationName&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;put:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;at:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aVariable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;localDeclarationName&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;ifNone:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;error:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;Non local statement points a variable that was never defined.&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;super &lt;/span&gt;&lt;span&gt;visitFASTPyVariable:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aVariable&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Let’s unpack the two branches:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;global&lt;/code&gt;&lt;/strong&gt; — we want a write &lt;code dir=&quot;auto&quot;&gt;x = 2&lt;/code&gt; inside the function to target the &lt;em&gt;module-level&lt;/em&gt; &lt;code dir=&quot;auto&quot;&gt;x&lt;/code&gt;. So we look at the &lt;strong&gt;bottom&lt;/strong&gt; scope (&lt;code dir=&quot;auto&quot;&gt;namesContext last&lt;/code&gt;, the module scope) and, if &lt;code dir=&quot;auto&quot;&gt;x&lt;/code&gt; is not there yet, we &lt;em&gt;declare it&lt;/em&gt; there with the current writing variable as its declaration. Then we &lt;strong&gt;copy a reference into the top scope&lt;/strong&gt; (&lt;code dir=&quot;auto&quot;&gt;namesContext top&lt;/code&gt;). From then on, any write in this scope simply finds &lt;code dir=&quot;auto&quot;&gt;x&lt;/code&gt; present in the top scope — &lt;code dir=&quot;auto&quot;&gt;ensureDeclarationOf:&lt;/code&gt; sees the same kind (&lt;code dir=&quot;auto&quot;&gt;#variable&lt;/code&gt; = &lt;code dir=&quot;auto&quot;&gt;#variable&lt;/code&gt;) and keeps the same declaration, so no new local is created and the write silently targets the global one. The copy trick makes the subsequent writes “resolve” without us having to special-case every write site.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;nonlocal&lt;/code&gt;&lt;/strong&gt; — the target scope is not the module but the &lt;em&gt;nearest enclosing function that already defines the name&lt;/em&gt;. So we scan &lt;code dir=&quot;auto&quot;&gt;namesContext allButFirst&lt;/code&gt; (everything except the bottom scope) and re-bind &lt;code dir=&quot;auto&quot;&gt;x&lt;/code&gt; in the top scope to the existing declaration found there. If no enclosing scope defines the name, this is a Python error (&lt;code dir=&quot;auto&quot;&gt;SyntaxError&lt;/code&gt; at compile time in real Python), so we raise an error too.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Both branches rely on a nice property of our data structure: &lt;strong&gt;the top entry of the stack is always the current scope&lt;/strong&gt;, and putting a &lt;em&gt;reference&lt;/em&gt; to an existing declaration (rather than a fresh node) in the current scope is exactly what redirects future uses.&lt;/p&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h2 id=&quot;shadowing-in-python&quot;&gt;Shadowing in Python&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Shadowing is another direct consequence of “no declarations”: in Python, &lt;em&gt;anything named can shadow anything named, in the same scope&lt;/em&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;              &lt;/span&gt;&lt;span&gt;# Declaration 1: variable&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; os &lt;/span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; x   &lt;/span&gt;&lt;span&gt;# Declaration 2: import (shadows Declaration 1)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt;:           &lt;/span&gt;&lt;span&gt;# Declaration 3: function (shadows Declaration 2)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;pass&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;)           &lt;/span&gt;&lt;span&gt;# links to Declaration 3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;the-rule-we-implemented&quot;&gt;The rule we implemented&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;In &lt;code dir=&quot;auto&quot;&gt;ensureDeclarationOf:&lt;/code&gt; (see &lt;a href=&quot;#the-core-operations&quot;&gt;core operations&lt;/a&gt;), when a name is &lt;strong&gt;re-declared&lt;/strong&gt; in the same scope, the resolver does not decide based on types (there are none) but on &lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;localResolverKind&lt;/code&gt;&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;if the new entity has the &lt;strong&gt;same kind&lt;/strong&gt; (e.g. re-assigning a variable): we keep the &lt;strong&gt;same declaration&lt;/strong&gt; and do nothing special. Two &lt;code dir=&quot;auto&quot;&gt;x = ...&lt;/code&gt; in a row share one declaration. (This is why &lt;code dir=&quot;auto&quot;&gt;ensureLocalUses&lt;/code&gt; initializes the uses instead of resetting them: several nodes can be declarations of one shared declaration.)&lt;/li&gt;
&lt;li&gt;if the kind is &lt;strong&gt;different&lt;/strong&gt; (a variable shadowed by an import or a function): we create a &lt;strong&gt;new declaration&lt;/strong&gt;, and link the two declarations together.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;localResolverKind&lt;/code&gt; is not used anywhere else in the resolver — it exists &lt;em&gt;only&lt;/em&gt; to drive this decision. Each node kind that can act as a declaration returns its kind, and the base FAST project provides no default because it is purely language-specific:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPyIdentifier          &gt;&gt; &lt;/span&gt;&lt;span&gt;localResolverKind&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#variable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPyParameter           &gt;&gt; &lt;/span&gt;&lt;span&gt;localResolverKind&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#variable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;&quot;can be reassigned&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPyWalrus              &gt;&gt; &lt;/span&gt;&lt;span&gt;localResolverKind&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#variable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPyAttributeAccess     &gt;&gt; &lt;/span&gt;&lt;span&gt;localResolverKind&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#variable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPySubscript           &gt;&gt; &lt;/span&gt;&lt;span&gt;localResolverKind&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#subscript&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPyFunctionDefinition  &gt;&gt; &lt;/span&gt;&lt;span&gt;localResolverKind&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#function&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPyMethodDefinition    &gt;&gt; &lt;/span&gt;&lt;span&gt;localResolverKind&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#method&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPyImport              &gt;&gt; &lt;/span&gt;&lt;span&gt;localResolverKind&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Two subtleties we hit:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Parameters are &lt;code dir=&quot;auto&quot;&gt;#variable&lt;/code&gt;&lt;/strong&gt;, not a dedicated kind, because they can be reassigned inside the body: &lt;code dir=&quot;auto&quot;&gt;def f(x): x = 2&lt;/code&gt; must &lt;em&gt;share&lt;/em&gt; the declaration with the parameter, not shadow it.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;FASTPyEntity&gt;&gt;localResolverKind&lt;/code&gt; raises an error by default, which catches any node kind that is used as a declaration without having declared its kind — a cheap safety net while extending the metamodel.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;the-shadowing-api&quot;&gt;The shadowing API&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;To make shadowing queryable, two back-links were added on the declarations (&lt;code dir=&quot;auto&quot;&gt;FASTPyEntity&lt;/code&gt;, in &lt;code dir=&quot;auto&quot;&gt;FAST-Python-Model&lt;/code&gt;, generated via the metamodel generator):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;declaration shadowing&lt;/code&gt; — returns the declaration &lt;strong&gt;it&lt;/strong&gt; shadows, or &lt;code dir=&quot;auto&quot;&gt;nil&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;declaration shadowedBy&lt;/code&gt; — returns the declaration that &lt;strong&gt;shadows it&lt;/strong&gt;, or &lt;code dir=&quot;auto&quot;&gt;nil&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Together they form a linked list from the first declaration to the most recent one. Each declaration keeps its &lt;strong&gt;own&lt;/strong&gt; &lt;code dir=&quot;auto&quot;&gt;localUses&lt;/code&gt; (the set of entities that resolve to &lt;em&gt;it&lt;/em&gt;, not to its successors), and usages always resolve to the most recent declaration.&lt;/p&gt;
&lt;p&gt;Going back to the example:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;varDecl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;module&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;statements&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;first&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;left&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;FASTPyVariable&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;importStmt&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;module&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;statements&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;second&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;       &lt;/span&gt;&lt;span&gt;&quot;FASTPyImportFromStatement&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;funcDecl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;module&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;statements&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;third&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;&quot;FASTPyFunctionDefinition&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;varDecl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;shadowedBy&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;=&gt; FASTPyImportFromStatement&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;importStmt&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;shadowedBy&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;&quot;=&gt; FASTPyFunctionDefinition&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;importStmt&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;shadowing&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;&quot;=&gt; FASTPyVariable&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;funcDecl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;shadowing&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;=&gt; FASTPyImportFromStatement&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;varDecl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;localUses&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;&quot;1  (just the assignment)&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;importStmt&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;localUses&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;1  (just the import)&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;funcDecl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;localUses&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;2  (the definition + print(x))&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;a-caution-about-same-kind&quot;&gt;A caution about “same kind”&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Same-kind re-declaration shares the declaration, which also means &lt;strong&gt;shadowing’s chain and local uses are independent of the SSA versioning&lt;/strong&gt;: if you need to know &lt;em&gt;which&lt;/em&gt; assignment impacts a particular use, local resolution is not enough — combine it with the &lt;a href=&quot;https://github.com/moosetechnology/FAST-Python/blob/main/resources/doc/analysis.md#static-single-assignment-ssa&quot;&gt;SSA pass&lt;/a&gt; (it produces one version per assignment). The two analyses are designed to be composed in this pipeline order: &lt;strong&gt;Local resolution → CFG → SSA&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h2 id=&quot;known-limits-and-what-is-left-to-do&quot;&gt;Known limits and what is left to do&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;We implemented local resolution for Python, but we focused on &lt;strong&gt;variables&lt;/strong&gt; first, because that is what the CFG/SSA and the reachability analyses needed. Functions, methods and imports are handled in the scope bookkeeping (&lt;code dir=&quot;auto&quot;&gt;localResolverKind&lt;/code&gt;, reordering in the visitor), but if your mission is a &lt;em&gt;complete&lt;/em&gt; Python symbol table, expect more work there (call graph resolution, &lt;code dir=&quot;auto&quot;&gt;self&lt;/code&gt;/class attributes, closures and bound variables…).&lt;/p&gt;
&lt;p&gt;Specific known weaknesses (documented in &lt;a href=&quot;https://github.com/moosetechnology/FAST-Python/blob/main/resources/doc/analysis.md#limitations-of-local-resolver-and-ssa&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;analysis.md&lt;/code&gt; → Limitations&lt;/a&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Attribute access chains&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;x.y.z = 3; a = x.y; print(a.z)&lt;/code&gt; — &lt;code dir=&quot;auto&quot;&gt;a.z&lt;/code&gt; should resolve to &lt;code dir=&quot;auto&quot;&gt;x.y.z&lt;/code&gt;, but it does not (only the source code of the attribute access is used as the name).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subscripts are compared by source code&lt;/strong&gt;: &lt;code dir=&quot;auto&quot;&gt;y[x]&lt;/code&gt; with different &lt;code dir=&quot;auto&quot;&gt;x&lt;/code&gt; values are conflated; &lt;code dir=&quot;auto&quot;&gt;x[0:4]&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;x[:4]&lt;/code&gt; (semantically equal) are seen as different. Matching the &lt;em&gt;expression&lt;/em&gt; instead of the string would fix it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Instance variables&lt;/strong&gt; (&lt;code dir=&quot;auto&quot;&gt;self.x&lt;/code&gt;) cannot be handled correctly without knowing the order in which methods are invoked.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Python 2 scoping&lt;/strong&gt; is not supported (comprehension variables leak in Python 2; we implement Python 3).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code dir=&quot;auto&quot;&gt;global&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;nonlocal&lt;/code&gt;&lt;/strong&gt; are handled, but &lt;code dir=&quot;auto&quot;&gt;nonlocal&lt;/code&gt; errors out if the variable was never defined in an enclosing scope.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also, one of the future step zould be to make some parts, such as the context stack, generic and push it to FAST so that it can be reused in other FAST projects.&lt;/p&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h2 id=&quot;quick-start&quot;&gt;Quick start&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&quot;Import&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FASTPythonImporter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;parseFile:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFile&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&quot;Resolve&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPythonLocalResolverVisitor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;resolve:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;module&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&quot;Query&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;allFunctionDefinitions&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;first&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;localDeclaration&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;a FASTPyFunctionDefinition&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The recommended pipeline for analysis:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FASTPythonImporter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;parseFile:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFile&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPythonLocalResolverVisitor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;resolve:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;module&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;allFunctionDefinitions&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;first&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cfg&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;                          &lt;/span&gt;&lt;span&gt;&quot;CFG&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPythonSSAVisitor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;resolve:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;allFunctionDefinitions&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;first&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;SSA (after resolution)&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The local resolver and SSA require &lt;strong&gt;Python 3&lt;/strong&gt; scoping.&lt;/p&gt;
&lt;hr&gt;
&lt;div&gt;&lt;h2 id=&quot;advice-for-implementing-it-in-your-own-fast-project&quot;&gt;Advice for implementing it in your own FAST project&lt;/h2&gt;&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Use the generated visitor, override &lt;code dir=&quot;auto&quot;&gt;visitX:&lt;/code&gt; selectively.&lt;/strong&gt; You rarely need to reorder everything — only where the metamodel order differs from the &lt;em&gt;declaration-before-use&lt;/em&gt; order (&lt;code dir=&quot;auto&quot;&gt;if&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;for&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;while&lt;/code&gt;, functions, comprehensions).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Model a scope stack explicitly.&lt;/strong&gt; One &lt;code dir=&quot;auto&quot;&gt;Stack&lt;/code&gt; of &lt;code dir=&quot;auto&quot;&gt;Dictionary&lt;/code&gt;s was enough for the whole algorithm. Wrap “new scope” sites in a &lt;code dir=&quot;auto&quot;&gt;useNewScopeDuring:&lt;/code&gt;/[ensure: pop] pair so the stack is popped even on error.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Make “what declares a name” explicit and language-aware.&lt;/strong&gt; For Python: write access declares; read access binds; &lt;code dir=&quot;auto&quot;&gt;for&lt;/code&gt; target declares in the enclosing scope; comprehensions open a scope; &lt;code dir=&quot;auto&quot;&gt;global&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;nonlocal&lt;/code&gt; redirect.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Add a &lt;code dir=&quot;auto&quot;&gt;localDeclarationName&lt;/code&gt; per node kind&lt;/strong&gt; (it is &lt;code dir=&quot;auto&quot;&gt;sourceCode&lt;/code&gt; for attribute accesses/subscripts, the identifier name otherwise) — do not hard-code “the name is the text” everywhere.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Add a &lt;code dir=&quot;auto&quot;&gt;localResolverKind&lt;/code&gt; and use it to drive shadowing.&lt;/strong&gt; It made the Java-free, type-free Python shadowing tractable and gave us a cheap way to keep-or-split declarations.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reset your attributes before re-resolving.&lt;/strong&gt; We flush &lt;code dir=&quot;auto&quot;&gt;localDeclaration&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;localUses&lt;/code&gt; on all contained entities at the start of &lt;code dir=&quot;auto&quot;&gt;resolve:&lt;/code&gt; so the resolver is idempotent on a model.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;FAST-Python&lt;/code&gt; sources you will want to look at: &lt;code dir=&quot;auto&quot;&gt;FASTPythonLocalResolverVisitor&lt;/code&gt;, the &lt;code dir=&quot;auto&quot;&gt;localResolverKind&lt;/code&gt;/&lt;code dir=&quot;auto&quot;&gt;localDeclarationName&lt;/code&gt; extensions in &lt;code dir=&quot;auto&quot;&gt;FAST-Python-Tools&lt;/code&gt;.&lt;/p&gt;</content:encoded><category>FAST</category><category>Python</category></item><item><title>Mixing up analysis of Project Architecture (Famix) and its history (Mining Software Repository)</title><link>https://modularmoose.org/blog/2026-08-27-msr-and-famix/</link><guid isPermaLink="true">https://modularmoose.org/blog/2026-08-27-msr-and-famix/</guid><description>Combine the architecture of a project (Famix) with its history (Mining Software Repositories).</description><pubDate>Thu, 27 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Famix is the meta-model family of Moose allowing one to analyse the dependencies of a project and its global architecture.
But sometimes, you want more, you want to see what are the part of the code that are modified most, are critical, etc.
It is for instance what people do when using Sonar, Coverage analysis, and so on.&lt;/p&gt;
&lt;p&gt;To explore the history of existing projects, Mining Software Repositories (MSR) is the way to go.
Moose also includes a set of tools to explore the history of a project, and to combine it with the Famix analysis.
The project is named GitProjectHealth, and the full documentation is available &lt;a href=&quot;https://modularmoose.org/users/git-project-health/getting-started-with-gitproject-health/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;But let’s today perform an example.
I have this nice HR application that I want to investigate.
It is large, and I want to retrieve information between the architecture and the history of the project.&lt;/p&gt;
&lt;p&gt;So let’s do a step by step blog about this story.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;creating-the-famix-model&quot;&gt;Creating the Famix model&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;I am working with Moose12. But this story should last for future version &lt;em&gt;(I mean, I don’t know how long, but it should not change a lot)&lt;/em&gt;
First, I clone the project, and then, I install its dependency with maven &lt;code dir=&quot;auto&quot;&gt;mvn install&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Then, I build a nice model using the docker version of VerveineJ.&lt;/p&gt;
&lt;aside aria-label=&quot;About VerveineJ&quot;&gt;&lt;p aria-hidden=&quot;true&quot;&gt;About VerveineJ&lt;/p&gt;&lt;div&gt;&lt;p&gt;VerveineJ is a java Project that convert Java code into a json that serialize the FamixModel that can be used by Moose.&lt;/p&gt;&lt;/div&gt;&lt;/aside&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-e&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;JAVA_XMX=-Xmx16G&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-v&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/path/to/hr:/src&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-v&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/path/to/.m2/repository:/dependency&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ghcr.io/evref-bl/verveinej:v4.2.6&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-anchor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;assoc&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-alllocals&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-format&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;json&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;I use the version &lt;code dir=&quot;auto&quot;&gt;4.2.6&lt;/code&gt; of VerveineJ, because I am with Moose12, but don’t hesitate to use the latest version of VerveineJ if you are with a more recent version of Moose.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Then, I load the model in Moose, and I can start to explore the architecture of the project.
To load the model, I simply drag and drop the json file in Moose, and then I can start to explore the model.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;retrieving-the-history-of-the-project&quot;&gt;Retrieving the history of the project&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;To retrieve the history of the project, I use the GitProjectHealth tool.
This project is not included in the Moose distribution by default, but you can download it by executing the following command in a Moose playground:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Metacello&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;repository:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;github://moosetechnology/GitProjectHealth:main/src&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;baseline:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;GitLabHealth&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;onConflict:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;ex&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;ex&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;useIncoming&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;onUpgrade:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;ex&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;ex&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;useIncoming&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;onDowngrade:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;ex&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;ex&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;useLoaded&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;load&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Then, because it is a large HR application, I will perform the retrieving of the history locally using git.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;rhModel&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GLHModel&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;repository&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GLHRepository&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;cacheAt:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#localImporterReference&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;put:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;/path/to/hr&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;asFileReference&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;yourself&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;project&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GLHProject&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;project&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;repository:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;repository&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;rhModel&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;add:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;repository&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;rhModel&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;add:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;project&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;localImporter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GitLocalModelImporter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;localImporter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;withFiles:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;localImporter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;withCommitDiffs:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;localImporter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;withDiffRanges:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;localImporter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;glhModel:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rhModel&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;localImporter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;withCommitsSince:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;30&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;years&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;localImporter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;importRepository:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;repository&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;rhModel&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;flush&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;rhModel&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;entities&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;do:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#flush&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;You’ll notice several things in the code above.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I created a fake project and repository to store the history of the project. This is to help the local importer and might be improved.&lt;/li&gt;
&lt;li&gt;I use the &lt;code dir=&quot;auto&quot;&gt;withFiles&lt;/code&gt; option to retrieve the files of the project, and the &lt;code dir=&quot;auto&quot;&gt;withCommitDiffs&lt;/code&gt; option to retrieve the diffs of the commits. The &lt;code dir=&quot;auto&quot;&gt;withDiffRanges&lt;/code&gt; option is set to false because I don’t need it for now.&lt;/li&gt;
&lt;li&gt;I use the &lt;code dir=&quot;auto&quot;&gt;withCommitsSince: 30 years&lt;/code&gt; option to retrieve all the commits of the project. You can change this value to retrieve only the last commits if you want.&lt;/li&gt;
&lt;li&gt;I use the &lt;code dir=&quot;auto&quot;&gt;flush&lt;/code&gt; method to remove cache that is computed by the local importer, this is for storage efficiency.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once it is done, I have the full history of the project, but not connected to the exsiting model of the code.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;connecting-the-models&quot;&gt;Connecting the models&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;We want now to connect the GitProjectHealth model, with the Famix model.
There is a tool dedicated for this usage in GitProjectHealth, it is called &lt;code dir=&quot;auto&quot;&gt;GPCGitToFamixConnector&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The project links the types of the Famix model with the files retrieved by the GitProjectHealth model based on the files path.
To use it, simply execute the following code:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;GPCGitToFamixConnector&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;famixModel:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;myFamixModel&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;glhProject:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;project&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;connect&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;it is possible that &lt;code dir=&quot;auto&quot;&gt;GPCGitToFamixConnector&lt;/code&gt; is not loaded in your Moose image. It is is the case, load the missing package from Iceberg, or check in the baseline of GitProjectHealth if it is included in the version you are using, there should be a group named “Famix”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And, that’s it… yeah, it is quite easy to connect the two models, and now you can explore the history of the project in the context of its architecture.&lt;/p&gt;
&lt;p&gt;You want to search for the types the most modified? One classic Moose query will do the job:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;myFamixModel&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;allUsing:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FamixTType)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sorted:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;appliedDiffs&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;descending&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;</content:encoded><category>Mining Software Repositories</category><category>Famix-tools</category><category>story</category></item><item><title>Building an ownership cartography of a system - Part 2</title><link>https://modularmoose.org/blog/2026-08-11-building-an-ownership-cartography-of-a-system-part2/</link><guid isPermaLink="true">https://modularmoose.org/blog/2026-08-11-building-an-ownership-cartography-of-a-system-part2/</guid><description>Visualize the ownership of a system with a Distribution Map.</description><pubDate>Thu, 13 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;When you share your work with others, such as the previous blog post, you can get feedback and suggestions for improvement.
And this is exactly what happened.&lt;/p&gt;
&lt;aside aria-label=&quot; &quot;&gt;&lt;p aria-hidden=&quot;true&quot;&gt; &lt;/p&gt;&lt;div&gt;&lt;blockquote&gt;
&lt;p&gt;“The last step I wanted to investigate is to visualize the ownership of a system. I did not create a visualisation dedicated to this point yet.”&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;You mean something like the Distribution Map? 😉&lt;/p&gt;&lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;And by Distribution Map, we are talking about a &lt;a href=&quot;https://www.researchgate.net/profile/Stephane-Ducasse/publication/221308136_Distribution_Map/links/02e7e51f0feed80eae000000/Distribution-Map.pdf&quot;&gt;research paper accepted at ICSM 2006&lt;/a&gt;
So, let’s not reinvent the wheel anymore and look at how to use the already existing Distribution Map in Moose to visualize the ownership of a system.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;one-color-for-each-developer&quot;&gt;One color for each developer&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The first visualisation that comes to mind is to use one color for each developer.
Using the Degree-of-Authorship (DOA) formula, we can compute the ownership of each file and retrieve the main developer for each file.&lt;/p&gt;
&lt;p&gt;In moose, we can then create a tag that will associate a color to each developer and then use this tag to color the files in the system.
We assign a tag to each file that corresponds to the main developer of the file.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;((&lt;/span&gt;&lt;span&gt;glhModel&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;allWithSubTypesOf:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GLHFile)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;select:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;file&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;file&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;diffs&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt; ~= &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;])&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;do:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;file&lt;/span&gt;&lt;/span&gt;&lt;span&gt; |  &lt;/span&gt;&lt;span&gt;file&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tagWithName:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;((&lt;/span&gt;&lt;span&gt;file&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;degreeOfAuthorship&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;keyAtValue:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1.0&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;We first search for all the files that have been modified, then we compute the degreeofAuthorship for every possible user, we select the one with the best score, which is 1, and we create a tag with the author name.
Once the tag is created for every file, it is possible to propagate the files to the Distribution Map.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;propagate-to-distribution-map&quot;&gt;Propagate to Distribution Map&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;To propagate the files to the distribution, we first retrieve the files in our model.
Then, we get the parent folder of the files.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;appsFolder&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;glhModel&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;allWithSubTypesOf:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GLHFileDirectory)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;detect:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;fi&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;fi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;src&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;files&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;appsFolder&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;allToScope:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GLHFileBlob).&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&quot;Find parent folder&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;folders&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;files&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;collect:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;file&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;file&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;directoryOwner&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;as:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Set).&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;folders&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Based on the parent folders, the Moose Distribution Map will be able to recalculate the children, and so the files of interest.
We select the &lt;code dir=&quot;auto&quot;&gt;folders&lt;/code&gt; variable and propagate with &lt;kbd&gt;Cmd&lt;/kbd&gt; + &lt;kbd&gt;Shift&lt;/kbd&gt; + &lt;kbd&gt;M&lt;/kbd&gt;, &lt;kbd&gt;Cmd&lt;/kbd&gt; + &lt;kbd&gt;Shift&lt;/kbd&gt; + &lt;kbd&gt;P&lt;/kbd&gt;.&lt;/p&gt;
&lt;p&gt;Then, we open the Distribution map from the Moose Menu.&lt;/p&gt;
&lt;p&gt;We first get a visualisation without any color.
So, in the settings of the visualisation, we select the tags to display.
We select every authors and get the last visualisation.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://modularmoose.org/_astro/visu.C91eT8JK_1Pwn6W.webp&quot; alt=&quot;visu&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1374&quot; height=&quot;1622&quot;&gt;&lt;/p&gt;
&lt;p&gt;Again, the visualisation well presents the different packages and the one with major author.
The gray square corresponds to file less modified in the system the last two years.&lt;/p&gt;</content:encoded><category>Mining Software Repositories</category></item><item><title>Building an ownership cartography of a system</title><link>https://modularmoose.org/blog/2026-08-11-building-an-ownership-cartography-of-a-system/</link><guid isPermaLink="true">https://modularmoose.org/blog/2026-08-11-building-an-ownership-cartography-of-a-system/</guid><description>Use git history and Moose to find out who owns which part of a system.</description><pubDate>Tue, 11 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;h2 id=&quot;context&quot;&gt;Context&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;When managing a software system, it is important to know who is responsible for which part of the system.
This information can be useful for various reasons, such as identifying potential bottlenecks, understanding the impact of changes, and improving collaboration among team members.&lt;/p&gt;
&lt;p&gt;One major threat could, for example, come from a developer leaving the team.
This is often referred to as the “bus factor” or “truck factor”.
But how to detect such a situation?&lt;/p&gt;
&lt;p&gt;Research have shown that the ownership of a system can be inferred from its version control history.
To do so, one approach is to first investigate the ownership of each file.&lt;/p&gt;
&lt;p&gt;Two nice papers, not from the Moose community, are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://homepages.dcc.ufmg.br/~mtov/pub/2019-sqj.pdf&quot;&gt;Algorithms for Estimating Truck Factors: A Comparative study&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://arxiv.org/pdf/1604.06766&quot;&gt;A Novel Approach for Estimating Truck Factors&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/aserg-ufmg/Truck-Factor&quot;&gt;Truck-Factor tool&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;computing-the-ownership-of-a-file&quot;&gt;Computing the ownership of a file&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Looking at the research paper, we can find a formula that can help build a first version of ownership.
It consists for each file of a git repository to compute a degree of authorship for each potential author using this formula.&lt;/p&gt;
&lt;p&gt;Given a file &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; with path &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f_p&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, the degree-of-authorship of a developer &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;d&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; whose Git user has been mapped to &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;m_d&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;m&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is given by.&lt;/p&gt;
&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/msub&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/msub&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;3.293&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;1.098&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/msub&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/msub&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;0.164&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;mi&gt;L&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/msub&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/msub&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;0.321&lt;/mn&gt;&lt;mo&gt;×&lt;/mo&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/msub&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/msub&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;DOA(m_d, f_p) = 3.293 + 1.098 × FA(m_d, f_p) + 0.164× DL(m_d, f_p)−0.321 ×ln(1 + AC (m_d, f_p))&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;D&lt;/span&gt;&lt;span&gt;O&lt;/span&gt;&lt;span&gt;A&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&lt;span&gt;m&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;3.293&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;1.098&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;×&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;F&lt;/span&gt;&lt;span&gt;A&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&lt;span&gt;m&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;0.164&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;×&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;D&lt;/span&gt;&lt;span&gt;L&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&lt;span&gt;m&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;−&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;0.321&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;×&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;l&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;A&lt;/span&gt;&lt;span&gt;C&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&lt;span&gt;m&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;With the following definitions:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;DOA depends on three factors: (i) first authorship (&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;FA&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;F&lt;/span&gt;&lt;span&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;): if &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;m_d&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;m&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; originally created &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;FA&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;F&lt;/span&gt;&lt;span&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is 1; otherwise it is 0; (ii) number of deliveries (&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;mi&gt;L&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;DL&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;D&lt;/span&gt;&lt;span&gt;L&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;): number of changes in &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; made by &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;m_d&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;m&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;; and (iii) number of acceptances (&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;AC&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;A&lt;/span&gt;&lt;span&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;): number of changes in &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;f&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; made by any developer, except &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;m_d&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;m&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Looking at the source code of the Truck-Factor tool, we can see thet &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;mi&gt;L&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;DL&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;D&lt;/span&gt;&lt;span&gt;L&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; corresponds to a commit that modifies a file.
The file &lt;a href=&quot;https://github.com/aserg-ufmg/Truck-Factor/blob/614600ed6b36bb8f452bc6eab7c9b95320f5d7be/gittruckfactor/src/aserg/gtf/task/DOACalculator.java#L104&quot;&gt;can be added, modified, and renamed&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/msub&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/msub&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;AC (m_d, f_p)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;A&lt;/span&gt;&lt;span&gt;C&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&lt;span&gt;m&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; is computed by the total number of modifications of a file minus the number of modifications made by the developer &lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/msub&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;m_d&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;m&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;moose-implementation&quot;&gt;Moose Implementation&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Moose comes with the &lt;a href=&quot;https://modularmoose.org/users/git-project-health/getting-started-with-gitproject-health&quot;&gt;GitProject Health&lt;/a&gt; project to represent a Git repository and analyze its history.
So, I wanted to implement the DOA formula in Moose.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;making-it-faster&quot;&gt;Making it faster&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;One concern is that GitProject Health is firstly made to analyze Git Social Platform and not only git repository with the truck factor in mind.
Thus, it is not optimized for this use case.&lt;/p&gt;
&lt;p&gt;The major concern comes when loading the model that rely on several calls to the Git Platform API.
In order to avoid this, I decided to implement a companion importer named &lt;code dir=&quot;auto&quot;&gt;GitLocalModelImporter&lt;/code&gt; that can load a model from a local git repository.&lt;/p&gt;
&lt;p&gt;To go faster, it relies on the &lt;a href=&quot;https://github.com/pharo-vcs/libgit2-pharo-bindings&quot;&gt;FFI LibGit2&lt;/a&gt;.
This project includes a &lt;code dir=&quot;auto&quot;&gt;LGitRevwalk&lt;/code&gt;, a walker that can iterate over the commits of a git repository.
Thus, we can iterate over the commits and retrieve the files, the diffs, the commits, and the authors in a repository.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This version is still not optimized to compute truck factor, but it can be used to do lot more than just computing truck factor. It comes as a new classic importer for GitProject Health and so can be used side by side with other importers for optimization.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div&gt;&lt;h3 id=&quot;implementing-the-doa-formula&quot;&gt;Implementing the DOA formula&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;To implement the DOA formula, I created a simple but effective class named &lt;code dir=&quot;auto&quot;&gt;GLPDegreeOfAuthorshipAnalyzer&lt;/code&gt;.
This class is now part of the GitProject Health project set of metrics.
It reuses the exact same algorithm as the Truck-Factor tool to compute the degree of authorship for each file in a git repository.&lt;/p&gt;
&lt;p&gt;We note several additionnal considerations to compute the DOA formula.
These considerations are mention because they enable analysis of a project without considering the history of the project, which is long to consider.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The first authorship (&lt;span&gt;&lt;span&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;FA&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;F&lt;/span&gt;&lt;span&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;) is computed by looking at the first commit that added or modified a file to the repository.&lt;/li&gt;
&lt;li&gt;GitProject Health does not consider renaming of files &lt;em&gt;yet&lt;/em&gt;, so it does not consider file renaming.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Even though not considering rename can create issues, this work has been performed on an industrial project and considering renaming would not drastically change the results of the analysis.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;vizualizing-the-ownership-of-a-system&quot;&gt;Vizualizing the ownership of a system&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The last step I wanted to investigate is to visualize the ownership of a system.
I did not create a vizualization dedicated to this point yet.
But let’s investigate a running example for the &lt;a href=&quot;https://github.com/pharo-project/pharo&quot;&gt;pharo&lt;/a&gt; project.&lt;/p&gt;
&lt;p&gt;After cloning the project, I create a Moose image with the GitProject Health project installed.
Then, I load the pharo project.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;glhModel&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GLHModel&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;repository&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GLHRepository&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cacheAt:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#localImporterReference&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;put:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;/path/to/MSR/pharo&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;asFileReference&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;yourself&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;glhModel&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;add:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;repository&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;localImporter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GitLocalModelImporter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;localImporter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;withFiles:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;localImporter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;glhModel:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;glhModel&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&quot;I will import the last two years&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;localImporter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;withCommitsSince:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;years&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;localImporter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;importRepository:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;repository&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;After a possibly long execution, we get the repository loaded.
It is thus possible to investigate it using our tools.&lt;/p&gt;
&lt;p&gt;We want to build a cartography of the application to identify the coverage of files with an author.
To do so, I decided to build a TreeMap using the Roassal framework.&lt;/p&gt;
&lt;p&gt;First, I need to load the Roassal TreeMap support&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Metacello&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;baseline:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;Roassal&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;repository:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;github://pharo-graphics/Roassal:Pharo13&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;onConflictUseIncoming&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;load:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#( Full )&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Then, start the fun.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;a-quick-view-of-the-project&quot;&gt;A quick view of the project&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;We build a dictionary with the degree of authorship for everyfile.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;filesAuthorShip&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;((&lt;/span&gt;&lt;span&gt;glhModel&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;allWithSubTypesOf:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GLHFile)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;select:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;file&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;file&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;diffs&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt; ~= &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;])&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;collect:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;file&lt;/span&gt;&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;&quot;This uses our analyser behind the scene&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;file&lt;/span&gt;&lt;span&gt; -&gt; &lt;/span&gt;&lt;span&gt;file&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;degreeOfAuthorshipAuthors&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;as:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Dictionary.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;We look for the folder that is the root of the tree map, and we compute the max number of authorship that will be used for coloring the vizualisation.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;appsFolder&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;glhModel&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;allWithSubTypesOf:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GLHFileDirectory)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;detect:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;fi&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;fi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;src&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;max&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;filesAuthorShip&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;collect:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#sum&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;max&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Finally, we build the tree map.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;palette&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;RSQualitativeColorPalette&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;qualitative&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;set39&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;RSTreeMap&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;inset:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;asPoint&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;boxShape&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;borderColor:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Color&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;black&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;boxShape&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;borderWidth:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0.05&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;color&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;NSScale&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;linear&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;domain:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;max&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;range:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#( white red ).&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;b&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;leafWeight:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;explore:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;appsFolder&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nesting:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;directory&lt;/span&gt;&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;directory&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;files&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;select:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;isKindOf:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GLHFileDirectory)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;leaves:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;directory&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;directory&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;files&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;reject:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;isKindOf:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GLHFileDirectory&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;shapes&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;do:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;box&lt;/span&gt;&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;box&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;borderWidth:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;box&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;isSLeaf&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;ifTrue:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;box&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;color:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;color&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;scale:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;filesAuthorShip&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;at:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;box&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifPresent:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;dic&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;dic&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sum&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifAbsent:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]))&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;ifFalse:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;box&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;splitOn:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt; &gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifTrue:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                    &lt;/span&gt;&lt;span&gt;box&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;color:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;palette&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;scale:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;box&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;splitOn:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;second&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;shapes&lt;/span&gt;&lt;span&gt; @ &lt;/span&gt;&lt;span&gt;(RSPopup&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;text:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;[:&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;crlf&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;((&lt;/span&gt;&lt;span&gt;filesAuthorShip&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;at:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifPresent:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;dic&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;dic&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sum&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifAbsent:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;])&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;printString&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]).&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Using this script, we built a vizualisation with different color for each package, and a red scale for know packages.
It ouput the following image&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://modularmoose.org/_astro/pharo-ownership.Dqj9RLMC_26Iprx.webp&quot; alt=&quot;&amp;#x22;Result&amp;#x22;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1490&quot; height=&quot;1496&quot;&gt;&lt;/p&gt;
&lt;p&gt;Looking at the image we see that some package have author from the 2 last year modification whereas other were not modified at all.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;More than showing the Truck Factor, this vizualization highlights the code that have been updated by people that gain or conserve knowledge on the codebase.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;One improvment could be to highlight the core contributors.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;highlighting-the-core-contributors&quot;&gt;highlighting the core contributors&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;To highlight the core contributors, we first create a color palette for them.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;coreContributors&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;filesAuthorShip&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;values&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;flatCollect:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#keys&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;asSet&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;paletteContributor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;RSQualitativeColorPalette&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;qualitative&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;flatui120&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Then, we update the first &lt;code dir=&quot;auto&quot;&gt;b shapes&lt;/code&gt; statements by:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;shapes&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;do:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;box&lt;/span&gt;&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;box&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;borderWidth:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;box&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;isSLeaf&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;ifTrue:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;filesAuthorShip&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;at:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;box&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifPresent:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;dic&lt;/span&gt;&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;author&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;author&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;dic&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;associations&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sorted:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt; &gt; &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;])&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;first&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;key&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;box&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;color:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;paletteContributor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;scale:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;author&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;ifFalse:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;box&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;splitOn:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;box&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;color:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Color&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;white&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This attributes the color of the core contributors to each box.
We present below a final computed visualization that highlight one contributor who seems to became the expert of the Refactoring package.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://modularmoose.org/_astro/core-contributor.dTmpdekm_7kCzM.webp&quot; alt=&quot;Core Contributor&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2730&quot; height=&quot;1572&quot;&gt;&lt;/p&gt;</content:encoded><category>Mining Software Repositories</category></item><item><title>Improving the generation of visitors</title><link>https://modularmoose.org/blog/2026-05-20-improving-visitor-generator/</link><guid isPermaLink="true">https://modularmoose.org/blog/2026-05-20-improving-visitor-generator/</guid><description>How to use the visitor generator, the problems found while using it on FAST-Python, and their fixes.</description><pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;h2 id=&quot;context&quot;&gt;Context&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Recently, I needed to implement a feature in &lt;code dir=&quot;auto&quot;&gt;FAST-Python&lt;/code&gt; requiring a visitor for my metamodel. People knowing me knows that I if I can automatize a task to save time and to keep the code coherant with the model, I’ll go for it. Nicolas Anquetil and Clotilde Toullec recently started to implement a visitor generator, so I tried it. Since it was a POC, I encountered some problems.&lt;/p&gt;
&lt;p&gt;I’ll explain in this blog post how to use this visitor generator, what problems I encountered and the solutions I proposed.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;using-the-visitor-generator&quot;&gt;Using the visitor generator&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Once my changes will be integrated, using the visitor generator is as simple as adding one method on the class side of your generator. For example, in FAST-Python:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPythonMetamodelGenerator&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;&gt;&gt;&lt;/span&gt;&lt;span&gt;metamodelToolGenerators&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FamixVisitorGenerator&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This will tell the generator to also generate a visitor trait.&lt;/p&gt;
&lt;p&gt;It is possible to also customize the package in which the visitor is generated by overridin &lt;code dir=&quot;auto&quot;&gt;#packageNameForVisitor&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPythonMetamodelGenerator&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;&gt;&gt;&lt;/span&gt;&lt;span&gt;packageNameForVisitor&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;FAST-Python-Visitor&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;problems-i-faced&quot;&gt;Problems I faced&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;While using this visitor generator I faced a few problems.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;dependency-on-sub-metamodels&quot;&gt;Dependency on sub metamodels&lt;/h3&gt;&lt;/div&gt;
&lt;div&gt;&lt;h4 id=&quot;problem&quot;&gt;Problem&lt;/h4&gt;&lt;/div&gt;
&lt;p&gt;The first one I encountered is that &lt;code dir=&quot;auto&quot;&gt;FAST-Python&lt;/code&gt; is depending on &lt;code dir=&quot;auto&quot;&gt;FAST&lt;/code&gt; that is depending on &lt;code dir=&quot;auto&quot;&gt;Famix&lt;/code&gt; that is depending on &lt;code dir=&quot;auto&quot;&gt;MooseQuery&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In order to have the FAST-Python visitor working, all dependencies needed to have a visitor themselves which was not the case. So I had to generate a FAST visitor for example. I could do it since I am part of the moosetechnology organization, but this is a hassle.&lt;/p&gt;
&lt;div&gt;&lt;h4 id=&quot;solution&quot;&gt;Solution&lt;/h4&gt;&lt;/div&gt;
&lt;p&gt;The solution I found was to generate standalone visitors. Instead of using the visitors of the sub metamodels, now we generate a visitor containing the visit of all entities of the model &lt;em&gt;and&lt;/em&gt; the visit of the remote trait used in the model.&lt;/p&gt;
&lt;p&gt;This can seems like a lot of useless code at first, but it has two advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Visitors and now standalone&lt;/li&gt;
&lt;li&gt;This allow to customize the visit of remote traits for the language we are currently working on. This will be important for one of the other problems I encountered.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;infinit-loops-in-visitors&quot;&gt;Infinit loops in visitors&lt;/h3&gt;&lt;/div&gt;
&lt;div&gt;&lt;h4 id=&quot;problem-1&quot;&gt;Problem&lt;/h4&gt;&lt;/div&gt;
&lt;p&gt;The second problem I faced was that the generated visitor had infinit loops while I tried to use it. The reason is simple, when visiting an entity, we were visiting all its relations, but Moose is a cyclic graph since we have relations to the contained entities and relations to the containers of the entity.&lt;/p&gt;
&lt;div&gt;&lt;h4 id=&quot;solution-1&quot;&gt;Solution&lt;/h4&gt;&lt;/div&gt;
&lt;p&gt;Since most analysis that we are doing are “top down” (meaning that we start by the top level entities of our project and we visit their children) and we do not often need a “bottom up” visitor (for this we can just iterate on parents), I decided to exclude the visit of parent entities from the visit.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;double-visit-of-some-relations&quot;&gt;Double visit of some relations&lt;/h3&gt;&lt;/div&gt;
&lt;div&gt;&lt;h4 id=&quot;problem-2&quot;&gt;Problem&lt;/h4&gt;&lt;/div&gt;
&lt;p&gt;In some cases I noticed the we visited two times the same nodes. This is due to the fact that Famix model mix the usage of superclasses and traits. Here is a simple case to understant what is happening:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Double visit example&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1240&quot; height=&quot;549&quot; src=&quot;https://modularmoose.org/_astro/double-visit.drawio.Cj5WR6SR_17kHId.webp&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here we see that a &lt;code dir=&quot;auto&quot;&gt;FASTPyReturnStatement&lt;/code&gt; inherits from &lt;code dir=&quot;auto&quot;&gt;FASTPyStatement&lt;/code&gt;. This class is using &lt;code dir=&quot;auto&quot;&gt;FASTTStatement&lt;/code&gt;. &lt;code dir=&quot;auto&quot;&gt;FASTPyReturnStatement&lt;/code&gt; also uses the trait &lt;code dir=&quot;auto&quot;&gt;FASTPyReturnStatement&lt;/code&gt;, but this trait also uses &lt;code dir=&quot;auto&quot;&gt;FASTTStatement&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now when we visit &lt;code dir=&quot;auto&quot;&gt;FASTPyReturnStatement&lt;/code&gt;, we end up visiting two times &lt;code dir=&quot;auto&quot;&gt;FASTTStatement&lt;/code&gt;. Once via its superclass and once via its trait composition.&lt;/p&gt;
&lt;div&gt;&lt;h4 id=&quot;solution-2&quot;&gt;Solution&lt;/h4&gt;&lt;/div&gt;
&lt;p&gt;The solution I proposed is that when we visit a trait composition, we check the users of the trait and if some of them already visit the trait in their superclasses, we skip the visit of this relation.&lt;/p&gt;
&lt;p&gt;With this, &lt;code dir=&quot;auto&quot;&gt;#visitFASTPyReturnStatement&lt;/code&gt; in the context of FAST-Python become:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;visitFASTTReturnStatement:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTReturnStatement&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;generated&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;We should visit FASTTStatement but all its users in this language already visit it in their superclasses so we skip the call here.&quot;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitEntity:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTReturnStatement&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;expression&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;In some cases, we need to skip the visit for some entities, but not all of them. For example, with conditional statements. In that case we generate a method like this:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;visitFASTTConditionalStatement:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTConditionalStatement&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;generated&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;We do not visit all behaviorals because some classes already visit it in their superclasses in this language implementation. Visiting them here also would cause a double visit of this trait.&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FASTPyIfStatement&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FASTPyWhileStatement&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;includes:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTConditionalStatement&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;ifFalse:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;visitFASTTStatement:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTConditionalStatement&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitFASTTWithCondition:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTConditionalStatement&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This is possible only because we generate standalone visitors now.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;With those changes I’m hoping it will be easier to generate and use visitors with Famix. The big advantage is that if we do not need to touch the visitor by hand, it will follow all the evolutions of the metamodel.&lt;/p&gt;
&lt;p&gt;Have fun with this :)&lt;/p&gt;</content:encoded><category>infrastructure</category><category>famix-tools</category></item><item><title>Introducing Java initializers</title><link>https://modularmoose.org/blog/2026-02-17-initializers/</link><guid isPermaLink="true">https://modularmoose.org/blog/2026-02-17-initializers/</guid><description>The Famix metamodel evolves again</description><pubDate>Tue, 17 Feb 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In Java, we can define behavior that is executed exclusively at the initialization of an instance. For now, our metamodel represented these behaviors as methods. This evolution represents them as &lt;code dir=&quot;auto&quot;&gt;Initializers&lt;/code&gt;.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;what-are-initializers&quot;&gt;What are initializers?&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;We consider as initializers the following elements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Constructors: they are called when creating a new instance. When a constructor is called, if no explicit call is defined, it implicitly calls the default no-argument constructor, that calls the no-argument constructor in the superclass. We do not represent implicit constructors and these invocations.&lt;/li&gt;
&lt;li&gt;Initialization blocks: blocks that are executed when a new instance is created. They are copied by the Java compiler into each constructor and avoid code duplication. We do not represent this implicit invocation.&lt;/li&gt;
&lt;li&gt;In Famix: the &lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;Initializer&gt;&lt;/code&gt; method: we create a method to hold all attribute definitions in a type.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;why-do-we-change&quot;&gt;Why do we change?&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The main motivation for this change is to adapt the metamodel to the needs of building call graphs.
Call graphs must be able to create the implicit invocations described above and to distinguish between the 3 types of initializers.&lt;/p&gt;
&lt;p&gt;Another motivation is to differentiate between initializers and actual methods.
In analyses, we often need to focus on methods and initializers can add noise when treated as actual methods, especially the &lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;Initializer&gt;&lt;/code&gt; method.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;whats-changing&quot;&gt;What’s changing&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;We introduce &lt;code dir=&quot;auto&quot;&gt;FamixJavaInitializer&lt;/code&gt;, a subclass of &lt;code dir=&quot;auto&quot;&gt;FamixJavaMethod&lt;/code&gt;.
An &lt;code dir=&quot;auto&quot;&gt;Initiliazer&lt;/code&gt; has 2 properties:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;#isInitializationBlock&lt;/code&gt;: boolean, &lt;code dir=&quot;auto&quot;&gt;false&lt;/code&gt; by default.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;#isConstructor&lt;/code&gt;: boolean, derived. In java, a constructor is an initializer with the same name as its parent type, with no declared type (or &lt;code dir=&quot;auto&quot;&gt;void&lt;/code&gt; as declared type).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We do not merge all initializers as we did before, but we still merge similar initializers, that will always be called together.
In a Java model, a type (&lt;code dir=&quot;auto&quot;&gt;TWithMethods&lt;/code&gt;) can define a maximum of 4 initializers (besides constructors):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An instance initialization block, that is the merge of all instance initialization blocks.&lt;/li&gt;
&lt;li&gt;An instance-side &lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;Initializer&gt;&lt;/code&gt; method, similar to the one we created before.&lt;/li&gt;
&lt;li&gt;A static initialization block, merge of all static initialization blocks (&lt;code dir=&quot;auto&quot;&gt;isClassSide&lt;/code&gt;is true).&lt;/li&gt;
&lt;li&gt;A static &lt;code dir=&quot;auto&quot;&gt;&amp;#x3C;Initializer&gt;&lt;/code&gt;method (&lt;code dir=&quot;auto&quot;&gt;isClassSide&lt;/code&gt;is true) for static attributes definition.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When inspecting a Java model, initializers can now be found under &lt;code dir=&quot;auto&quot;&gt;Initializers&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;Model initializers&lt;/code&gt;.&lt;/p&gt;</content:encoded><category>meta-model</category></item><item><title>Speed up models creation: application to JSON/MSE parsing</title><link>https://modularmoose.org/blog/2025-11-18-speedup-import-json-mse/</link><guid isPermaLink="true">https://modularmoose.org/blog/2025-11-18-speedup-import-json-mse/</guid><description>How profiling a 330MB JSON import led to much faster model creation in Moose.</description><pubDate>Tue, 18 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;h2 id=&quot;context&quot;&gt;Context&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;In order to be able to work with Moose there is a prerequisite we cannot avoid: we need a model to analyze. This can be archieved in 2 principal ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Importing an existing JSON/MSE file containing a model&lt;/li&gt;
&lt;li&gt;Importing a model via a Moose importer such as the Pharo importer or Python importer&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While doing this, we create a lot of entities and set a lot of relations. But this can take some time. I found out that this time was even bigger than I anticipated while profiling a JSON import.&lt;/p&gt;
&lt;p&gt;Here is the result of the profiling of a JSON of 330MB on a Macbook pro M1 from 2023:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Image of a profiling&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;933&quot; height=&quot;1018&quot; src=&quot;https://modularmoose.org/_astro/profiler_full_before.CWk2NXFT_Z1ziVcQ.webp&quot;&gt;&lt;/p&gt;
&lt;p&gt;Form this profiling we can see that we spend 351sec for this import. We can find more information in this report:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Image of a profiling 2&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;746&quot; height=&quot;738&quot; src=&quot;https://modularmoose.org/_astro/profiler_2_before.BqghhSnI_svEDz.webp&quot;&gt;&lt;/p&gt;
&lt;p&gt;On this screenshot we can see some noise due to the fact that the profiler was not adapted to the new event listening loop of Pharo. But in the leaves we can also see that most of the time is spent in &lt;code dir=&quot;auto&quot;&gt;FMSlotMultivaluedLink&gt;&gt;#indexOf:startingAt:ifAbsent:&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This is used by a mecanism of all instance variables that are &lt;code dir=&quot;auto&quot;&gt;FMMany&lt;/code&gt; because those we do not want duplicated elements. Thus, we check if the collection contains the element before adding it.&lt;/p&gt;
&lt;p&gt;But during the import of a JSON file, we should have no duplicates making this check useless. This also explains why we spend so much time in this method: we always are in the worst case scenario: there is no element matching.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;the-optimization&quot;&gt;The optimization&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;In order to optimize the creation of a model when we know we will not create any duplicates, we can disable the check.&lt;/p&gt;
&lt;p&gt;For this, we can use a dynamic variable declaring that we should check for duplicated elements by default, but allowing to disable the check during the execution of some code.&lt;/p&gt;
&lt;aside aria-label=&quot;Note&quot;&gt;&lt;p aria-hidden=&quot;true&quot;&gt;Note&lt;/p&gt;&lt;div&gt;&lt;p&gt;If you do not know what is a Dynamic Variable you can check &lt;a href=&quot;https://github.com/pharo-open-documentation/pharo-wiki/blob/master/PharoProjects/DynamicVariables.md&quot;&gt;the pharo wiki&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&lt;/aside&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;DynamicVariable&lt;/span&gt;&lt;span&gt; &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span&gt;#FMShouldCheckForDuplicatedEntitiesInMultivalueLinks&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;slots:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;tag:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;Utilities&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;package:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;Fame-Core&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FMShouldCheckForDuplicatedEntitiesInMultivalueLinks&lt;/span&gt;&lt;span&gt;&gt;&gt;&lt;/span&gt;&lt;span&gt;#default&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;And now that we have the variable, we can use it:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FMSlotMultivalueLink&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;unsafeAdd:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;element&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;includes:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;element&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifFalse:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;uncheckUnsafeAdd:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;element&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;FMShouldCheckForDuplicatedEntitiesInMultivalueLinks&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;ifTrue:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;includes:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;element&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifFalse:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;uncheckUnsafeAdd:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;element&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;ifFalse:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;uncheckUnsafeAdd:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;element&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FMMultivalueLink&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;unsafeAdd:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;element&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;includes:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;element&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifFalse:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;uncheckUnsafeAdd:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;element&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;FMShouldCheckForDuplicatedEntitiesInMultivalueLinks&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;ifTrue:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;includes:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;element&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifFalse:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;uncheckUnsafeAdd:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;element&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;ifFalse:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;uncheckUnsafeAdd:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;element&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;And the last step is to disable the check during the MSE/JSON parsing:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FMMSEParser&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;basicRun&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Document.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;/span&gt;&lt;span&gt;atEnd&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifFalse:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;syntaxError&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;FMShouldCheckForDuplicatedEntitiesInMultivalueLinks&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;value:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;during:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Document.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;/span&gt;&lt;span&gt;atEnd&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifFalse:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;syntaxError&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;result-of-the-optimization&quot;&gt;Result of the optimization&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Now let’s try to import the same JSON file with the optiwization enabled:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Image of a profiling&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1054&quot; height=&quot;1037&quot; src=&quot;https://modularmoose.org/_astro/profiler_full_after.BmjsNuSM_kIEeM.webp&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Image of a profiling 2&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;621&quot; height=&quot;723&quot; src=&quot;https://modularmoose.org/_astro/profiler_2_after.C3X9lOqc_249m2B.webp&quot;&gt;&lt;/p&gt;
&lt;p&gt;We can see that the import time went from 351sec to 113sec!&lt;/p&gt;
&lt;p&gt;We can also notice that we do not have one bottleneck in our parsing. This means that it will be harder to optimize more this task (even if some people still have some ideas on how to do that).&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;use-this-optimization-in-your-project&quot;&gt;Use this optimization in your project&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This optimization has been made for the import of JSON but it can be used in other contexts.
For example, in the Moose Python importer, the implementation is sure to never produce a duplicate. Thus, we could use the same trick this way:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixPythonImporter&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;import&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;FMShouldCheckForDuplicatedEntitiesInMultivalueLinks&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;value:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;during:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; super &lt;/span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;</content:encoded><category>infrastructure</category><category>optimization</category></item><item><title>Testing your algo on a java project</title><link>https://modularmoose.org/blog/2025-10-08-testing-your-algo-on-a-java-project/</link><guid isPermaLink="true">https://modularmoose.org/blog/2025-10-08-testing-your-algo-on-a-java-project/</guid><description>Test your Moose algorithms on real Java projects without storing models by hand.</description><pubDate>Wed, 08 Oct 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;When developping algorithm on top of the Moose platform, we can easily hurt a wall during testing.&lt;/p&gt;
&lt;p&gt;To do functional (and sometimes unit) testing, we need to work on a Moose model. Most of the time we are getting this model in two ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We produce a model and save the &lt;code dir=&quot;auto&quot;&gt;.json&lt;/code&gt; to recreate this model in the tests&lt;/li&gt;
&lt;li&gt;We create a model by hand&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But those 2 solutions have drawbacks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Keeping a JSON will not follow the evolutions of Famix and the model produce will not be representative of the last version of Famix&lt;/li&gt;
&lt;li&gt;Creating a model by hand has the drawback of taking the risk that this model will not be representative of what we could manipulate in reality. For example, we might not think about setting the stubs or the source anchors&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In order to avoid those drawbacks I will describe my way of managing such testing cases in this article. In order to do this, I will explain how I set up the tests of a project to build CallGraph of Java projects.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;the-idea&quot;&gt;The idea&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The idea I had for testing callgraphs is to implement real java projects in a &lt;code dir=&quot;auto&quot;&gt;resources&lt;/code&gt; folder in the git of the project. Then, we can parse them when launching the tests and manipulate the produced model. This would ensure that we always have a model up to date with the latest version of Famix. If tests breaks, this means that our famix model evolved and that our project does not work anymore for this language.&lt;/p&gt;
&lt;svg host=&quot;65bd71144e&quot; width=&quot;217px&quot; height=&quot;381px&quot; viewBox=&quot;-0.5 -0.5 217 381&quot; content=&quot;&amp;#x26;lt;mxfile&amp;#x26;gt;&amp;#x26;lt;diagram name=&amp;#x26;quot;Page-1&amp;#x26;quot; id=&amp;#x26;quot;kOQ6wMe3Ks2p-SqpZatp&amp;#x26;quot;&amp;#x26;gt;7Zhfd9ogGMY/TS7rSUBjvNy03XaxMzcvtu6OJW+TtElICWqyTz8o5C9Oq2et9px5ofDw8hJ+PAJq4XlafmAkjz7TABIL2UFp4YWFkOu54l0KlRImM6SEkMWBkpxWWMW/QYu2VtdxAEUvkFOa8Djviz7NMvB5TyOM0W0/7I4m/VFzEoIhrHySmOr3OOCRUj00bfWPEIdRPbLjzlRLSupgPZMiIgHddiR8beE5o5SrUlrOIZHsai6q381fWpsHY5Dx53R4XH11H4pHtryarbAXfHF/buiVp7JsSLLWE9YPy6uaQMjoOjcH0+NvgHEody0F+VVnaGcrXAI0Bc4qEad7odlY9avqldfAti1v5GgbRR3W2NOBRK9x2ORuMYiCJnEEFcegsiSsAOm9SL7njN5Lsw1RCVJZADKzbeH32yjmsMqJL1u34tshtIin4kkWjije0YxrvyMZbiLeu2JD7ibfY3m6L4UTGTjnDAiXJO/JhrwZoGcDiA2An9KcMt4YMlXb7kXTq2py57bj2KD5bZ1JlFDwQnzS7C1yxejcXCeHzxLIgnfyUBY1PyFFEft9WH2yUMb8hyyPJrp2q+NkeVF2whZVXcnEVDqdZPW229Z2e6rV/YbLVHBGH5ojHx29cAVdMx8Ob4qcsBD25dNnEQS9e8rezWlim6teawwSwuNN/3azywp6hCWNM94e1s4UjbzecY3HAz+pmet+3fvIIBVyh6nQbJBKwTFSPbmzmfrphnX/uWFPNN8pRn91w9a370OGxZdlWNseuKy5Dx1r2B2pJq9r2Ol/wx5hWPxMw44vzLDTkXBa+3L6e+T0ZPfuzWts4ydbWVTbH7UqvP1nAF//AQ==&amp;#x26;lt;/diagram&amp;#x26;gt;&amp;#x26;lt;/mxfile&amp;#x26;gt;&quot;&gt;
    &lt;defs&gt;&lt;/defs&gt;
    &lt;g&gt;
        &lt;g&gt;&lt;/g&gt;
        &lt;g&gt;
            &lt;rect x=&quot;0&quot; y=&quot;100&quot; width=&quot;216&quot; height=&quot;60&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot;&gt;&lt;/rect&gt;
        &lt;/g&gt;
        &lt;g&gt;
            &lt;g transform=&quot;translate(-0.5 -0.5)&quot;&gt;
                &lt;switch&gt;
                    &lt;foreignObject pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http://www.w3.org/TR/SVG11/feature#Extensibility&quot;&gt;
                        &lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
                            &lt;div&gt;
                                &lt;div&gt;
                                    Parse the project
                                &lt;/div&gt;
                            &lt;/div&gt;
                        &lt;/div&gt;
                    &lt;/foreignObject&gt;
                    &lt;text x=&quot;108&quot; y=&quot;136&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;&amp;#x22;Helvetica&amp;#x22;&quot; font-size=&quot;20px&quot; text-anchor=&quot;middle&quot;&gt;
                        Parse the project
                    &lt;/text&gt;
                &lt;/switch&gt;
            &lt;/g&gt;
        &lt;/g&gt;
        &lt;g&gt;
            &lt;rect x=&quot;0&quot; y=&quot;0&quot; width=&quot;216&quot; height=&quot;60&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot;&gt;&lt;/rect&gt;
        &lt;/g&gt;
        &lt;g&gt;
            &lt;g transform=&quot;translate(-0.5 -0.5)&quot;&gt;
                &lt;switch&gt;
                    &lt;foreignObject pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http://www.w3.org/TR/SVG11/feature#Extensibility&quot;&gt;
                        &lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
                            &lt;div&gt;
                                &lt;div&gt;
                                    Create java project
                                &lt;/div&gt;
                            &lt;/div&gt;
                        &lt;/div&gt;
                    &lt;/foreignObject&gt;
                    &lt;text x=&quot;108&quot; y=&quot;36&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;&amp;#x22;Helvetica&amp;#x22;&quot; font-size=&quot;20px&quot; text-anchor=&quot;middle&quot;&gt;
                        Create java project
                    &lt;/text&gt;
                &lt;/switch&gt;
            &lt;/g&gt;
        &lt;/g&gt;
        &lt;g&gt;
            &lt;rect x=&quot;0&quot; y=&quot;210&quot; width=&quot;216&quot; height=&quot;60&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot;&gt;&lt;/rect&gt;
        &lt;/g&gt;
        &lt;g&gt;
            &lt;g transform=&quot;translate(-0.5 -0.5)&quot;&gt;
                &lt;switch&gt;
                    &lt;foreignObject pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http://www.w3.org/TR/SVG11/feature#Extensibility&quot;&gt;
                        &lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
                            &lt;div&gt;
                                &lt;div&gt;
                                    Import the model
                                &lt;/div&gt;
                            &lt;/div&gt;
                        &lt;/div&gt;
                    &lt;/foreignObject&gt;
                    &lt;text x=&quot;108&quot; y=&quot;246&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;&amp;#x22;Helvetica&amp;#x22;&quot; font-size=&quot;20px&quot; text-anchor=&quot;middle&quot;&gt;
                        Import the model
                    &lt;/text&gt;
                &lt;/switch&gt;
            &lt;/g&gt;
        &lt;/g&gt;
        &lt;g&gt;
            &lt;rect x=&quot;0&quot; y=&quot;320&quot; width=&quot;216&quot; height=&quot;60&quot; fill=&quot;#ffffff&quot; stroke=&quot;#000000&quot; pointer-events=&quot;all&quot;&gt;&lt;/rect&gt;
        &lt;/g&gt;
        &lt;g&gt;
            &lt;g transform=&quot;translate(-0.5 -0.5)&quot;&gt;
                &lt;switch&gt;
                    &lt;foreignObject pointer-events=&quot;none&quot; width=&quot;100%&quot; height=&quot;100%&quot; requiredFeatures=&quot;http://www.w3.org/TR/SVG11/feature#Extensibility&quot;&gt;
                        &lt;div xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
                            &lt;div&gt;
                                &lt;div&gt;
                                    Run tests on the model
                                &lt;/div&gt;
                            &lt;/div&gt;
                        &lt;/div&gt;
                    &lt;/foreignObject&gt;
                    &lt;text x=&quot;108&quot; y=&quot;356&quot; fill=&quot;light-dark(#000000, #ffffff)&quot; font-family=&quot;&amp;#x22;Helvetica&amp;#x22;&quot; font-size=&quot;20px&quot; text-anchor=&quot;middle&quot;&gt;
                        Run tests on the model
                    &lt;/text&gt;
                &lt;/switch&gt;
            &lt;/g&gt;
        &lt;/g&gt;
        &lt;g&gt;
            &lt;path d=&quot;M 108 60 L 108 91.76&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-width=&quot;2&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot;&gt;&lt;/path&gt;
            &lt;path d=&quot;M 108 97.76 L 104 89.76 L 108 91.76 L 112 89.76 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-width=&quot;2&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot;&gt;&lt;/path&gt;
        &lt;/g&gt;
        &lt;g&gt;
            &lt;path d=&quot;M 108 160 L 108 201.76&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-width=&quot;2&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot;&gt;&lt;/path&gt;
            &lt;path d=&quot;M 108 207.76 L 104 199.76 L 108 201.76 L 112 199.76 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-width=&quot;2&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot;&gt;&lt;/path&gt;
        &lt;/g&gt;
        &lt;g&gt;
            &lt;path d=&quot;M 108 270 L 108 311.76&quot; fill=&quot;none&quot; stroke=&quot;#000000&quot; stroke-width=&quot;2&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;stroke&quot;&gt;&lt;/path&gt;
            &lt;path d=&quot;M 108 317.76 L 104 309.76 L 108 311.76 L 112 309.76 Z&quot; fill=&quot;#000000&quot; stroke=&quot;#000000&quot; stroke-width=&quot;2&quot; stroke-miterlimit=&quot;10&quot; pointer-events=&quot;all&quot;&gt;&lt;/path&gt;
        &lt;/g&gt;
    &lt;/g&gt;
    &lt;switch&gt;
        &lt;g requiredFeatures=&quot;http://www.w3.org/TR/SVG11/feature#Extensibility&quot;&gt;&lt;/g&gt;
        &lt;a transform=&quot;translate(0,-5)&quot; xlink:href=&quot;https://www.drawio.com/doc/faq/svg-export-text-problems&quot; target=&quot;_blank&quot;&gt;
            &lt;text text-anchor=&quot;middle&quot; font-size=&quot;10px&quot; x=&quot;50%&quot; y=&quot;100%&quot;&gt;
                Text is not SVG - cannot display
            &lt;/text&gt;
        &lt;/a&gt;
    &lt;/switch&gt;
&lt;/svg&gt;
&lt;div&gt;&lt;h2 id=&quot;basic-setup&quot;&gt;Basic setup&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;create-your-java-code&quot;&gt;Create your java code&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The first step to build tests is to write some example java code.&lt;/p&gt;
&lt;p&gt;I will start with a minimal example:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Main&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;static&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&lt;span&gt;[] &lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;System&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;out&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;Hello World!&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;I’ll save this file in the git repository of my project under &lt;code dir=&quot;auto&quot;&gt;Famix-CallGraph/resources/sources/example1/Main.java&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now that we have the source code, we need a way to access it in our project.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;use-gitbridge&quot;&gt;Use GitBridge&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;In order to access our resources, we will use &lt;a href=&quot;https://github.com/jecisc/GitBridge&quot;&gt;GitBrigde&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can install it by executing:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Metacello&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;githubUser:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;jecisc&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;project:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;GitBridge&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;commitish:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;v1.x.x&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;path:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;src&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;baseline:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;GitBridge&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;load&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;But we should add it to our baseline:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;BaselineOfFamixCallGraph&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;#gitBridge:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;spec&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;spec&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;baseline:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;GitBridge&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;with:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;spec&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;repository:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;github://jecisc/GitBridge:v1.x.x/src&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;BaselineOfFamixCallGraph&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;#baseline:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;spec&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;baseline&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;spec&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;for:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#common&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;do:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;Dependencies&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;gitBridge:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;spec&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;Packages&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;spec&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;package:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;Famix-CallGraph&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;package:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;Famix-CallGraph-Tests&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;with:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;spec&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;requires:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#( &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;Famix-CallGraph&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;GitBridge&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; )&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&amp;#x3C;== WE ADD GITBRIDGE HERE!&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;spec&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;for:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#NeedsFamix&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;do:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;famix:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;spec&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;spec&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;package:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;Famix-CallGraph&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;with:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;spec&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;requires:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#( Famix )&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Now that we have the dependency running, we can use this project. We will explain the minimal steps here but you can find the &lt;a href=&quot;https://github.com/jecisc/GitBridge/blob/master/resources/documentation/UserGuide.md&quot;&gt;full documantation here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The usage of GitBridge begins with the definition of our &lt;code dir=&quot;auto&quot;&gt;FamixCallGraphBridge&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;GitBridge&lt;/span&gt;&lt;span&gt; &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span&gt;#FamixCallGraphBridge&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;slots:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;package:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;Famix-CallGraph-Tests&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Now that this class exists we can access our git folder using &lt;code dir=&quot;auto&quot;&gt;FamixCallGraphBridge current root&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Let’s add some syntactic suggar:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixCallGraphBridge&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;#resources&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;root&lt;/span&gt;&lt;span&gt; / &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;resources&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixCallGraphBridge&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;#sources&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;resources&lt;/span&gt;&lt;span&gt; / &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;sources&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;We can now access our java projects doing &lt;code dir=&quot;auto&quot;&gt;FamixCallGraphBridge current sources&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This step is almost done, but in order for our tests to work in a github action (for example), we need two little tweaks.&lt;/p&gt;
&lt;p&gt;In our &lt;code dir=&quot;auto&quot;&gt;smalltalk.ston&lt;/code&gt; file, we need to register our project in Iceberg (because GitBridge uses Iceberg to access the root folder).&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;SmalltalkCISpec&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;#loading&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;SCIMetacelloLoadSpec&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;#baseline&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;FamixCallGraph&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;#directory&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;src&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;#registerInIceberg&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;&quot;&amp;#x3C;== This line&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Also, in our github action we need to be sure that the checkout action will get enough info for git bridge to run and not the minimal ammount (which is the default) adding a &lt;code dir=&quot;auto&quot;&gt;fetch-depth:&lt;/code&gt; option.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;steps:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- uses: actions/checkout@v4&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;with:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;fetch-depth: &apos;0&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;parse-and-import-your-model&quot;&gt;Parse and import your model&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Now we need to be able to parse our project. For this, we will use a Java utility thaht is directly in Moose: &lt;code dir=&quot;auto&quot;&gt;FamixJavaFoldersImporter&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We can parse and receive a model doing:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(FamixJavaFoldersImporter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;importFolders:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FamixCallGraphBridge&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sources&lt;/span&gt;&lt;span&gt; / &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;example1&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;anyOne&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;tests-implementation&quot;&gt;Tests implementation&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Now that we can access the model it is possible to implement our tests.&lt;/p&gt;
&lt;p&gt;I’m starting by an abstract class:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;TestCase&lt;/span&gt;&lt;span&gt; &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span&gt;#FamixAbstractJavaCallGraphBuilderTestCase&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;slots:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#graph&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;package:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;Famix-CallGraph-Tests&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Now I will create a TestCase that needs my java model&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixAbstractJavaCallGraphBuilderTestCase&lt;/span&gt;&lt;span&gt; &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span&gt;#FamixJavaCHAExample1Test&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;slots:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;package:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;Famix-CallGraph-Tests&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;And now I will create a setup importing the model and creating a call graph:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixAbstractJavaCallGraphBuilderTestCase&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;#setUp&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;super &lt;/span&gt;&lt;span&gt;setUp&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(FamixJavaFoldersImporter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;importFolders:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;javaSourcesFolder&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;anyOne&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;graph&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(FamixJavaCHABuilder&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;entryPoints:&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;entryPoints&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixJavaCHAExample1Test&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;#javaSourcesFolder&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;Return the java folder containing the sources to parse for those tests&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;folder&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;folder&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FamixCallGraphBridge&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sources&lt;/span&gt;&lt;span&gt; / &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;example1&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;folder&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifAbsent:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;error:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;Folder does not exists &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; , &lt;/span&gt;&lt;span&gt;folder&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pathString&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;folder&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;And now you have your model available for the testing!&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;optimization&quot;&gt;Optimization&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;I am using this technic to tests multiple projects such as parsers or call graph builders. In those projects I do touch my model and the setup can take time. So I optimize this setup in order to build a model only once for all the test case using a &lt;code dir=&quot;auto&quot;&gt;TestResource&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In order to do this we can remove the slots we added to &lt;code dir=&quot;auto&quot;&gt;FamixAbstractJavaCallGraphBuilderTestCase&lt;/code&gt; and create a test resource that will hold them&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;TestResource&lt;/span&gt;&lt;span&gt; &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span&gt;#FamixAbstractJavaCallGraphBuilderTestResource&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;slots:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#graph&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;package:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;Famix-CallGraph-Tests&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Then we can move the setup to this class&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixAbstractJavaCallGraphBuilderTestResource&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;#setUp&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;super &lt;/span&gt;&lt;span&gt;setUp&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(FamixJavaFoldersImporter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;importFolders:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;javaSourcesFolder&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;anyOne&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;graph&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(FamixJavaCHABuilder&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;entryPoints:&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;entryPoints&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Personally I’m also adding a tearDown cleaning the vars because TestResources are singletons and I do not want to hold a model in memory all the time.&lt;/p&gt;
&lt;p&gt;Then I’m creating my test resource for the &lt;code dir=&quot;auto&quot;&gt;example1&lt;/code&gt; project.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixAbstractJavaCallGraphBuilderTestResource&lt;/span&gt;&lt;span&gt; &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span&gt;#FamixJavaCHAExample1Resource&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;slots:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;package:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;Famix-CallGraph-Tests&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixJavaCHAExample1Resource&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;#javaSourcesFolder&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;Return the java folder containing the sources to parse for those tests&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;folder&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;folder&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FamixCallGraphBridge&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sources&lt;/span&gt;&lt;span&gt; / &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;example1&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;folder&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifAbsent:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;error:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;Folder does not exists &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; , &lt;/span&gt;&lt;span&gt;folder&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pathString&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;folder&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;And now we can declare that the TestCase will use this resource:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixJavaCHAExample1Test&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;#resources&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FamixJavaCHAExample1Resource&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The model then become accessible like this:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixJavaCHAExample1Resource&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;#model&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;resources&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;anyOne&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;current&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;model&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;simplify-your-life&quot;&gt;Simplify your life&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Here is a few tricks I use to simplify even better the setting of my tests cases&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;automatic-java-source-folder-detection&quot;&gt;Automatic java source folder detection&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The first one is to make automatic the detection of the java source folder by using the name of the test cases:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixAbstractJavaCallGraphBuilderTestResource&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;#javaSourcesFolder&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;javaSourcesFolder&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixAbstractJavaCallGraphBuilderTestResource&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;#javaSourcesFolder&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;Return the java folder containing the sources to parse for those tests&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;folder&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;folder&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FamixCallGraphBridge&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sources&lt;/span&gt;&lt;span&gt; / &lt;/span&gt;&lt;span&gt;((&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;withoutPrefix:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;FamixJavaCHA&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;withoutSuffix:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;Resource&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;uncapitalized&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;folder&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifAbsent:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;error:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;Folder does not exists &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; , &lt;/span&gt;&lt;span&gt;folder&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pathString&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;folder&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;We can now remove this method from all subclasses! But makes sure the name of your source folder matches the name of the tests ressource ;)&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;automatic-test-resource-detection-and-access&quot;&gt;Automatic test resource detection and access&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;We can do the same with the detection of the test resource in the test case.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixAbstractJavaCallGraphBuilderTestCase&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;#resources&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;environment&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;at:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;((&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;withoutSuffix:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;Test&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; , &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;Resource&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;asSymbol&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;ifPresent:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;ifAbsent:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixAbstractJavaCallGraphBuilderTestCase&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;#sourceResource&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;resources&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;anyOne&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;current&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixAbstractJavaCallGraphBuilderTestCase&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;#sourceResource&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;I return the instance of the test resource I&apos;m using to build the sources of a java project&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sourceResource&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixAbstractJavaCallGraphBuilderTestCase&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;#model&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;sourceResource&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;model&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Et voila ! Now adding a test case ready to use on a new java project is equivalent to create a test case:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixAbstractJavaCallGraphBuilderTestCase&lt;/span&gt;&lt;span&gt; &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span&gt;#FamixJavaCHAExample2Test&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;slots:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;package:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;Famix-CallGraph-Tests&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;And the resource associated!&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixAbstractJavaCallGraphBuilderTestResource&lt;/span&gt;&lt;span&gt; &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span&gt;#FamixJavaCHAExample2Resource&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;slots:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;package:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;Famix-CallGraph-Tests&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Nothing much.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;easily-find-the-sources-of-the-tested-project&quot;&gt;Easily find the sources of the tested project&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;A last thing I am doing to simplify thing is to implement a method to access easily the sources.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixJavaCHAExample1Test&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;#openSources&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;script:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;self new openSources&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;resources&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;anyOne&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;javaSourcesFolder&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;openInOSFileBrowser&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;other-languages-than-java&quot;&gt;Other languages than Java&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;It is possible to do the same thing for other languages than java but maybe not exactly in the same way than in this blogpost for the section “Parse and import your model”. But this article is meant to be an inspiration!&lt;/p&gt;
&lt;p&gt;I hope this helps improve the robustness of our projects :)&lt;/p&gt;</content:encoded><category>CI</category><category>infrastructure</category></item><item><title>Generation of new FAST-Language metamodel using Pharo-Tree-Sitter project</title><link>https://modularmoose.org/blog/2025-09-16-generation-of-fast-metamodel-using-treesitter/</link><guid isPermaLink="true">https://modularmoose.org/blog/2025-09-16-generation-of-fast-metamodel-using-treesitter/</guid><description>Generate a first version of a new FAST-Language meta-model with Pharo-Tree-Sitter.</description><pubDate>Mon, 15 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;If you’re here, you’re probably interested in creating a new FAST metamodel and expanding Moose to represent the AST (Abstract Syntax Tree) of an additional language.
In this post, we explain to you how to generate a “First version” of a new FAST-Language metamodel using the project Pharo-Tree-Sitter.
To be able to understand that, we assume you are already familiar with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tree-Sitter&lt;/li&gt;
&lt;li&gt;Pharo-Tree-Sitter&lt;/li&gt;
&lt;li&gt;FAST&lt;/li&gt;
&lt;li&gt;Metamodel generators&lt;/li&gt;
&lt;/ul&gt;
&lt;aside aria-label=&quot;If you are not, the following provides a general introduction to these tools/libraries along with references for further details:&quot;&gt;&lt;p aria-hidden=&quot;true&quot;&gt;If you are not, the following provides a general introduction to these tools/libraries along with references for further details:&lt;/p&gt;&lt;div&gt;&lt;/div&gt;&lt;/aside&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://tree-sitter.github.io/tree-sitter/&quot;&gt;Tree-Sitter&lt;/a&gt;&lt;/strong&gt; is a parser generator tool and an incremental parsing library. It can build a concrete syntax tree for a source file and efficiently update the syntax tree as the source file is edited. It is able to parse a large variety of programming languages such as Java, C++, C#, Python and many others.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/Evref-BL/Pharo-Tree-Sitter/&quot;&gt;Pharo-Tree-Sitter&lt;/a&gt;&lt;/strong&gt; is a project developed in Pharo that integrates the original Tree-Sitter parsers and allows visualizing their results (such as ASTs) directly in Pharo. It relies on the FFI protocol, which requires the corresponding libraries depending on the OS (.dll, .so, or .pylib) to be present in Pharo’s VM folders.
The project supports parsing several languages, and for some of them (like Python, TypeScript, and C), the library generation is automated. You can find more details in the repository’s README.
This is the project that we will use to generate a new FAST-Language metamodel, so you need to download it into your Pharo image.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/moosetechnology/fast&quot;&gt;FAST&lt;/a&gt;&lt;/strong&gt; means Famix AST. Contrary to Famix that represent application at a high abstraction level, FAST uses a low-level representation: the AST.
FAST defines a set of traits that can be used to create new meta-models compatible with Moose tools.
When developing a new FAST-Language metamodel, you will rely on these FAST traits to structure your metamodel. However, this does not apply to the “First version” described in this post, but rather to the upgraded versions when you evolve and refine it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://modularmoose.org/developers/create-new-metamodel/&quot;&gt;Metamodel generator&lt;/a&gt;&lt;/strong&gt; is a Pharo library used to create new metamodels such as FAST-Java, Famix-Java, or FAST-Fortran.
The generation of any new version of a FAST-Language metamodel can only be achieved through the metamodel generator.
As you will see in this post, Pharo-Tree-Sitter enables you to define a new metamodel generator. Once executed, it produces the corresponding FAST-Language metamodel. We will explain this process in more detail in the following sections.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;download-pharo-tree-sitter-and-get-the-correspondent-libraries&quot;&gt;Download Pharo-Tree-Sitter and get the correspondent libraries&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;First you need to create a Moose image and download &lt;a href=&quot;https://github.com/Evref-BL/Pharo-Tree-Sitter/&quot;&gt;Pharo-Tree-Sitter&lt;/a&gt;:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Metacello&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;baseline:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;TreeSitter&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;repository:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;github://Evref-BL/Pharo-Tree-Sitter:main/src&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;load&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Once downloaded, you need to make sure that Pharo-Tree-Sitter is able to parse the language that you intend to create the metamodel for.
If it is not included, you need to follow the instructions in the readme file of this repository and add the new language.
For this blog post we will assume that the language is already supported and we will continue with “Python” 🐍🐍🐍.&lt;/p&gt;
&lt;p&gt;To be able to continue, and if this is the first time you’re using this project (Pharo-Tree-Sitter), you need to launch the tests of python in package “TreeSitter-Tests” class “TSParserPythonTest”.
This is needed to launch the process of downloading the original &lt;strong&gt;&lt;a href=&quot;https://github.com/tree-sitter/tree-sitter&quot;&gt;tree-sitter&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href=&quot;https://github.com/tree-sitter/tree-sitter-python&quot;&gt;tree-sitter-python&lt;/a&gt;&lt;/strong&gt; projects from GitHub, generating the correspondent libraries and moving them to the correspondent VM folder based on the image version you create: for example Moose 12.
If you create another image of another version, you need to launch the tests again to make sure the libraries are again moved to the correspondent folder.
Now that you have the libraries, you can parse python code and get an AST, but not FAST-Python model.
So in the next step we explain how this can be possible.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;create-the-first-version-of-the-metamodel-fast-python-in-our-example&quot;&gt;Create the first version of the metamodel (FAST-Python in our example)&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Don’t worry, not too much to be done, but a snippet of code needs to be written and executed.
But we have to explain to you first how it is working.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;explaining-package-treesitter-fast-utils&quot;&gt;Explaining package TreeSitter-FAST-Utils&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;This package contains two main classes: “TSFASTBuilder” and “TSFASTImporter”.
For our task we will rely on the first one.
The second is used to make the transition between an AST generated by TreeSitter and a FAST-Language model.&lt;/p&gt;
&lt;p&gt;“TSFASTBuilder” contains a set of methods responsible for generating a new metamodel generator:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;#tsLanguage:&lt;/code&gt; is used to set an instance of TSLanguage, which is &lt;code dir=&quot;auto&quot;&gt;TSLanguage python&lt;/code&gt; in our case.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;#createMetamodelGeneratorClass&lt;/code&gt; is responsible for creating a new package and a class inside. By default, the class name will be “FASTLanguageNameMetamodelGenerator” which is “FASTPythonMetamodelGenerator” and the package name is “FAST-LanguageName-Model-Generator”.
This method also calls another one “typesToReify”, which gets all the symbols from the initial TreeSitter project (using an FFI call), and add them as slots in the class definition. These symbols represent the nodes of the language in question like “class” for Python.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;#addPrefixMethodIn:&lt;/code&gt; adds &lt;code dir=&quot;auto&quot;&gt;#prefix&lt;/code&gt; method on the class side of the metamodel generator class. By default it is FASTLanguage.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;#addPackageNameMethodIn:&lt;/code&gt; adds &lt;code dir=&quot;auto&quot;&gt;#packageName&lt;/code&gt; method on the class side of the metamodel generator class. By default it’s ‘FAST-Language-Model’.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;#addSubmetamodelsMethodIn:&lt;/code&gt; adds &lt;code dir=&quot;auto&quot;&gt;#submetamodels&lt;/code&gt; method on the class side of the metamodel generator class, and by default it contains FASTMetamodelGenerator.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;#addDefineClassIn:&lt;/code&gt; adds &lt;code dir=&quot;auto&quot;&gt;#defineClasses&lt;/code&gt; method. In this method slots are defined, starting by #entity then all the symbols imported from TreeSitter.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;#addDefineTraitsIn:&lt;/code&gt; adds &lt;code dir=&quot;auto&quot;&gt;#defineTraits&lt;/code&gt; method. By default FASTTEntity trait is created.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;#addDefineHierarchyIn:&lt;/code&gt; adds &lt;code dir=&quot;auto&quot;&gt;#defineHierarchy&lt;/code&gt; method. By default only #entity relation is defined with FASTTEntity.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;#addDefineRelationsIn:&lt;/code&gt; adds &lt;code dir=&quot;auto&quot;&gt;#defineRelations&lt;/code&gt; method. By default only #entity relations are defined with genericChildren and genericParent.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Voilà, now that you understand how it works, we will show you how to generate one for Python:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;tsb&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TSFASTBuilder&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;tsb&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;languageName:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;Python&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;tsb&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tsLanguage:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TSLanguage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;python&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;tsb&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This will generate the metamodel generator. Now that the generator is created you can use it to generate the metamodel:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTPythonMetamodelGenerator&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;generate&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Now you can access the packages and classes created: ‘FAST-Python-Model’ and ‘FAST-Python-Model-Generator’.&lt;/p&gt;
&lt;p&gt;From now on you have to handle the metamodel manually. You have to add missing traits (including FAST Traits), properties that should be imported from TreeSitter…  You benefit from the importer to handle the parsing on the metamodel side. You can create a package for tools having a #parse method doing this for example:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;parser&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tsLanguage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;importer&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Smalltalk&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;image&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;garbageCollect&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;parser&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TSParser&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;tsLanguage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TSLanguage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;python&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;parser&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;language:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tsLanguage&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;importer&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TSFASTImporter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;importer&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tsLanguage:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tsLanguage&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;importer&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;languageName:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;Python&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;importer&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;originString:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;importer&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;import:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;parser&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;parseString:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rootNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;pay attention to #source: &quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;You can check FASTTypeScript for more details.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;N.B: We recommend you to parse many python examples (you can find a lot in the main project of TreeSitter-Python), using Pharo-Tree-Sitter project. Once parsed you can inspect in Pharo the properties for each node using &lt;code dir=&quot;auto&quot;&gt;#collectFieldNameOfNamedChild&lt;/code&gt; and find the properties for each one. Then you can add them in #defineRelations of the metamodel.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That’s it for now!&lt;/p&gt;</content:encoded><category>meta-model</category><category>Python</category></item><item><title>Visualizing java dependencies between microservices</title><link>https://modularmoose.org/blog/2025-09-12-microservice-dependency/</link><guid isPermaLink="true">https://modularmoose.org/blog/2025-09-12-microservice-dependency/</guid><description>A simple process to analyze and visualize the dependencies between Java microservices with Moose.</description><pubDate>Fri, 12 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In July, I had to analyze the dependencies between microservices for &lt;a href=&quot;https://www.berger-levrault.com/&quot;&gt;Berger-Levrault&lt;/a&gt;.
To do so, I chose to use the Moose tool.&lt;/p&gt;
&lt;p&gt;Here is the simple but effective process I followed.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;about-the-project-structure&quot;&gt;About the project structure&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The backend I analyzed follows a common pattern.
In the git repository, there is a folder &lt;code dir=&quot;auto&quot;&gt;api&lt;/code&gt; containing the microservices, and a folder &lt;code dir=&quot;auto&quot;&gt;lib&lt;/code&gt; with resources for each microservice.
There is also an additional project called &lt;code dir=&quot;auto&quot;&gt;lib-common&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Thus, the microservice &lt;code dir=&quot;auto&quot;&gt;home&lt;/code&gt; is composed of a project named &lt;code dir=&quot;auto&quot;&gt;api-home&lt;/code&gt; and a project named &lt;code dir=&quot;auto&quot;&gt;lib-home&lt;/code&gt;.&lt;/p&gt;
&lt;starlight-file-tree data-pagefind-ignore=&quot;true&quot;&gt;&lt;ul&gt;&lt;li&gt;&lt;details open&gt;&lt;summary&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;svg width=&quot;16&quot; height=&quot;16&quot; aria-hidden=&quot;true&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M22.073 4.900L22.073 4.900L12.148 4.900L12.148 3.950Q12.148 3.125 11.585 2.563Q11.023 2 10.198 2L10.198 2L0.048 2L0.048 22L23.948 22L23.948 6.850Q23.998 6.025 23.448 5.462Q22.898 4.900 22.073 4.900Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/span&gt;src
&lt;/span&gt;&lt;/span&gt;&lt;/summary&gt;&lt;ul&gt;&lt;li&gt;&lt;details open&gt;&lt;summary&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;svg width=&quot;16&quot; height=&quot;16&quot; aria-hidden=&quot;true&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M22.073 4.900L22.073 4.900L12.148 4.900L12.148 3.950Q12.148 3.125 11.585 2.563Q11.023 2 10.198 2L10.198 2L0.048 2L0.048 22L23.948 22L23.948 6.850Q23.998 6.025 23.448 5.462Q22.898 4.900 22.073 4.900Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/span&gt;api
&lt;/span&gt;&lt;/span&gt;&lt;/summary&gt;&lt;ul&gt;&lt;li&gt;&lt;details open&gt;&lt;summary&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;svg width=&quot;16&quot; height=&quot;16&quot; aria-hidden=&quot;true&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M22.073 4.900L22.073 4.900L12.148 4.900L12.148 3.950Q12.148 3.125 11.585 2.563Q11.023 2 10.198 2L10.198 2L0.048 2L0.048 22L23.948 22L23.948 6.850Q23.998 6.025 23.448 5.462Q22.898 4.900 22.073 4.900Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/span&gt;api-home
&lt;/span&gt;&lt;/span&gt;&lt;/summary&gt;&lt;ul&gt;&lt;li&gt;&lt;details&gt;&lt;summary&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;svg width=&quot;16&quot; height=&quot;16&quot; aria-hidden=&quot;true&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M22.073 4.900L22.073 4.900L12.148 4.900L12.148 3.950Q12.148 3.125 11.585 2.563Q11.023 2 10.198 2L10.198 2L0.048 2L0.048 22L23.948 22L23.948 6.850Q23.998 6.025 23.448 5.462Q22.898 4.900 22.073 4.900Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/span&gt;src/&lt;/span&gt;&lt;/span&gt;&lt;/summary&gt;&lt;ul&gt;&lt;li&gt;&lt;span&gt;&lt;span&gt;…&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/details&gt;&lt;/li&gt;&lt;li&gt;&lt;details open&gt;&lt;summary&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;svg width=&quot;16&quot; height=&quot;16&quot; aria-hidden=&quot;true&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M22.073 4.900L22.073 4.900L12.148 4.900L12.148 3.950Q12.148 3.125 11.585 2.563Q11.023 2 10.198 2L10.198 2L0.048 2L0.048 22L23.948 22L23.948 6.850Q23.998 6.025 23.448 5.462Q22.898 4.900 22.073 4.900Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/span&gt;lib
&lt;/span&gt;&lt;/span&gt;&lt;/summary&gt;&lt;ul&gt;&lt;li&gt;&lt;details open&gt;&lt;summary&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;svg width=&quot;16&quot; height=&quot;16&quot; aria-hidden=&quot;true&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M22.073 4.900L22.073 4.900L12.148 4.900L12.148 3.950Q12.148 3.125 11.585 2.563Q11.023 2 10.198 2L10.198 2L0.048 2L0.048 22L23.948 22L23.948 6.850Q23.998 6.025 23.448 5.462Q22.898 4.900 22.073 4.900Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/span&gt;lib-home
&lt;/span&gt;&lt;/span&gt;&lt;/summary&gt;&lt;ul&gt;&lt;li&gt;&lt;details&gt;&lt;summary&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;svg width=&quot;16&quot; height=&quot;16&quot; aria-hidden=&quot;true&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M22.073 4.900L22.073 4.900L12.148 4.900L12.148 3.950Q12.148 3.125 11.585 2.563Q11.023 2 10.198 2L10.198 2L0.048 2L0.048 22L23.948 22L23.948 6.850Q23.998 6.025 23.448 5.462Q22.898 4.900 22.073 4.900Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/span&gt;src/&lt;/span&gt;&lt;/span&gt;&lt;/summary&gt;&lt;ul&gt;&lt;li&gt;&lt;span&gt;&lt;span&gt;…&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/details&gt;&lt;/li&gt;&lt;li&gt;&lt;details&gt;&lt;summary&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;svg width=&quot;16&quot; height=&quot;16&quot; aria-hidden=&quot;true&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M22.073 4.900L22.073 4.900L12.148 4.900L12.148 3.950Q12.148 3.125 11.585 2.563Q11.023 2 10.198 2L10.198 2L0.048 2L0.048 22L23.948 22L23.948 6.850Q23.998 6.025 23.448 5.462Q22.898 4.900 22.073 4.900Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/span&gt;lib-common/&lt;/span&gt;&lt;/span&gt;&lt;/summary&gt;&lt;ul&gt;&lt;li&gt;&lt;span&gt;&lt;span&gt;…&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/starlight-file-tree&gt;
&lt;p&gt;We wanted to check that dependencies were correctly implemented in the project:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;no &lt;code dir=&quot;auto&quot;&gt;api&lt;/code&gt; project should directly depend on another &lt;code dir=&quot;auto&quot;&gt;api&lt;/code&gt; (API calls are allowed, but not classic Java dependencies)&lt;/li&gt;
&lt;li&gt;each &lt;code dir=&quot;auto&quot;&gt;api&lt;/code&gt; project can depend on its equivalent &lt;code dir=&quot;auto&quot;&gt;lib&lt;/code&gt; project&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;lib&lt;/code&gt; projects can depend on &lt;code dir=&quot;auto&quot;&gt;lib-common&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let’s see how to perform this check with Moose.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;loading-the-project&quot;&gt;Loading the project&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;To perform the analysis, I used Moose and followed these steps:&lt;/p&gt;
&lt;ol role=&quot;list&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://modularmoose.org/beginners/install-moose/&quot;&gt;I installed the latest version of Moose&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I cloned the repository containing the backend to analyze.&lt;/li&gt;
&lt;li&gt;I installed the project dependencies with:
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;mvn&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;clean&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;I used &lt;a href=&quot;https://modularmoose.org/developers/parsers/verveinej/&quot;&gt;VerveineJ&lt;/a&gt; to generate a model of the code. To avoid version issues, I used the Docker version of VerveineJ, which gave me a &lt;em&gt;model.json&lt;/em&gt; file:
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-v&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/path/to/my/project:/src&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-v&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/home/badetitou/.m2/repository:/dependency&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;ghcr.io/evref-bl/verveinej:v3.3.1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-alllocals&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-anchor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;assoc&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-format&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;json&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-o&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;model.json&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;I loaded the model into a Moose 12 image by drag-and-dropping the &lt;em&gt;model.json&lt;/em&gt; file into the running Moose image.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;h2 id=&quot;building-a-dependency-visualization&quot;&gt;Building a dependency visualization&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Moose provides ready-to-use visualizations to represent dependencies. In my case, I chose to use the &lt;em&gt;Architectural map&lt;/em&gt;.
This visualization presents the entities of the model (packages, classes, methods) as a tree and displays the associations between them (i.e., the dependencies).&lt;/p&gt;
&lt;p&gt;I first asked this visualization to display all the classes. It works, but does not allow us to distinguish the different microservices.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://modularmoose.org/_astro/bad_architectural_map.DspGWar9_VJNLD.svg&quot; alt=&quot;Unhelpful architectural map&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;5669&quot; height=&quot;3598&quot;&gt;&lt;/p&gt;
&lt;p&gt;The main problem is that too much information is displayed and we cannot see the microservices.
To fix this, I used Moose’s tag feature.
A tag allows you to associate a color and a name to an entity.&lt;/p&gt;
&lt;p&gt;So I tagged the classes of my system depending on their location in the repository.&lt;/p&gt;
&lt;p&gt;To do this, in a Moose Playground, I used the following script (adapt it to your context 😉):&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;allTaggedEntities&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;do:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;entity&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;entity&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;removeTags&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;((&lt;/span&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;allWithSubTypesOf:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FamixJavaType)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;reject:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sourceAnchor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;isNil&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;])&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;do:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sourceAnchor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifNotNil:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;sa&lt;/span&gt;&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;sa&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;fileName&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;beginsWith:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;./services/api-A&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifTrue:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tagWithName:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;A&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;sa&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;fileName&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;beginsWith:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;./services/api-B&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifTrue:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tagWithName:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;B&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;sa&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;fileName&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;beginsWith:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;./services/api-C&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifTrue:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tagWithName:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;C&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;sa&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;fileName&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;beginsWith:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;./libraries/lib-A&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifTrue:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tagWithName:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;lib-A&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;sa&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;fileName&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;beginsWith:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;./libraries/lib-common&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifTrue:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tagWithName:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;lib-common&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;sa&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;fileName&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;beginsWith:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;./libraries/lib-B&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifTrue:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tagWithName:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;lib-B&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;sa&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;fileName&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;beginsWith:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;./libraries/lib-C&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifTrue:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tagWithName:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;lib-C&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;allWithSubTypesOf:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FamixJavaType)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;reject:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tags&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;isEmpty&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;aside aria-label=&quot;Note&quot;&gt;&lt;p aria-hidden=&quot;true&quot;&gt;Note&lt;/p&gt;&lt;div&gt;&lt;p&gt;In the Moose Playground, select all the lines and execute &lt;em&gt;Propagate&lt;/em&gt; to send the result to the architectural map.&lt;/p&gt;&lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;The result is not perfect yet because entities are not grouped by tag.
To fix this, simply select the &lt;em&gt;tag to add&lt;/em&gt; option in the architectural map settings.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://modularmoose.org/_astro/architectural_map.BXGvwAE__Z28fm9v.svg&quot; alt=&quot;Correct architectural map&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;541&quot; height=&quot;304&quot;&gt;&lt;/p&gt;
&lt;p&gt;You then get a clear visualization of the links between the microservice projects and the libraries they use. We see that no &lt;code dir=&quot;auto&quot;&gt;api&lt;/code&gt; is linked to an incorrect &lt;code dir=&quot;auto&quot;&gt;lib&lt;/code&gt; project.
We also notice that microservice &lt;em&gt;B&lt;/em&gt; is linked to &lt;em&gt;lib-B&lt;/em&gt; as well as &lt;em&gt;lib-common&lt;/em&gt;.
Maybe this link to &lt;em&gt;lib-common&lt;/em&gt; should be removed? But that’s another story…&lt;/p&gt;</content:encoded><category>story</category></item><item><title>Building a Famix importer with TreeSitterFamixIntegration</title><link>https://modularmoose.org/blog/2025-08-11-famix-importer-with-treesitterfamixintegration/</link><guid isPermaLink="true">https://modularmoose.org/blog/2025-08-11-famix-importer-with-treesitterfamixintegration/</guid><description>Build a Famix importer for C code with the TreeSitterFamixIntegration framework.</description><pubDate>Mon, 11 Aug 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Analyzing source code starts with parsing and for this you need &lt;em&gt;semantic understanding&lt;/em&gt; of how symbols in the code relate to each other.
In this post, we’ll walk through how to build a &lt;strong&gt;C code importer&lt;/strong&gt; using the &lt;strong&gt;&lt;a href=&quot;https://github.com/moosetechnology/TreeSitterFamixIntegration&quot;&gt;TreeSitterFamixIntegration&lt;/a&gt;&lt;/strong&gt; framework.&lt;/p&gt;
&lt;aside aria-label=&quot;Important&quot;&gt;&lt;p aria-hidden=&quot;true&quot;&gt;Important&lt;/p&gt;&lt;div&gt;&lt;p&gt;The goal of this blog post is to provide a starting point on how to use the TreeSitterFamixIntegration framework to build a Famix importer.&lt;/p&gt;&lt;/div&gt;&lt;/aside&gt;
&lt;div&gt;&lt;h2 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Basic knowledge of Famix and Moose.&lt;/li&gt;
&lt;li&gt;Basic knowledge of what &lt;a href=&quot;https://tree-sitter.github.io/tree-sitter/&quot;&gt;Tree-sitter&lt;/a&gt; is.&lt;/li&gt;
&lt;li&gt;Familiarity with the Visitor design pattern. You can check &lt;a href=&quot;https://modularmoose.org/blog/2025-03-26-visitor-external-grammar/&quot;&gt;this blog post&lt;/a&gt; which explains the Visitor pattern in the context of tree-sitter ASTs.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;overview-of-treesitterfamixintegration&quot;&gt;Overview of TreeSitterFamixIntegration&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The TreeSitterFamixIntegration stack provides tools to ease the development of Famix importers using tree-sitter.
This package offers some great features for parsing such as (but not limited to):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Useful methods for source management (getting source text, positions, setting sourceAnchor of a famix entity).&lt;/li&gt;
&lt;li&gt;Error handling to help catch and report parsing issues&lt;/li&gt;
&lt;li&gt;a better TreeSitter node inspector (which is very helpful when debugging)&lt;/li&gt;
&lt;li&gt;Utility to efficiently import and attach single-line and multi-line comments to their corresponding entities.&lt;/li&gt;
&lt;li&gt;Context tracking for symbol scope (no more context push and pop 😁)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There is a detailed &lt;a href=&quot;https://github.com/moosetechnology/TreeSitterFamixIntegration/blob/main/resources/docs/UserDocumentation.md&quot;&gt;documentation&lt;/a&gt; you can check that explain every features.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;step-1-setting-up-our-environment&quot;&gt;Step 1: Setting up our environment&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;After creating a new Moose image, let’s start by loading the necessary packages.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;the-c-metamodel&quot;&gt;The C Metamodel&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;First, we need to load the C metamodel. This metamodel provides the Famix classes that represent C entities such as functions, structs, variables, etc.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Metacello&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;baseline:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;FamixCpp&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;repository:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;github://moosetechnology/Famix-Cpp:main&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;load&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;aside aria-label=&quot;Tip&quot;&gt;&lt;p aria-hidden=&quot;true&quot;&gt;Tip&lt;/p&gt;&lt;div&gt;&lt;p&gt;You can directly load the C metamodel from the Moose toolbar by going to the &lt;strong&gt;Library&lt;/strong&gt; menu: &lt;em&gt;Library Famix &gt; Load additional modules &gt; Load Famix-Cpp&lt;/em&gt;&lt;/p&gt;&lt;/div&gt;&lt;/aside&gt;
&lt;div&gt;&lt;h3 id=&quot;the-treesitterfamixintegration-project&quot;&gt;The TreeSitterFamixIntegration project&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Next, we need to load the TreeSitterFamixIntegration project.
It provides both pharo-tree-sitter and SRSymbolResolver.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Metacello&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;githubUser:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;moosetechnology&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;project:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;TreeSitterFamixIntegration&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;commitish:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;path:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;src&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;baseline:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;TreeSitterFamixIntegration&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;load&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;the-project-structure&quot;&gt;The project structure&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Now that we have the necessary packages loaded, we can create our C importer.&lt;/p&gt;
&lt;p&gt;Create a new package named &lt;code dir=&quot;auto&quot;&gt;Famix-C-Importer&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The minimum classes we will have to create inside are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;FamixCimporter&lt;/code&gt;: This class will be responsible for importing C files and parsing them using Tree-sitter.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;FamixCVisitor&lt;/code&gt;: This class will walk through the parsed C syntax tree and create Famix entities.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;FamixCCommentVisitor&lt;/code&gt;: This class will handle comments and attach them to the corresponding Famix entities.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;the-famixcimporter-class&quot;&gt;The &lt;code dir=&quot;auto&quot;&gt;FamixCimporter&lt;/code&gt; class&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;FamixCimporter&lt;/code&gt; class is the entry point for our importer. It will handle the parsing of C files into Abstract Syntax Trees (AST).&lt;/p&gt;
&lt;p&gt;This class will inherit from &lt;code dir=&quot;auto&quot;&gt;FamixTSAbstractImporter&lt;/code&gt; (defined in the TreeSitterFamixIntegration project), which provides the necessary methods for importing and parsing C files using Tree-sitter.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixTSAbstractImporter&lt;/span&gt;&lt;span&gt; &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span&gt;#FamixCImporter&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;slots:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;package:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;Famix-C-Importer&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Now, let’s override some methods to set up our importer:&lt;/p&gt;
&lt;div&gt;&lt;h4 id=&quot;1-treesitterlanguage-method&quot;&gt;1. &lt;code dir=&quot;auto&quot;&gt;treeSitterLanguage&lt;/code&gt; method&lt;/h4&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixCImporter&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;treeSitterLanguage&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;Should return a TreeSitter language such as  TSLanguage python&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TSLanguage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cLang&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This method returns the Tree-sitter language we want to use for parsing. In this case, we are using the C language. You can find the available languages in the &lt;code dir=&quot;auto&quot;&gt;Pharo-Tree-Sitter&lt;/code&gt; package.&lt;/p&gt;
&lt;div&gt;&lt;h4 id=&quot;2-visitorclass-method&quot;&gt;2. &lt;code dir=&quot;auto&quot;&gt;visitorClass&lt;/code&gt; method&lt;/h4&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixCImporter&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;visitorClass&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FamixCVisitor&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;It returns the visitor class that will walk through the parsed syntax tree and create Famix entities. We will define this class later.&lt;/p&gt;
&lt;div&gt;&lt;h4 id=&quot;3-importfilereference-method&quot;&gt;3. &lt;code dir=&quot;auto&quot;&gt;importFileReference:&lt;/code&gt; method&lt;/h4&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixCImporter&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;importFileReference:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFileReference&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;aFileReference&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;isFile&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;ifTrue:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;isCFile:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFileReference&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifFalse:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;importFile:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFileReference&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;ifFalse:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;aFileReference&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;children&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;do:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;each&lt;/span&gt;&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;importFileReference:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;each&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This method calls &lt;code dir=&quot;auto&quot;&gt;importFile:&lt;/code&gt; on all C files recursively found in a directory.
We will add more logic to this method later but for now, it serves as a starting point for our importer.&lt;/p&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;isCFile:&lt;/code&gt; method checks if the file has a &lt;code dir=&quot;auto&quot;&gt;.c&lt;/code&gt; or &lt;code dir=&quot;auto&quot;&gt;.h&lt;/code&gt; extension.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixCImporter&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;isCFile:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFileReferencemon&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#( &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;h&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; )&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;includes:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFileReference&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;extension&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;importFile:&lt;/code&gt; method is defined in the &lt;code dir=&quot;auto&quot;&gt;FamixTSAbstractImporter&lt;/code&gt; class (provided by the TreeSitter-Famix-Integration project).
It parses the file content to create an AST and then passes the visitor (the &lt;code dir=&quot;auto&quot;&gt;FamixCVisitor&lt;/code&gt; that we previously defined) to walk through the AST.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;the-famixcvisitor-class&quot;&gt;The &lt;code dir=&quot;auto&quot;&gt;FamixCVisitor&lt;/code&gt; class&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;FamixCVisitor&lt;/code&gt; class is responsible for walking through the parsed AST and creating Famix entities. It will inherit from &lt;code dir=&quot;auto&quot;&gt;FamixTSAbstractVisitor&lt;/code&gt;, which provides the necessary methods for visiting Tree-sitter nodes.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixTSAbstractVisitor&lt;/span&gt;&lt;span&gt; &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span&gt;#FamixCVisitor&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;slots:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;package:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;Famix-C-Importer&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;For this class, we will just need to override one method:&lt;/p&gt;
&lt;div&gt;&lt;h4 id=&quot;modelclass-method&quot;&gt;&lt;code dir=&quot;auto&quot;&gt;modelClass&lt;/code&gt; method&lt;/h4&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixCVisitor&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;modelClass&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FamixCModel&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;It returns the Famix metamodel class that will be used to create Famix entities. In this case, we are using &lt;code dir=&quot;auto&quot;&gt;FamixCModel&lt;/code&gt; which is in the &lt;code dir=&quot;auto&quot;&gt;Famix-Cpp&lt;/code&gt; package.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;lets-test-our-importer-so-far&quot;&gt;Let’s test our importer so far&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Now that we have our importer and visitor classes set up, we can already test it.
To test our importer, we can create a simple C file and import it using the &lt;code dir=&quot;auto&quot;&gt;FamixCImporter&lt;/code&gt; class.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;test.c&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;#include&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;stdio.h&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; aGlobalVar &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; aLocalVar;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;aLocalVar &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; aGlobalVar &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;To import this file, we can use the following code in the Playground (cmd + O + P to open it):&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;import c project&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1270&quot; height=&quot;279&quot; src=&quot;https://modularmoose.org/_astro/import-c-project.CgZ9R0ZR_1qXkP.webp&quot;&gt;&lt;/p&gt;
&lt;p&gt;Before running the above code, open the Transcript to see the logs (cmd + O + T to open it).&lt;/p&gt;
&lt;p&gt;Then select all the code and run it by inspecting it (cmd + I or click the “Inspect” button). You will get something similar to this.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Model inspector&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1194&quot; height=&quot;386&quot; src=&quot;https://modularmoose.org/_astro/model-inspector.BRdGc3pP_1DOyst.webp&quot;&gt;&lt;/p&gt;
&lt;p&gt;The above screenshot shows what is inside our model. We can see that there is pretty much nothing there yet apart from the SourceLanguages which is added by default by TreeSitterFamixIntegration.&lt;/p&gt;
&lt;p&gt;Now if we look at the Transcript, we can see that the importer has imported the file but we didn’t implement the visitor methods yet for every node in the AST, so no Famix entities were created.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;transcript log&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;888&quot; height=&quot;432&quot; src=&quot;https://modularmoose.org/_astro/transcript-log.ksm7Dm90_2dFWJJ.webp&quot;&gt;&lt;/p&gt;
&lt;aside aria-label=&quot;Note&quot;&gt;&lt;p aria-hidden=&quot;true&quot;&gt;Note&lt;/p&gt;&lt;div&gt;&lt;p&gt;The way those methods are named is &lt;code dir=&quot;auto&quot;&gt;visitNodeType: aNode&lt;/code&gt; where &lt;code dir=&quot;auto&quot;&gt;NodeType&lt;/code&gt; is the type of the node in the AST. For example, for a function declaration, it would be &lt;code dir=&quot;auto&quot;&gt;visitFunctionDeclaration: aNode&lt;/code&gt;.
This &lt;a href=&quot;https://modularmoose.org/blog/2025-03-26-visitor-external-grammar/&quot;&gt;blog post&lt;/a&gt; explains one way to create automatically these methods.&lt;/p&gt;&lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;If you want to inspect the corresponding AST of our test file, you can do something similar to what is in &lt;a href=&quot;https://modularmoose.org/blog/2025-03-25-tree-sitter/#a-first-pharo-ast&quot;&gt;this other blog post&lt;/a&gt; on tree-sitter.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;translation unit AST&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1204&quot; height=&quot;1296&quot; src=&quot;https://modularmoose.org/_astro/translationunit-ast.hN2HiN_f_WyBAe.webp&quot;&gt;&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;step-2-our-first-famix-entities&quot;&gt;Step 2: Our first Famix entities&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;In this section we are going to see some examples of visiting methods for creating compilation unit and function entities.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;compilationunit-entities&quot;&gt;CompilationUnit entities&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Let’s go back to our &lt;code dir=&quot;auto&quot;&gt;FamixCImporter&lt;/code&gt; class and from there we will create a CompilationUnit and HeaderFile entities. We need to do that there because we have to check if the file is a header file or a source file.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixCImporter&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;importFileReference:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFileReference&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;aFileReference&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;isFile&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;ifTrue:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;fileEntity&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;isCFile:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFileReference&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifFalse:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;fileEntity&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFileReference&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;extension&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                        &lt;/span&gt;&lt;span&gt;ifTrue:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                         &lt;/span&gt;&lt;span&gt;visitor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;newCompilationUnitNamed:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFileReference&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;basename&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                  &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                        &lt;/span&gt;&lt;span&gt;ifFalse:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                         &lt;/span&gt;&lt;span&gt;visitor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;newHeaderFileNamed:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFileReference&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;basename&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                  &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;visitor&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;useCurrentEntity:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;fileEntity&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;during:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;importFile:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aFileReference&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;ifFalse:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;aFileReference&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;children&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;do:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;each&lt;/span&gt;&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;importFileReference:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;each&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                    &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;We use the &lt;mark&gt;useCurrentEntity:during:&lt;/mark&gt; to provide a context for the visitor. This is same as pushing the &lt;code dir=&quot;auto&quot;&gt;fileEntity&lt;/code&gt; to a context, visit children and then popping it from the context. And it will set the current entity to the &lt;code dir=&quot;auto&quot;&gt;fileEntity&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now try importing a whole directory containing C files. You should see that the importer creates a &lt;code dir=&quot;auto&quot;&gt;FamixCHeaderFile&lt;/code&gt; for each header file and a &lt;code dir=&quot;auto&quot;&gt;FamixCCompilationUnit&lt;/code&gt; for each source file.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;source-anchors&quot;&gt;Source Anchors&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;To set the source anchor for any Famix entity, we can use the &lt;mark&gt;setSourceAnchor: aFamixEntity from: aTSNode&lt;/mark&gt; method provided by the &lt;code dir=&quot;auto&quot;&gt;FamixTSAbstractVisitor&lt;/code&gt; class. This method takes a Famix entity and a Tree-sitter node.&lt;/p&gt;
&lt;p&gt;We can use it to set the source anchor for our &lt;code dir=&quot;auto&quot;&gt;fileEntity&lt;/code&gt; . Go to &lt;code dir=&quot;auto&quot;&gt;visitTranslationUnit:&lt;/code&gt; in the &lt;code dir=&quot;auto&quot;&gt;FamixCVisitor&lt;/code&gt; class and add the following code:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixCVisitor&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;visitTranslationUnit:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;/span&gt;&lt;span&gt;setSourceAnchor:&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;currentEntity&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;from:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitChildren:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;for not cutting the traversal&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;aside aria-label=&quot;Note&quot;&gt;&lt;p aria-hidden=&quot;true&quot;&gt;Note&lt;/p&gt;&lt;div&gt;&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;self currentEntity&lt;/code&gt; returns the entity that is currently being visited by the visitor (i.e at the top of the stack). In this case, it will return the &lt;code dir=&quot;auto&quot;&gt;fileEntity&lt;/code&gt; that we pushed to the context in the &lt;code dir=&quot;auto&quot;&gt;importFileReference:&lt;/code&gt; method by using the &lt;code dir=&quot;auto&quot;&gt;useCurrentEntity:during:&lt;/code&gt; method.&lt;/p&gt;&lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;Now if we import our &lt;code dir=&quot;auto&quot;&gt;test.c&lt;/code&gt; file again, we will see that the &lt;code dir=&quot;auto&quot;&gt;CompilationUnit&lt;/code&gt; entity has a source anchor.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;function-entities&quot;&gt;Function entities&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Next, we will create &lt;code dir=&quot;auto&quot;&gt;FamixCFunction&lt;/code&gt; entities for each function declaration in the C file. We will do this in the &lt;code dir=&quot;auto&quot;&gt;visitFunctionDefinition:&lt;/code&gt; method of the &lt;code dir=&quot;auto&quot;&gt;FamixCVisitor&lt;/code&gt; class.&lt;/p&gt;
&lt;p&gt;But first we need to know where the function name is located to create the &lt;code dir=&quot;auto&quot;&gt;FamixCFunction&lt;/code&gt; entity. Create the method and put a &lt;code dir=&quot;auto&quot;&gt;halt&lt;/code&gt; there to inspect the node.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;visitFunctionDefinition:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;/span&gt;&lt;span&gt;halt&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitChildren:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;img alt=&quot;function definition ast&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;899&quot; height=&quot;449&quot; src=&quot;https://modularmoose.org/_astro/function-definition-ast.BcpGInHu_Z2fyIjO.webp&quot;&gt;&lt;/p&gt;
&lt;p&gt;If we look at the function definition node, we can see that the function name is in the identifier node, which is a child of the function declarator node.&lt;/p&gt;
&lt;p&gt;To get that name, there are two ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;visit the function_declarator until the identifier returns its name using &lt;code dir=&quot;auto&quot;&gt;self visit: aNode&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;get it by child field name using &lt;code dir=&quot;auto&quot;&gt;aNode _fieldName&lt;/code&gt; that returns the child node with the given field name. And you don’t need to implement the &lt;code dir=&quot;auto&quot;&gt;_fieldName&lt;/code&gt; method because it is already handled by the framework.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For simplicity, and to show other available features in the framework, we will use the second way.&lt;/p&gt;
&lt;p&gt;Let’s inspect the function definition node to see what fields it has.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;function definition fields&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;925&quot; height=&quot;449&quot; src=&quot;https://modularmoose.org/_astro/function-definition-fields.Dy98LWAF_Z1DNJa9.webp&quot;&gt;&lt;/p&gt;
&lt;p&gt;So if we do &lt;code dir=&quot;auto&quot;&gt;aNode _declarator&lt;/code&gt; it will return the function declarator node&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;function declarator&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;929&quot; height=&quot;274&quot; src=&quot;https://modularmoose.org/_astro/function-declarator.CVlkAdVj_Z2wKfEb.webp&quot;&gt;
And if we do &lt;code dir=&quot;auto&quot;&gt;aNode _declarator&lt;/code&gt; from the function_declarator it will give us the identifier that we want.&lt;/p&gt;
&lt;aside aria-label=&quot;Note&quot;&gt;&lt;p aria-hidden=&quot;true&quot;&gt;Note&lt;/p&gt;&lt;div&gt;&lt;p&gt;the &lt;code dir=&quot;auto&quot;&gt;sourceText&lt;/code&gt; will return the text of the node, which is the function name in this case.&lt;/p&gt;&lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;Now we can create the function entity and set its name and source anchor.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;visitFunctionDefinition:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;declaratorNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;identifierNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;functionName&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;entity&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;declaratorNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;_&lt;/span&gt;&lt;span&gt;declarator.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;identifierNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;declaratorNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;_&lt;/span&gt;&lt;span&gt;declarator.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;functionName&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;identifierNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sourceText&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;entity&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;newFunctionNamed:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;functionName&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;functionOwner:&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;currentEntity&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;setSourceAnchor:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;entity&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;from:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;useCurrentEntity:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;entity&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;during:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;visitChildren:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;self currentEntity&lt;/code&gt; returns the compilation unit entity which is the parent of the function entity.&lt;/p&gt;
&lt;p&gt;And before visiting the children, we set the current entity to the newly created function entity using &lt;code dir=&quot;auto&quot;&gt;useCurrentEntity:during:&lt;/code&gt;. This will allow us to create other entities that are related to this function, such as parameters and local variables.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;local-and-global-variables&quot;&gt;Local and Global Variables&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The difference between local and global variables is that local variables are declared inside a function, while global variables are declared outside any function.&lt;/p&gt;
&lt;div&gt;&lt;h4 id=&quot;implementation&quot;&gt;Implementation&lt;/h4&gt;&lt;/div&gt;
&lt;aside aria-label=&quot;Tip&quot;&gt;&lt;p aria-hidden=&quot;true&quot;&gt;Tip&lt;/p&gt;&lt;div&gt;&lt;p&gt;Before visiting a node, check its fields by inspecting the node to know how to extract the needed information.&lt;/p&gt;&lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;To create the variable entities, we will create the &lt;code dir=&quot;auto&quot;&gt;visitDeclaration:&lt;/code&gt; method in the &lt;code dir=&quot;auto&quot;&gt;FamixCVisitor&lt;/code&gt; class. This method is called for each variable declaration in the C file.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixCVisitor&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;visitDeclaration:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;fields: type - declarator&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;varName&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;entity&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visit:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;_&lt;/span&gt;&lt;span&gt;type.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;varName&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;visit:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;_&lt;/span&gt;&lt;span&gt;declarator.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;entity&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;currentEntity&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;isFunction&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;              &lt;/span&gt;&lt;span&gt;ifTrue:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                  &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;newLocalVariableNamed:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;varName&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                    &lt;/span&gt;&lt;span&gt;parentBehaviouralEntity:&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;currentEntity&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                    &lt;/span&gt;&lt;span&gt;yourself&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;              &lt;/span&gt;&lt;span&gt;ifFalse:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                  &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;newGlobalVariableNamed:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;varName&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                    &lt;/span&gt;&lt;span&gt;parentScope:&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;currentEntity&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;                    &lt;/span&gt;&lt;span&gt;yourself&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;setSourceAnchor:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;entity&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;from:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;visitDeclaration:&lt;/code&gt; method does the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Visits the variable’s type. This will allow us to parse its type information.&lt;/li&gt;
&lt;li&gt;Retrieves the variable name by visiting the &lt;code dir=&quot;auto&quot;&gt;declarator&lt;/code&gt; field. If the variable is initialized, this will be an &lt;code dir=&quot;auto&quot;&gt;init_declarator&lt;/code&gt; node; otherwise, it will be an &lt;code dir=&quot;auto&quot;&gt;identifier&lt;/code&gt;. We should implement visit methods for both cases to extract the name correctly.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixCVisitor&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;visitInitDeclarator:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;fields: declarator - value&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visit:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;_&lt;/span&gt;&lt;span&gt;value.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;visit:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;_&lt;/span&gt;&lt;span&gt;declarator&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;variable name is in the declarator node&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixCVisitor&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;visitIdentifier:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sourceText&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;returns the name of the variable&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;Creates a variable entity, either a local variable or a global variable, depending on whether the current entity is a function or not.&lt;/li&gt;
&lt;li&gt;Sets the source anchor for the variable entity using the &lt;code dir=&quot;auto&quot;&gt;setSourceAnchor:from:&lt;/code&gt; method.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;h2 id=&quot;step-3-symbol-resolution&quot;&gt;Step 3: Symbol resolution&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;In this section, we will implement the symbol resolution for our C importer. This will allow us to resolve references to variables and functions in our C code.&lt;/p&gt;
&lt;p&gt;As an example, we will resolve the reference to the local variable &lt;code dir=&quot;auto&quot;&gt;aLocalVar&lt;/code&gt; in the &lt;code dir=&quot;auto&quot;&gt;main&lt;/code&gt; function, which will be represented as a famix write access entity.&lt;/p&gt;
&lt;div&gt;&lt;h4 id=&quot;implementation-1&quot;&gt;Implementation&lt;/h4&gt;&lt;/div&gt;
&lt;div&gt;&lt;h5 id=&quot;create-the-write-access-entity&quot;&gt;&lt;strong&gt;Create the write access entity&lt;/strong&gt;&lt;/h5&gt;&lt;/div&gt;
&lt;p&gt;To create the write access entity, we will implement the &lt;code dir=&quot;auto&quot;&gt;visitAssignmentExpression:&lt;/code&gt; method in the &lt;code dir=&quot;auto&quot;&gt;FamixCVisitor&lt;/code&gt; class. This method is called for each assignment expression.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;visitAssignmentExpression:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;fields: left - right&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;access&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;leftVarName&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;leftVarName&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;visit:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;_&lt;/span&gt;&lt;span&gt;left.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;access&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;newAccess&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;accessor:&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;currentEntity&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;isWrite:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;yourself&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;setSourceAnchor:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;access&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;from:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;using-sridentifierresolvable&quot;&gt;Using SRIdentifierResolvable&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Add the following code to the &lt;code dir=&quot;auto&quot;&gt;visitAssignmentExpression:&lt;/code&gt; method to resolve the variable:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;visitAssignmentExpression:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;fields: left - right&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;access&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;leftVarName&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;leftVarName&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;visit:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;_&lt;/span&gt;&lt;span&gt;left.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;access&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;newAccess&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;accessor:&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;currentEntity&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;isWrite:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;yourself&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;setSourceAnchor:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;access&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;from:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;resolve:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;((SRIdentifierResolvable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;identifier:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;leftVarName&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;expectedKind:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;FamixCLocalVariable.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;FamixCGlobalVariable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;yourself&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;foundAction:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;variable&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;currentEntity&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;access&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;variable:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;variable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The &lt;mark&gt;resolve: aResolvable foundAction: aBlockClosure&lt;/mark&gt; method is provided by the &lt;code dir=&quot;auto&quot;&gt;FamixTSAbstractVisitor&lt;/code&gt; class.&lt;/p&gt;
&lt;p&gt;It takes two arguments:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;aResolvable&lt;/code&gt;: an instance of &lt;code dir=&quot;auto&quot;&gt;SRIdentifierResolvable&lt;/code&gt;. This resolvable is created with the identifier (the variable name) and the expected kinds of entities (in this case, either a local variable or a global variable). The &lt;code dir=&quot;auto&quot;&gt;identifier:&lt;/code&gt; method sets the identifier to resolve, and the &lt;code dir=&quot;auto&quot;&gt;expectedKind:&lt;/code&gt; method sets the expected kinds of entities that can be resolved.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;aBlockClosure&lt;/code&gt;: a block that will be executed when the resolvable is resolved (we found the variable). In this case we set the variable of the access entity to the resolved variable.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;See the &lt;a href=&quot;https://github.com/jecisc/SymbolResolver/blob/main/resources/docs/UserDocumentation.md#sridentifierresovable&quot;&gt;SRIdentifierResolvable documentation&lt;/a&gt;&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;custom-resolver&quot;&gt;Custom resolver&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;SRIdentifierResolvable&lt;/code&gt; is a generic resolver that can be used to resolve identifiers. However, in some cases, we may need to create a custom resolver to handle specific cases. In that case, we can create a class that inherits from &lt;code dir=&quot;auto&quot;&gt;SRResolvable&lt;/code&gt; and override the &lt;code dir=&quot;auto&quot;&gt;resolveInScope:currentEntity:&lt;/code&gt; method to implement our custom resolution logic.&lt;/p&gt;
&lt;p&gt;For more information about the symbol resolver, you can check the &lt;a href=&quot;https://github.com/jecisc/SymbolResolver/blob/main/resources/docs/UserDocumentation.md#add-you-own-solver&quot;&gt;documentation&lt;/a&gt;.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;step-4-parse-comments&quot;&gt;Step 4: Parse comments&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;The TreeSitterFamixIntegration package provides a utility to parse comments and attach them to the corresponding Famix entities. This is done using the &lt;code dir=&quot;auto&quot;&gt;FamixCCommentVisitor&lt;/code&gt; class.&lt;/p&gt;
&lt;p&gt;let’s add some comments to our &lt;code dir=&quot;auto&quot;&gt;test.c&lt;/code&gt; file:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;test.c&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;#include&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;stdio.h&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; aGlobalVar &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;/*&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;entry point of our programm&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; aLocalVar;&lt;/span&gt;&lt;span&gt; // a local variable&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;aLocalVar &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; aGlobalVar &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h4 id=&quot;implementation-2&quot;&gt;Implementation&lt;/h4&gt;&lt;/div&gt;
&lt;p&gt;To parse comments, we will create the &lt;code dir=&quot;auto&quot;&gt;FamixCCommentVisitor&lt;/code&gt; class that will inherit from &lt;code dir=&quot;auto&quot;&gt;FamixTSAbstractCommentVisitor&lt;/code&gt;. And we just need to override the &lt;code dir=&quot;auto&quot;&gt;visitNode:&lt;/code&gt; method.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixCCommentVisitor&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;visitNode:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;#comment&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifTrue:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sourceText&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;beginsWith:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;/*&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;ifTrue:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;addMultilineCommentNode:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;ifFalse:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;addSingleLineCommentNode:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;super &lt;/span&gt;&lt;span&gt;visitNode:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;We use the &lt;code dir=&quot;auto&quot;&gt;addMultilineCommentNode:&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;addSingleLineCommentNode:&lt;/code&gt; methods provided by the &lt;code dir=&quot;auto&quot;&gt;FamixTSAbstractCommentVisitor&lt;/code&gt; class to add the comment to the model.&lt;/p&gt;
&lt;p&gt;For a detailed explanation of how to use the comment visitor, you can check the &lt;a href=&quot;https://github.com/moosetechnology/TreeSitterFamixIntegration/blob/main/resources/docs/UserDocumentation.md#comment-importer-helper&quot;&gt;documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Last thing to do is to use the comment visitor somewhere in our importer. We can do that everytime we finish visiting every children of translation unit node.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FamixCImporter&lt;/span&gt;&lt;span&gt; &gt;&gt;&lt;/span&gt;&lt;span&gt;visitTranslationUnit:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;setSourceAnchor:&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;currentEntity&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;from:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitChildren:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;FamixCCommentVisitor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;visitor:&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;importCommentsOf:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNode&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;We use the &lt;code dir=&quot;auto&quot;&gt;visitor: aFamixVisitor importCommentsOf: aNode&lt;/code&gt; method to import the comments of the translation unit node.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;In this blog post, we have seen how to build a Famix importer for C code using the TreeSitterFamixIntegration framework. We have covered the following topics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Setting up the environment and creating the importer and visitor classes.&lt;/li&gt;
&lt;li&gt;Creating Famix entities for compilation units, functions, and variables.&lt;/li&gt;
&lt;li&gt;Implementing symbol resolution for local and global variables.&lt;/li&gt;
&lt;li&gt;Parsing comments and attaching them to the corresponding Famix entities.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is just a starting point for building an importer with this stack. You have to implement more tests and methods to handle other entities. The TreeSitterFamixIntegration framework provides a lot of other utilities we didn’t cover to help you with that.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;useful-links&quot;&gt;Useful links&lt;/h2&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/moosetechnology/TreeSitterFamixIntegration/blob/main/resources/docs/UserDocumentation.md&quot;&gt;TreeSitterFamixIntegration documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Evref-BL/Pharo-Tree-Sitter&quot;&gt;Pharo-Tree-Sitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/jecisc/SymbolResolver/blob/main/resources/docs/UserDocumentation.md&quot;&gt;Symbol Resolver documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://modularmoose.org/blog/2025-03-26-visitor-external-grammar/&quot;&gt;Creating an importer for an alien grammar&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>infrastructure</category></item><item><title>Transformation journey (3/3) : Visualize and apply code transformations</title><link>https://modularmoose.org/blog/2025-06-13-transformation-third/</link><guid isPermaLink="true">https://modularmoose.org/blog/2025-06-13-transformation-third/</guid><description>How to visualize, edit, and apply code transformations to source files</description><pubDate>Fri, 13 Jun 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Once again, let me welcome you to the final blog post in those three blog posts about code transformations! During the &lt;a href=&quot;https://modularmoose.org/blog/2024-04-01-transformation-first/&quot;&gt;first blog&lt;/a&gt; post, we used queries and tools to locate the entities we seek to transform, before implementing the actual transformation logic in the &lt;a href=&quot;https://modularmoose.org/blog/2024-04-14-transformation-second/&quot;&gt;second blog&lt;/a&gt; post.&lt;/p&gt;
&lt;p&gt;In this third post, we will use a visualisation window allowing us to check the source code of our entity before and after a transformation, and finally apply those transformation on the actual source files, therefore transposing this transformation from Moose to your actual software!&lt;/p&gt;
&lt;p&gt;We are still following the scenario presented in the previous blog posts, on our use case, ArgoUML. In this system three classes define and use a method named &lt;code dir=&quot;auto&quot;&gt;logError&lt;/code&gt;.
A class &lt;code dir=&quot;auto&quot;&gt;ArgoLogger&lt;/code&gt; has been defined that contains a static method &lt;code dir=&quot;auto&quot;&gt;logError&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The transformation task is to add a receiver node to each &lt;code dir=&quot;auto&quot;&gt;logError&lt;/code&gt; method invocation so that the method called is now &lt;code dir=&quot;auto&quot;&gt;ArgoLogger.logError&lt;/code&gt;().&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;preface&quot;&gt;Preface&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;As this blog post follows what was discussed and built in the first one of the series, a lot of information (how to build the image and model used for our use case, but also the use case itself) is provided in the previous posts.&lt;/p&gt;
&lt;p&gt;If you haven’t read it, or if you forgot the content of the post, it is recommended to go back to it, as it will not be repeated in this post.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;tools-to-import&quot;&gt;Tools to import&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;In this final blog post, we do not have any new tools to import. As long as you still have &lt;code dir=&quot;auto&quot;&gt;FAST-Java-Tools&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;Carrefour&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;Motion&lt;/code&gt; from the two previous posts, you should have no problem following this blogpost!&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;a-first-look-on-our-transformation&quot;&gt;A first look on our transformation&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;At this point, we now have in our tool modified FAST trees of the methods we need to transform, all encapsulated in wrapper objects to save all the necessary information to complete the transformation, and apply it where needed.
Hovewer, before that, you may feel the need to check the transformation produced by your tool.&lt;/p&gt;
&lt;p&gt;To do so, we can use the &lt;code dir=&quot;auto&quot;&gt;TransformationEditor&lt;/code&gt; tool, a dialog window able to display the code before and after our code transformation, along with some nice and practical features to fulfill this task.&lt;/p&gt;
&lt;p&gt;First, let’s add a new method to our transformation tool; &lt;code dir=&quot;auto&quot;&gt;displayTransformationOfMethod: aMethodWrapper&lt;/code&gt;. We will call this new method in the already existing method &lt;code dir=&quot;auto&quot;&gt;transformMethod: aJavaMethodWrapper&lt;/code&gt;, as shown here :&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;transformMethod:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aJavaMethodWrapper&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;methodInvocationNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;codeEditor&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;methodInvocationNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;motionQueryForFastMethod:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;aJavaMethodWrapper&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;transformedFastMethod&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;methodInvocationNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;receiver:&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;createNewReceiverNode&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;aJavaMethodWrapper&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;addTransformedFastNode:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;methodInvocationNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;receiver&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;codeEditor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;displayTransformationOfMethod:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aJavaMethodWrapper&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;displayTransformationOfMethod:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aMethodWrapper&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;exportVisitor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;transformedCode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;codeEditor&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;exportVisitor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FASTJavaExporttVisitor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;transformedCode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;exportVisitor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;export:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;aMethodWrapper&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;transformedFastMethod&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;codeEditor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TransformationEditor&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;openForOriginalText:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;aMethodWrapper&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;originalFastMethod&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sourceText&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;transformed:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;transformedCode&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;originalEntity:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aMethodWrapper&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;famixMethod&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;codeEditor&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;As you can notice in this new method, we also call another tool, the &lt;code dir=&quot;auto&quot;&gt;FASTJavaExportVisitor&lt;/code&gt;. This visitor will allow us to convert a FAST Java tree to a string giving us the source code of our method after transformation.&lt;/p&gt;
&lt;p&gt;Coupling the result of using this tool to this class method of the &lt;code dir=&quot;auto&quot;&gt;TransformationEditor&lt;/code&gt; class will display such results :&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&amp;#x22;Transformation display&amp;#x22;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1600&quot; height=&quot;848&quot; src=&quot;https://modularmoose.org/_astro/editor_without_highlights.B47Rvv4J_Z1sjC9B.webp&quot;&gt;&lt;/p&gt;
&lt;p&gt;In this new window, you can find on the left the original source code of the entity, before any transformation. And on the right, you can find the source code of the same entity, after applying the transformation.&lt;/p&gt;
&lt;p&gt;The first thing we can notice, is how radically different the two methods look at a glance. Hovewer, everything is the same (to the exception of the new ArgoLogger class added with our transformation). They look different because the transformed code is generated from the transformed FAST tree, and the export visitor exports that code with its own formating.&lt;/p&gt;
&lt;p&gt;The source code after transformation (on the right pane) is also editable, meaning that you can manually add code to the entity if it is necessary for any reason. Do be careful that the code is syntaxically correct however, as there is no checks (syntax, compilation) on this code in Moose.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;adding-highlights&quot;&gt;Adding highlights&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;We now have a way to view our transformation, but as it is, it is still tough to view properly where are the changes and what they are. And in this example, the transformation is very basic! If the transformation was spread throughout a class rather than a method, or if the transformation was simply more complex, then the tool would fail as a means to review the changes.&lt;/p&gt;
&lt;p&gt;But of course, we can fix that. 😉&lt;/p&gt;
&lt;p&gt;To do so, we will modify the new method &lt;code dir=&quot;auto&quot;&gt;displayTransformationOfMethod:&lt;/code&gt; and use a subclass of the export visitor previously used; &lt;code dir=&quot;auto&quot;&gt;FASTJavaExportAndHiglightVisitor&lt;/code&gt;.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;displayTransformationOfMethod:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aMethodWrapper&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;exportVisitor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;transformedCode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;codeEditor&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;exportVisitor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FASTJavaExportAndHighlightVisitor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;exportVisitor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;entitiesToHighlight:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;aMethodWrapper&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;transformedFastNodes&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;transformedCode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;exportVisitor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;export:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;aMethodWrapper&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;transformedFastMethod&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;codeEditor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TransformationEditor&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;openForOriginalText:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;aMethodWrapper&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;originalFastMethod&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sourceText&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;transformed:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;transformedCode&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;removedHighlights:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;OrderedCollection&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;addedHighlights:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;exportVisitor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;highlights&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;originalEntity:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aMethodWrapper&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;famixMethod&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;codeEditor&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Our first edit simply calls the method wrapper to add a “transformed node”, a FAST node added during the transformation. In a similar fashion, you can add an “original node”, a FAST node removed during the transformation (no such node exists in our example, so we don’t use that feature).&lt;/p&gt;
&lt;p&gt;This new transformed node is used in our second edit, where we give the transformed nodes collection to the new visitor tool that we are going to use.&lt;/p&gt;
&lt;p&gt;This tool behaves just like the original exporter tool, except when it encounters a node present in the transformed nodes list. In this case, the tool save an interval corresponding to the &lt;code dir=&quot;auto&quot;&gt;startPos&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;endPos&lt;/code&gt; of the node, to know precisely its position in the generated string.&lt;/p&gt;
&lt;p&gt;This allows our editing window to apply an highlight on this interval, therefore showing only the nodes added in the transformation for the user to easily review the work of their transformation tool.&lt;/p&gt;
&lt;p&gt;To use this feature in the editing window, simply do as done in the edit, giving the tool a collection of interval for the &lt;code dir=&quot;auto&quot;&gt;removedHighlights&lt;/code&gt; and / or &lt;code dir=&quot;auto&quot;&gt;addedHighlights&lt;/code&gt; slots.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&amp;#x22;Transformation display with highlighting&amp;#x22;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1600&quot; height=&quot;828&quot; src=&quot;https://modularmoose.org/_astro/editor_with_highlights.BTaL_u0D_ZVrWUI.webp&quot;&gt;&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;applying-our-changes-on-the-source-files&quot;&gt;Applying our changes on the source files&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Now that we reviewed and accepted the transformation on our entities, only one step remains. To apply those code changes on the actual source code of the modeled software, thereby completing the transformation task.&lt;/p&gt;
&lt;p&gt;Once again, we have a tool ready for this need, in the form of the &lt;code dir=&quot;auto&quot;&gt;TransformationApplyerOnSourceAnchor&lt;/code&gt; class. Let’s do a final edit on our method &lt;code dir=&quot;auto&quot;&gt;transformSourceCodeOfMethod&lt;/code&gt; to add it:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;transformSourceCodeOfMethod:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aMethodWrapper&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;exportVisitor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;transformedCode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;codeEditor&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;exportVisitor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FASTJavaExportAndHighlightVisitor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;exportVisitor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;entitiesToHighlight:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;aMethodWrapper&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;transformedFastNodes&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;transformedCode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;exportVisitor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;export:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;aMethodWrapper&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;transformedFastMethod&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;codeEditor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TransformationEditor&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;openForOriginalText:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;aMethodWrapper&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;originalFastMethod&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sourceText&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;transformed:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;transformedCode&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;removedHighlights:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;OrderedCollection&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;addedHighlights:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;exportVisitor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;highlights&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;originalEntity:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aMethodWrapper&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;famixMethod&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;codeEditor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;isOk&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifTrue:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;tool&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;tool&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TransformationApplyerOnSourceAnchor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;tool&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;transformMethod:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aMethodWrapper&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;famixMethod&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;withNewSource:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;codeEditor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;fetchEditedCode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;As you can see, all this tool needs in our context is a method and the new source code as a String to complete the operation. You can also see that we called the method &lt;code dir=&quot;auto&quot;&gt;fetchEditedCode&lt;/code&gt; on our code editor window, which returns the String present in the right window of said editor. Using this method ensures that you get the right data, even if the code was manually edited during its review.&lt;/p&gt;
&lt;p&gt;Once this tool has made its job and transformed the source code of your software, do keep in mind that the model of that software is no longer up to date with the source. This means that any analysis that you could run on this model could be flawed, so it is recommended to regularly replace that model with a new one, based from the source after it has been transformed.&lt;/p&gt;
&lt;p&gt;Hovewer, the model is slightly updated by the tool after each transformation applyed. The values of &lt;code dir=&quot;auto&quot;&gt;startPos&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;endPos&lt;/code&gt; on the source anchor of entities within the file which received a transformation. This means that their source code will still be properly fetched by Moose whenever you need it.&lt;/p&gt;
&lt;p&gt;For example, if your transformation tool relies mostly on the FAST models, this allows you to apply some transformations on several entities even if those are located in the same file without having to worry too much about the order in which you make those transformations.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;try-it-yourself&quot;&gt;Try it yourself!&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This concludes our blog post series about code transformation!&lt;/p&gt;
&lt;p&gt;We now have a tool managing every step of the way to complete a specific transformation case, from finding the necessary informations needed for the transformation, transforming a FAST model and using those transformed FAST models to view, edit and apply the transformations to the source code.&lt;/p&gt;
&lt;p&gt;Just like with the two other posts, feel free to now try the tool and methods that we created here in a Playground and experiment with the results, or the methods themselves!&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;t&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;LoggerTransformationTool&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;onModel:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MooseModel&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;root&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;first&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;t&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;findAndTransformAllLogErrorInvocations&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;img alt=&quot;&amp;#x22;Testing class&amp;#x22;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1082&quot; height=&quot;654&quot; src=&quot;https://modularmoose.org/_astro/testing-class.AdlQuLsW_1OsNaP.webp&quot;&gt;&lt;/p&gt;
&lt;p&gt;The whole source code that was written on the three blog posts is still available on that &lt;a href=&quot;https://github.com/RomainDeg/Moose-BlogPost-Transformation&quot;&gt;repository&lt;/a&gt;.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Through the use of tools to query and search through FAST models, transform said models, before generating, reviewing and applying the new code on the source files, we managed to build a fully functionnal and semi-automatic transformation tool for our use case!&lt;/p&gt;
&lt;p&gt;This use case was a rather small example.
A real transformation in a software would need more queries and FAST edits.
But the only real difference would be the scale. Using the methodology and tools in the same way that they were used in this blog post would be enough to apply to many use cases out there. 😄&lt;/p&gt;</content:encoded><category>transformation</category></item><item><title>Parametrics next generation</title><link>https://modularmoose.org/blog/2025-05-07-parametrics-next-generation/</link><guid isPermaLink="true">https://modularmoose.org/blog/2025-05-07-parametrics-next-generation/</guid><description>The Famix metamodel evolves</description><pubDate>Wed, 07 May 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;How do we represent the relation between a generic entity, its type parameters and the entities that concretize it? The Famix metamodel has evolved over the years to improve the way we represent these relations. The last increment is described in a previous &lt;a href=&quot;https://modularmoose.org/blog/2023-07-13-parametric&quot;&gt;blogpost&lt;/a&gt;.
We present here a new implementation that eases the management of parametric entities in Moose.&lt;/p&gt;
&lt;p&gt;The major change between this previous version and the new implementation presented in this post is this:
&lt;strong&gt;We do not represent the parameterized entities anymore&lt;/strong&gt;.&lt;/p&gt;
&lt;aside aria-label=&quot;Generic? Parametric? Parameterized? Know the difference&quot;&gt;&lt;p aria-hidden=&quot;true&quot;&gt;Generic? Parametric? Parameterized? Know the difference&lt;/p&gt;&lt;div&gt;&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;parametric entity&lt;/strong&gt; is an entity that declares type parameters or arguments. It can be generic or parameterized, according to the following definitions.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;generic entity&lt;/strong&gt; is an entity that defines 1 or several type parameters. To be instantiated, inherited, implemented or invoked, their type parameters must be replaced by existing types (type arguments). &lt;code dir=&quot;auto&quot;&gt;ArrayList&amp;#x3C;E&gt;&lt;/code&gt; is a generic class. In Famix Java, we represent generic classes, interfaces and methods.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;type parameter&lt;/strong&gt; is a parameter that must be replaced by an existing type in order to use the generic entity that defines it. In &lt;code dir=&quot;auto&quot;&gt;ArrayList&amp;#x3C;E&gt;&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;E&lt;/code&gt;  is a type parameter.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;parameterized entity&lt;/strong&gt; is a parametric entity for which the type parameters have been replaced by existing types. &lt;code dir=&quot;auto&quot;&gt;ArrayList&amp;#x3C;String&gt;&lt;/code&gt; is a parameterized class. Parameterized entities are not represented as entities in the new Famix implementation.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;type argument&lt;/strong&gt; is the type used to replace a type parameter. It can be any type, except primitive types. &lt;code dir=&quot;auto&quot;&gt;String&lt;/code&gt; is a type argument of &lt;code dir=&quot;auto&quot;&gt;ArrayList&amp;#x3C;String&gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;concretization&lt;/strong&gt; is a Famix association that represents the fact that a type parameter has been replaced by a type argument.&lt;/li&gt;
&lt;/ul&gt;&lt;aside aria-label=&quot;Please note&quot;&gt;&lt;p aria-hidden=&quot;true&quot;&gt;Please note&lt;/p&gt;&lt;div&gt;&lt;p&gt;In Famix, because parameterized entities are not represented anymore, “parametric” and “generic” can be used interchangeably to refer to generic entities.&lt;/p&gt;&lt;/div&gt;&lt;/aside&gt;&lt;/div&gt;&lt;/aside&gt;
&lt;div&gt;&lt;h2 id=&quot;whats-wrong-with-the-previous-parametrics-implementation&quot;&gt;What’s wrong with the previous parametrics implementation?&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;difference-between-parametric-and-non-parametric-entities&quot;&gt;Difference between parametric and non-parametric entities&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The major issue with the previous implementation was the difference between parametric and non-parametric entities in practice, particularly when trying to trace the inheritance tree.
Here is a concrete example: getting the superclass of the superclass of a class.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;For a non-parametric class, the sequence is straightforward: ask the inheritance for the superclass, repeat.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt=&quot;Getting super inheritances - Non-parametric entities.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;366&quot; height=&quot;236&quot; src=&quot;https://modularmoose.org/_astro/sequence-inheritance-non-parametric.JUSuPlpy_14CnCA.webp&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;For a parametric class (see the little code snippet below), there was an additional step, navigating through the concretization:&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;java.util.ArrayList&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;public class ArrayList&amp;#x3C;E&gt; { /* ... */ }&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MySpecializedList&lt;/span&gt;&lt;span&gt; extends &lt;/span&gt;&lt;span&gt;ArrayList&amp;#x3C;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; {}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;img alt=&quot;Getting super inheritances - Parametric entities.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;767&quot; height=&quot;323&quot; src=&quot;https://modularmoose.org/_astro/sequence-inheritance-parametric.Cp7HH0Fa_2xodl.webp&quot;&gt;&lt;/p&gt;
&lt;p&gt;This has caused many headaches to developers who wanted to browse a hierarchy: how do we keep track of the full hierarchy when it includes parametric classes? How to manage both situations without knowing if the classes will be parametric or not?
The same problem occurred to browse the implementations of parametric interfaces and the invocations of generic methods.&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;naming&quot;&gt;Naming&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The previous implementation naming choices were a little complex to grasp and did not match the standard vocabulary, especially in Java:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A type parameter was named a &lt;code dir=&quot;auto&quot;&gt;ParameterType&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;A type argument was named a &lt;code dir=&quot;auto&quot;&gt;ConcreteParameterType&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;entities-duplication&quot;&gt;Entities duplication&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Each time there was a concretization, a parametric entity was created. This created duplicates of virtually the same entity: one for the generic entity and &lt;strong&gt;one for each parameterized entity&lt;/strong&gt;.
Let’s see an example:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyClass&lt;/span&gt;&lt;span&gt; implements &lt;/span&gt;&lt;span&gt;List&amp;#x3C;&lt;/span&gt;&lt;span&gt;Float&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;List&amp;#x3C;&lt;/span&gt;&lt;span&gt;Integer&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;getANumber&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;List&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;Number&lt;/span&gt;&lt;span&gt;&gt; &lt;/span&gt;&lt;span&gt;listA&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;List&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;Integer&lt;/span&gt;&lt;span&gt;&gt; &lt;/span&gt;&lt;span&gt;listB&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;For the interface &lt;code dir=&quot;auto&quot;&gt;List&amp;#x3C;E&gt;&lt;/code&gt;, we had 6 parametric interfaces:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;One was the generic one: &lt;code dir=&quot;auto&quot;&gt;#isGeneric &gt;&gt;&gt; true&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;3 were the parameterized interfaces implemented by &lt;code dir=&quot;auto&quot;&gt;ArrayList&amp;#x3C;E&gt;&lt;/code&gt;, its superclass &lt;code dir=&quot;auto&quot;&gt;AbstractList&amp;#x3C;E&gt;&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;MyClass&lt;/code&gt;. They were different because the &lt;em&gt;concrete types&lt;/em&gt; were different: &lt;code dir=&quot;auto&quot;&gt;E&lt;/code&gt; from &lt;code dir=&quot;auto&quot;&gt;ArrayList&amp;#x3C;E&gt;&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;E&lt;/code&gt; from &lt;code dir=&quot;auto&quot;&gt;AbstractList&amp;#x3C;E&gt;&lt;/code&gt;and &lt;code dir=&quot;auto&quot;&gt;Float&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;2 were declared types: &lt;code dir=&quot;auto&quot;&gt;List&amp;#x3C;Number&gt;&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;List&amp;#x3C;Integer&gt;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h2 id=&quot;the-new-implementation&quot;&gt;The new implementation&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;parametric-associations&quot;&gt;Parametric associations&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;When deciding of a new implementation, our main goal was to create a situation in which the dependencies would work in the same way for all entities, parametric or not.
That’s where we introduce parametric associations. These associations only differ from standard associations by one property: they trigger a concretization.&lt;/p&gt;
&lt;p&gt;Here is the new Famix metamodel traits that represent concretizations:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Class diagram for Parametric Associations&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;713&quot; height=&quot;261&quot; src=&quot;https://modularmoose.org/_astro/uml-parametric-association.fXCQF5U9_6Lk40.webp&quot;&gt;&lt;/p&gt;
&lt;p&gt;There is a direct relation between a parametric entity and its type parameters.
A concretization is the association between a type parameter and the type argument that replaces it.
A parametric association triggers one or several concretizations, according to the number of type parameters the parametric entity has. Example: a parametric association that targets &lt;code dir=&quot;auto&quot;&gt;Map&amp;#x3C;K,V&gt;&lt;/code&gt; will trigger 2 concretizations.&lt;/p&gt;
&lt;p&gt;The parametric entity is the target of the parametric association. It is always generic. As announced, we do not represent parameterized entities anymore.
Coming back to the entities’ duplication example above, we now represent only 1 parametric interface for &lt;code dir=&quot;auto&quot;&gt;List&amp;#x3C;E&gt;&lt;/code&gt;and it is the target of the 5 parametric associations.&lt;/p&gt;
&lt;aside aria-label=&quot;Deprecation&quot;&gt;&lt;p aria-hidden=&quot;true&quot;&gt;Deprecation&lt;/p&gt;&lt;div&gt;&lt;p&gt;The previous testing API to check if an entity is parametric, generic or &lt;em&gt;concrete&lt;/em&gt; is now deprecated.
Please use the generated testing method &lt;code dir=&quot;auto&quot;&gt;#isParametricEntity&lt;/code&gt;.
You can also test if an association is parametric, using &lt;code dir=&quot;auto&quot;&gt;#isParametricAssociation&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;&lt;/aside&gt;
&lt;div&gt;&lt;h3 id=&quot;entity-typing&quot;&gt;Entity typing&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;This metamodel evolution is the occasion of another major change: the replacement of the direct relation between a typed entity and its type. This new association is called Entity typing.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Class diagram for Entity Typing&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;603&quot; height=&quot;71&quot; src=&quot;https://modularmoose.org/_astro/uml-entity-typing.DDPWOCX4_Z1xnFi4.webp&quot;&gt;&lt;/p&gt;
&lt;p&gt;The choice to replace the existing relation by a reified association is made to represent the dependency in coherence with the rest of the metamodel.&lt;/p&gt;
&lt;p&gt;With this new association, we can now add parametric entity typings.&lt;/p&gt;
&lt;p&gt;In a case like this:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ArrayList&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&gt; &lt;/span&gt;&lt;span&gt;myAttribute&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;we have an “entity typing” association between &lt;code dir=&quot;auto&quot;&gt;myAttribute&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;ArrayList&lt;/code&gt;. This association is parametric: it triggers the concretization of &lt;code dir=&quot;auto&quot;&gt;E&lt;/code&gt; in &lt;code dir=&quot;auto&quot;&gt;ArrayList&amp;#x3C;E&gt;&lt;/code&gt; by &lt;code dir=&quot;auto&quot;&gt;String&lt;/code&gt;.&lt;/p&gt;
&lt;aside aria-label=&quot;Deprecation&quot;&gt;&lt;p aria-hidden=&quot;true&quot;&gt;Deprecation&lt;/p&gt;&lt;div&gt;&lt;p&gt;The method &lt;code dir=&quot;auto&quot;&gt;#declaredType&lt;/code&gt; is still part of the API of &lt;code dir=&quot;auto&quot;&gt;TTypedEntity&lt;/code&gt;. However, it’s not a getter for the &lt;code dir=&quot;auto&quot;&gt;#declaredType&lt;/code&gt; attribute anymore. It now returns the type that is target of the association.&lt;/p&gt;&lt;p&gt;The setter &lt;code dir=&quot;auto&quot;&gt;#declaredType:&lt;/code&gt; is deprecated and cannot be automatically transformed. If you need to replace it, you should create an instance of the EntityTyping class in your metamodel and set the declared type as its target. You will have something like:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;myVariable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;myModel&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;newLocalVariableNamed:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#myVar&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;myType&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;myModel&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;newTypeNamed:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#MyType&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;myVariable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;typing:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;myModel&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;newEntityTyping&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;declaredType:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;myType&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;yourself&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/div&gt;&lt;/aside&gt;
&lt;div&gt;&lt;h3 id=&quot;type-parameters-bounds&quot;&gt;Type parameters bounds&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Type parameters can be bounded:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyParametricClass&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;extends&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Number&lt;/span&gt;&lt;span&gt;&gt; {}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;In the previous implementation, the bounds of type parameters were implemented as inheritances: in the example above, &lt;code dir=&quot;auto&quot;&gt;Number&lt;/code&gt; would be the superclass of &lt;code dir=&quot;auto&quot;&gt;T&lt;/code&gt;.
Since this change, bounds were introduced for wildcards.
We have now the occasion to also apply them to type parameters.
In the new implementation, &lt;code dir=&quot;auto&quot;&gt;Number&lt;/code&gt; is the upper bound of &lt;code dir=&quot;auto&quot;&gt;T&lt;/code&gt;.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This diagram sums up the new parametrics implementation in Famix traits and Java metamodel.
Please note that this is not the full Java metamodel but only a relevant part.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Class diagram for all changes&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1673&quot; height=&quot;818&quot; src=&quot;https://modularmoose.org/_astro/uml-new-parametrics-mm.BTiU1iMv_1BpMeh.webp&quot;&gt;&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;whats-next&quot;&gt;What’s next?&lt;/h2&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;should-concretization-really-be-an-association&quot;&gt;Should Concretization really be an association?&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;The representation of parametric entities is a challenge that will most likely continue as Famix evolves. The next question will probably be this one: should &lt;code dir=&quot;auto&quot;&gt;Concretization&lt;/code&gt; really be an association?
An association is the reification of a dependency. Yet, there is no dependency between a type argument and the type parameter it replaces. Each can exist without the other. The dependency is in fact between the source of the parametric association and the type parameter.&lt;/p&gt;
&lt;p&gt;With one of our previous examples:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MySpecializedList&lt;/span&gt;&lt;span&gt; extends &lt;/span&gt;&lt;span&gt;ArrayList&amp;#x3C;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; {}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;MySpecializedList&lt;/code&gt; has a superclass (&lt;code dir=&quot;auto&quot;&gt;ArrayList&amp;#x3C;E&gt;&lt;/code&gt;) and also depends on &lt;code dir=&quot;auto&quot;&gt;String&lt;/code&gt;, as a type argument. However, &lt;code dir=&quot;auto&quot;&gt;String&lt;/code&gt; does not depend on &lt;code dir=&quot;auto&quot;&gt;E&lt;/code&gt; neither &lt;code dir=&quot;auto&quot;&gt;E&lt;/code&gt; on &lt;code dir=&quot;auto&quot;&gt;String&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The next iteration of the representation of parametric entities will probably cover this issue. Stay tuned!&lt;/p&gt;</content:encoded><category>meta-model</category></item><item><title>Creating an importer for an alien grammar</title><link>https://modularmoose.org/blog/2025-03-26-visitor-external-grammar/</link><guid isPermaLink="true">https://modularmoose.org/blog/2025-03-26-visitor-external-grammar/</guid><description>Tricks to write a visitor for an alien AST, for example to build a Famix model from a Tree-sitter AST.</description><pubDate>Sat, 29 Mar 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In this blog-post, we see some tricks to create a visitor for an alien AST.
This visitor can allow, for example, to generate a Famix model from an external AST.&lt;/p&gt;
&lt;p&gt;In a previous blog-post, we saw how to &lt;a href=&quot;https://modularmoose.org/blog/2025-03-25-tree-sitter&quot;&gt;create a parser from a tree-sitter grammar&lt;/a&gt;.
This parser gives us an AST (Abstract Syntax Tree) which is a tree of nodes representing any given program that the parser can understand.
But the structure is decided by the external tool and might not be what we want.
For example it will not be a Famix model.&lt;/p&gt;
&lt;p&gt;Let see some tricks to help convert this alien grammar into something that better fits our needs.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;the-visitor-design-pattern&quot;&gt;The Visitor design pattern&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Let’s first look at what a “Visitor” is.
If you already know, you can skip this part.&lt;/p&gt;
&lt;p&gt;When dealing with ASTs or Famix models, visitors are very convenient tools to walk through the entire tree/model and perform some actions.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://en.wikipedia.org/wiki/Visitor_pattern&quot;&gt;Visitor&lt;/a&gt; is a design pattern that allows to perform some actions on a set of interconnected objects, presumably all from a family of classes.
Typically, the classes all belong to the same inheritance hierarchy.
In our case, the objects will all be nodes in an AST.
For Famix, the objects would be entities from a Famix meta-model.&lt;/p&gt;
&lt;p&gt;In the Visitor pattern, all the classes have an &lt;code dir=&quot;auto&quot;&gt;#accept:&lt;/code&gt; method.
Each &lt;code dir=&quot;auto&quot;&gt;#accept:&lt;/code&gt; in each class will call a visiting method of the visitor that is specific to it.
For example the classes &lt;code dir=&quot;auto&quot;&gt;NodeA&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;NodeB&lt;/code&gt; will respectively define:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;NodeA&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;accept:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aVisitor&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;aVisitor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;visitNodeA:&lt;/span&gt;&lt;span&gt; self&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;NodeB&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;accept:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aVisitor&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;aVisitor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;visitNodeB:&lt;/span&gt;&lt;span&gt; self&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Each visiting method in the visitor will with the element it receives, knowing what is its class: in &lt;code dir=&quot;auto&quot;&gt;#visitNodeA:&lt;/code&gt; the visitor knows how to deal with a &lt;code dir=&quot;auto&quot;&gt;NodeA&lt;/code&gt; instance and similarly for &lt;code dir=&quot;auto&quot;&gt;#visitNodeB:&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The visitor pattern is a kind of ping-pong between the visiting and &lt;code dir=&quot;auto&quot;&gt;#accept:&lt;/code&gt; methods:
&lt;img alt=&quot;ping-pong of visiting ans accept methods&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;250&quot; height=&quot;80&quot; src=&quot;https://modularmoose.org/_astro/visitor-pingpong.DkuQYj9x_1O00VV.webp&quot;&gt;&lt;/p&gt;
&lt;p&gt;Typically, all the node are interconnected in a tree or a graph.
To walk through the entire structure, it is expected that each visiting method take care of visiting the sub-objects of the current object.
For example we could say that &lt;code dir=&quot;auto&quot;&gt;NodeA&lt;/code&gt; has a property &lt;code dir=&quot;auto&quot;&gt;child&lt;/code&gt; containing another node:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;NodeVisitor&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;visitNodeA:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aNodeA&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;do some stuff&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;aNodeA&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;child&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;accept:&lt;/span&gt;&lt;span&gt; self&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;It is easy to see that if &lt;code dir=&quot;auto&quot;&gt;child&lt;/code&gt; contains a &lt;code dir=&quot;auto&quot;&gt;NodeB&lt;/code&gt;, this will trigger the visiting method &lt;code dir=&quot;auto&quot;&gt;visitNodeB:&lt;/code&gt; on it.
If it’s a instance of some other class, similarly it will trigger the appropriate visiting method.
To visit the entire structure one simply calls &lt;code dir=&quot;auto&quot;&gt;accept:&lt;/code&gt; on the root of the tree/graph passing it the visitor.&lt;/p&gt;
&lt;p&gt;Visitors are very useful with ASTs or graphs because once all the &lt;code dir=&quot;auto&quot;&gt;accept: &lt;/code&gt; methods are implemented, we can define very different visitors that will &lt;code dir=&quot;auto&quot;&gt;&quot;do some stuff&quot;&lt;/code&gt; (see above) on all the object in the tree/graph.&lt;/p&gt;
&lt;p&gt;Several of the &lt;a href=&quot;https://modularmoose.org/blog/tag/famix-tools/&quot;&gt;“Famix-tools”&lt;/a&gt; blog-posts are based on visitors.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;an-external-ast&quot;&gt;An external AST&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;In a &lt;a href=&quot;https://modularmoose.org/blog/2025-03-25-tree-sitter&quot;&gt;preceding blog-post&lt;/a&gt; we saw how to create an AST from a Perl program using the Tree-Sitter Perl grammar.&lt;/p&gt;
&lt;p&gt;We will use this as an example to see how to create a visitor on this external AST.
Here “external” means it was created by an external tool and we don’t have control on the structure of the AST.
If we want to create a Famix-Perl model from a Tree-Sitter AST, we will need to convert the nodes in the Tree-Sitter AST into Famix entities.&lt;/p&gt;
&lt;p&gt;We will use a simple Perl program as example:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;package&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Person&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;sub&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;my&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;$class&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;shift&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;my&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;$self&lt;/span&gt;&lt;span&gt; = {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;_firstName&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;shift&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;_lastName&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;shift&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;_ssn&lt;/span&gt;&lt;span&gt;       &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;shift&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# Print all the values just for clarification.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;First Name is &lt;/span&gt;&lt;span&gt;$self&lt;/span&gt;&lt;span&gt;-&gt;{_firstName}&lt;/span&gt;&lt;span&gt;\n&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;Last Name is &lt;/span&gt;&lt;span&gt;$self&lt;/span&gt;&lt;span&gt;-&gt;{_lastName}&lt;/span&gt;&lt;span&gt;\n&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;SSN is &lt;/span&gt;&lt;span&gt;$self&lt;/span&gt;&lt;span&gt;-&gt;{_ssn}&lt;/span&gt;&lt;span&gt;\n&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;bless&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;$self&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;$class&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;$self&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;sub&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;setFirstName&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;my&lt;/span&gt;&lt;span&gt; ( &lt;/span&gt;&lt;span&gt;$self&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;$firstName&lt;/span&gt;&lt;span&gt; ) = &lt;/span&gt;&lt;span&gt;@_&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;$self&lt;/span&gt;&lt;span&gt;-&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;_firstName&lt;/span&gt;&lt;span&gt;} = &lt;/span&gt;&lt;span&gt;$firstName&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;defined&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$firstName&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;$self&lt;/span&gt;&lt;span&gt;-&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;_firstName&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;sub&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;getFirstName&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;$self&lt;/span&gt;&lt;span&gt;-&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;_firstName&lt;/span&gt;&lt;span&gt;};&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;(Note: In Perl, “package” is used to create classes. Therefore in our example, “new”, “setFirstName”, and “getFirstName” are some kind of Perl methods.)&lt;/p&gt;
&lt;p&gt;Following the instructions in the previous post, you should be able to get a Tree-Sitter AST like this one:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;External AST from Tree-Sitter&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;275&quot; height=&quot;365&quot; src=&quot;https://modularmoose.org/_astro/external-AST.BmOk4wi7_ZqPkAM.webp&quot;&gt;&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;a-visitor-on-a-tree-sitter-ast&quot;&gt;A Visitor on a Tree-Sitter AST&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;To have a visitor for this AST, we first need to have an &lt;code dir=&quot;auto&quot;&gt;accept:&lt;/code&gt; method in all the classes of the AST’s nodes.
Fortunately this is all taken care of by the &lt;a href=&quot;https://github.com/Evref-BL/Pharo-Tree-Sitter&quot;&gt;Pharo Tree-Sitter&lt;/a&gt; project.
In &lt;code dir=&quot;auto&quot;&gt;TSNode&lt;/code&gt; one finds:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;accept:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTSVisitor&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTSVisitor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;visitNode:&lt;/span&gt;&lt;span&gt; self&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;And a class &lt;code dir=&quot;auto&quot;&gt;TSVisitor&lt;/code&gt; defines:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;visitNode:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTSNode&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;aTSNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;collectNamedChild&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;do:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;child&lt;/span&gt;&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;child&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;accept:&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Which is a method ensuring that all children of a &lt;code dir=&quot;auto&quot;&gt;TSNode&lt;/code&gt; will be visited.
Thanks guys!&lt;/p&gt;
&lt;p&gt;But less fortunately, there are very few different nodes in a Tree-Sitter AST.
Actually, all the nodes are instances of &lt;code dir=&quot;auto&quot;&gt;TSNode&lt;/code&gt;.
So the “subroutine_declaration_statement”, “block”, “expression_statement”, “return_expression”,… of our example are all of the same class, which is not very useful for a visitor.&lt;/p&gt;
&lt;p&gt;This happens quite often.
For example a parser dumping an AST in XML format will contain mostly XMLElements.
If it is in JSON, they are all “objects” without any native class specification in the format. 😒&lt;/p&gt;
&lt;p&gt;Fortunately, people building ASTs usually put inside a property with an indication of the type of each node.
For Tree-Sitter, this is the “type” property.
Every &lt;code dir=&quot;auto&quot;&gt;TSnode&lt;/code&gt; has a &lt;code dir=&quot;auto&quot;&gt;type&lt;/code&gt; which is what is displayed in the screenshot above.&lt;/p&gt;
&lt;p&gt;How can we use this to help visiting the AST in a meaningfull way (from a visitor point a view)?
We have no control on the &lt;code dir=&quot;auto&quot;&gt;accept:&lt;/code&gt; method in &lt;code dir=&quot;auto&quot;&gt;TSNode&lt;/code&gt;, it will always call &lt;code dir=&quot;auto&quot;&gt;visitNode:&lt;/code&gt;.
But we can add an extra indirection to call different visiting methods according to the &lt;code dir=&quot;auto&quot;&gt;type&lt;/code&gt; of the node.&lt;/p&gt;
&lt;p&gt;So, our visitor will inherit from &lt;code dir=&quot;auto&quot;&gt;TSVisitor&lt;/code&gt; but it will override the &lt;code dir=&quot;auto&quot;&gt;visitNode:&lt;/code&gt; method.
The new method will take the &lt;code dir=&quot;auto&quot;&gt;type&lt;/code&gt; of the node, build a visiting method name from it, and call the method on the node.&lt;/p&gt;
&lt;p&gt;Let’s decide that all our visiting methods will be called “visitPerl&amp;#x3C;some-type&gt;”.
For example for a “block”, the method will be &lt;code dir=&quot;auto&quot;&gt;visitPerlBlock:&lt;/code&gt;, for a “return_expression” it will be `visitPerlReturn_expression:”.&lt;/p&gt;
&lt;p&gt;This is very easily done in Pharo with this method:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;visitNode:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTSNode&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;selector&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;selector&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;visitPerl&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; , &lt;/span&gt;&lt;span&gt;aTSNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;capitalized&lt;/span&gt;&lt;span&gt; , &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;perform:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;selector&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;asSymbol&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;with:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTSNode&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This method builds the new method name in a temporary variable &lt;code dir=&quot;auto&quot;&gt;selector&lt;/code&gt; and then calls it using &lt;code dir=&quot;auto&quot;&gt;perform:with:&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Note that the &lt;code dir=&quot;auto&quot;&gt;type&lt;/code&gt; name is capitalized to match the Pharo convention for method names.
We could have removed all the underscores (_) but it would have required a little bit of extra work.
This is not difficult with string manipulation methods.
You could try it… (or you can continue reading and find the solution further down.)&lt;/p&gt;
&lt;p&gt;With this simple extra indirection in &lt;code dir=&quot;auto&quot;&gt;#visitNode:&lt;/code&gt;, we can now define separate visiting method for each type of &lt;code dir=&quot;auto&quot;&gt;TSNode&lt;/code&gt;.
For example to convert the AST to a Famix model, &lt;code dir=&quot;auto&quot;&gt;visitPerlPackage:&lt;/code&gt; would create a &lt;code dir=&quot;auto&quot;&gt;FamixPerlClass&lt;/code&gt;, and &lt;code dir=&quot;auto&quot;&gt;visitPerlSubroutine_declaration_statement:&lt;/code&gt; will create a &lt;code dir=&quot;auto&quot;&gt;FamixPerlMethod&lt;/code&gt;.
(Of course it is a bit more complex than that, but you got the idea, right?)&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;creating-the-visiting-methods&quot;&gt;Creating the visiting methods&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Our visitor is progressing but not done yet.
If we call &lt;code dir=&quot;auto&quot;&gt;astRootNode accept: TreeSitterPerlVisitor new&lt;/code&gt; with the root node of the Tree-Sitter AST, it will immediately halt on a DoesNotUnderstand error because the method &lt;code dir=&quot;auto&quot;&gt;visitPerlSource_file:&lt;/code&gt; does not exist in the visitor.&lt;/p&gt;
&lt;p&gt;We can create it that way:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;visitPerlSource_file:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTSNode&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitPerlAbstractNode:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTSNode&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;visitPerlAbstractNode:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTSNode&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt;super &lt;/span&gt;&lt;span&gt;visitNode:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTSNode&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Here we introduce a &lt;code dir=&quot;auto&quot;&gt;visitPerlAbstractNode:&lt;/code&gt; that is meant to be called by all visiting methods.
From the point of view of the visitor, we are kind of creating a virtual inheritance hierarchy where each specific &lt;code dir=&quot;auto&quot;&gt;TSNode&lt;/code&gt; will “inherit” from that “PerlAbstractNode”.
This will be useful in the future when we create sub-classes of our visitor.&lt;/p&gt;
&lt;p&gt;By calling &lt;code dir=&quot;auto&quot;&gt;super visitNode:&lt;/code&gt;, in &lt;code dir=&quot;auto&quot;&gt;visitPerlAbstractNode:&lt;/code&gt; we ensure that the children of the “source_file” will be visited.
And… we instantly get a new halt with DoesNotUnderstand: &lt;code dir=&quot;auto&quot;&gt;visitPerlPackage_statement:&lt;/code&gt;.
Again we define it:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;visitPerlPackage_statement:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTSNode&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitPerlAbstractNode:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTSNode&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This is rapidly becoming repetitive and tedious. There are a lot of methods to define (25 for our example) and they are all the same.&lt;/p&gt;
&lt;p&gt;Let’s improve that.
We will use the Pharo DoesNotUnderstand mechanism to automate everything.
When a message is sent that an object that does not understand it, then the message &lt;code dir=&quot;auto&quot;&gt;doesNotUnderstand:&lt;/code&gt; is sent to this object with the original message (not understood) as parameter.
The default behavior is to raise an exception, but we can change that.
We will change &lt;code dir=&quot;auto&quot;&gt;doesNotUnderstand:&lt;/code&gt; so that it creates the required message automatically for us.
This is easy all we need to do is create a string:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;visitPerl&amp;#x3C;some-name&gt;: aTSNode&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;^self visitPerlAbstractNode: aTSNode&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;We will then ask Pharo to compile this method in the Visitor class and to execute it.
&lt;em&gt;et voila!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Building the string is simple because the selector is the one that was not understood originally by the visitor.
We can get it from the argument of &lt;code dir=&quot;auto&quot;&gt;doesNotUnderstand:&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So we define the method like that:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;doesNotUnderstand:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aMessage&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;code&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;code&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aMessage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;selector&lt;/span&gt;&lt;span&gt; , &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; aTSNode&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;^super visitNode: aTSNode&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;compile:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;code&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;classified:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#visiting&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;perform:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aMessage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;selector&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;with:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aMessage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;arguments&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;first&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;First we generate the source code of the method in the &lt;code dir=&quot;auto&quot;&gt;code&lt;/code&gt; variable.
Then we compile it in the visitor’s class.
Last we call the new method that was just created.
Here to call it, we use &lt;code dir=&quot;auto&quot;&gt;perform:with:&lt;/code&gt; again, knowing that our method has only one argument (so only one “with:” in the call).&lt;/p&gt;
&lt;p&gt;For more security, it can be useful to add the following guard statement at the beginning of our &lt;code dir=&quot;auto&quot;&gt;doesNotUnderstand:&lt;/code&gt; method:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;aMessage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;selector&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;beginsWith:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;visitPerl&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;ifFalse:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; super &lt;/span&gt;&lt;span&gt;doesNotUnderstand:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aMessage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This ensures that we only create methods that begins with “visitPerl”, if for any reason, some other message is not understood, it will raise an exception as usual.&lt;/p&gt;
&lt;p&gt;Now visiting the AST from our example creates all the visiting methods automatically:
&lt;img alt=&quot;All the visiting method created&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;705&quot; height=&quot;556&quot; src=&quot;https://modularmoose.org/_astro/all-visit-methods.C5-y7uI1_Z2gEDTx.webp&quot;&gt;&lt;/p&gt;
&lt;p&gt;Of course this visitor does not do anything but walking through the entire AST.
Let’s say it is already a good start and we can create specific visitors from it.&lt;/p&gt;
&lt;p&gt;For example we see in the screen shot above that there is a &lt;code dir=&quot;auto&quot;&gt;TreeSitterPerlDumpVisitor&lt;/code&gt;.
It just dumps on the Transcript the list of node visited.
For this, it only needs to define:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;visitPerlAbstractNode:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTSNode&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;visiting a &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;aTSNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;traceCr&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;super &lt;/span&gt;&lt;span&gt;visitPerlAbstractNode:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTSNode&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;Et voila!&lt;/em&gt; (number 2)&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note: Redefining  &lt;code dir=&quot;auto&quot;&gt;doesNotUnderstand:&lt;/code&gt; is a nice trick to quickly create all the visiting methods, but it is recommended that you remove it once the visitor is stable, to make sure you catch all unexpected errors in the future.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div&gt;&lt;h2 id=&quot;better-visiting-methods&quot;&gt;Better visiting methods&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;This is all well and good, but the visiting methods have one drawback:
They visit the children of a node in an unspecified order.
For example, an “assignment_expression” has two children, the variable assigned and the expression assigned to it.
We must rely on Tree-Sitter to visit them in the right order so that the first child is always the variable assigned and the second child is always the right-hand-side expression.&lt;/p&gt;
&lt;p&gt;It would be better to have a name for these children so as to make sure that we know what we are visiting at any time.&lt;/p&gt;
&lt;p&gt;In this case, Tree-Sitter helps us with the &lt;code dir=&quot;auto&quot;&gt;collectFieldNameOfNamedChild&lt;/code&gt; method of &lt;code dir=&quot;auto&quot;&gt;TSNode&lt;/code&gt;.
This method returns an &lt;code dir=&quot;auto&quot;&gt;OrderedDictionary&lt;/code&gt; where the children are associated to a (usually) meaningful key.
In the case of  “assignment_expression” the dictionary has two keys: “left” and “right” each associated to the correct child.
It would be better to call them instead of blindly visit all the children.&lt;/p&gt;
&lt;p&gt;So we will change our visitor for this.
The &lt;code dir=&quot;auto&quot;&gt;visitNode:&lt;/code&gt; method will now call the visiting method with the dictionnary of keys/children as second parameter, the dictionnary of fields.
This departs a bit from the traditional visitor pattern where the visiting methods usually have only one argument, the node being visited.
But the extra information will help make the visiting methods simpler:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;visitNode:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTSNode&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;selector&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;selector&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;streamContents:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;st&lt;/span&gt;&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;st&lt;/span&gt;&lt;span&gt; &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;visitPerl&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$_&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;split:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTSNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;do:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;word&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;st&lt;/span&gt;&lt;span&gt; &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span&gt;word&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;capitalized&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;st&lt;/span&gt;&lt;span&gt; &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;:withFields:&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;perform:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;selector&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;asSymbol&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;with:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTSNode&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;with:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTSNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;collectFieldNameOfNamedChild&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;It looks significantly more complex, but we also removed the underscores (_) in the visiting method selector (first part of the &lt;code dir=&quot;auto&quot;&gt;#visitNode:&lt;/code&gt; method).
So for “assignment_expression”, the visiting method will now be: &lt;code dir=&quot;auto&quot;&gt;visitPerleAssignmentExpression:withFields:&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;From this, we could have the following template for our visiting methods:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;visitPerlAssignmentExpression:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTSNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;withFields:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;fields&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitKey:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;left&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;inDictionnary:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;fields&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;visitKey:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;right&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;inDictionnary:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;fields&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Where &lt;code dir=&quot;auto&quot;&gt; visitKey: inDictionnary:&lt;/code&gt; takes care of the fact that several nodes may be associated to the same key.
Here it is:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;visitKey:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aKey&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;inDictionnary:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;childrenDictionnary&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;child&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;child&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;childrenDictionnary&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;at:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aKey&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ifAbsent:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt;child&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;isCollection&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;ifTrue:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;child&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;collect:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;accept:&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;ifFalse:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;child&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;accept:&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code dir=&quot;auto&quot;&gt;doesNotUnderstand:&lt;/code&gt; method to generate all this is also more complex because there is more to generate.
Here it is:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;doesNotUnderstand:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aMessage&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;aMessage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;selector&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;beginsWith:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;visitPerl&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;ifFalse:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; super &lt;/span&gt;&lt;span&gt;doesNotUnderstand:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aMessage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;compile:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;self &lt;/span&gt;&lt;span&gt;createVisitMethod:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aMessage&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;classified:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#visiting&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;perform:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aMessage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;selector&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;with:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aMessage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;arguments&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;first&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;with:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aMessage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;arguments&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;second&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The code generation has been extracted in a separate method for the sake of readability:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;createVisitMethod:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aMessage&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;| &lt;/span&gt;&lt;span&gt;fields&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTSNode&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;aTSNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aMessage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;arguments&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;first&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;fields&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aMessage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;arguments&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;second&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;streamContents:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;str&lt;/span&gt;&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;str&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;visitPerl&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$_&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;split:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;aTSNode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;do:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;word&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;str&lt;/span&gt;&lt;span&gt; &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span&gt;word&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;capitalized&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;str&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;: aTSNode withFields: fields&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;^{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;fields&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;keysDo:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;key&lt;/span&gt;&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;str&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;    self visitKey: &lt;/span&gt;&lt;span&gt;&apos;&apos;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span&gt;key&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span&gt;&apos;&apos;&apos;&lt;/span&gt;&lt;span&gt; inDictionnary: fields.&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;cr&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;str&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;  }&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;cr&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Again, it may look a bit complex, but this is only building a string with the needed source code. Go back to the listing of &lt;code dir=&quot;auto&quot;&gt;#visitPerlAssignmentExpression:&lt;/code&gt; above to see that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;we first build the selector of the new visiting method with its parameter;&lt;/li&gt;
&lt;li&gt;then we put a return and start a dynamic array;&lt;/li&gt;
&lt;li&gt;after that we create a call to &lt;code dir=&quot;auto&quot;&gt;#visitKey:inDictionnary&lt;/code&gt; for each field;&lt;/li&gt;
&lt;li&gt;and finally,  we close the dynamic array.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Et voila!&lt;/em&gt; (number 3).&lt;/p&gt;
&lt;p&gt;This is it.
If we call again this visitor on an AST from Tree-Sitter, it will generate all the new visiting methods with explicit field visiting.
For example:
&lt;img alt=&quot;Explicit visiting of a node&amp;#x27;s fields&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;785&quot; height=&quot;408&quot; src=&quot;https://modularmoose.org/_astro/final-subroutine-declaration.BeJFAs2t_1uYTnT.webp&quot;&gt;&lt;/p&gt;
&lt;p&gt;The implementation of all this can be found in the &lt;a href=&quot;https://github.com/moosetechnology/Famix-Perl&quot;&gt;https://github.com/moosetechnology/Famix-Perl&lt;/a&gt; repository on github.
All that’s  left to do is create a sub-class of this visitor and override the visiting methods to do something useful with each node type.&lt;/p&gt;
&lt;p&gt;That’s all for today folks.&lt;/p&gt;</content:encoded><category>infrastructure</category></item><item><title>Creating a Parser based on Tree-Sitter grammar</title><link>https://modularmoose.org/blog/2025-03-25-tree-sitter/</link><guid isPermaLink="true">https://modularmoose.org/blog/2025-03-25-tree-sitter/</guid><description>Create a parser for a new language in Pharo based on a Tree-sitter grammar.</description><pubDate>Tue, 25 Mar 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Moose is a huge consumer of language parsers.
Relying on external tools help us with this.&lt;/p&gt;
&lt;p&gt;We are always looking into integrating new programming languages into the platform.
There are two main requirements for this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;create a parser of the language, to “understand” the source code&lt;/li&gt;
&lt;li&gt;create a meta-model for the language, to be able to represent and manipulate the source code&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Creating the meta-model has already been covered in an other blogpost: &lt;a href=&quot;https://modularmoose.org/blog/2021-02-04-coasters&quot;&gt;/blog/2021-02-04-coasters&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In this post, we will be looking at how to use a Tree-Sitter grammar to help build a parser for a language.
We will use the Perl language example for this.&lt;/p&gt;
&lt;p&gt;Note: Creating a parser for a language is a large endehavour that can easily take 3 to 6 months of work.
Tree-Sitter, or any other grammar tool, will help in that, but it remains a long task.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;getting-the-tree-sitter-grammar&quot;&gt;Getting the Tree-Sitter grammar&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;We do not explain in detail here how to install tree-sitter or a new Tree-Sitter grammar.
I found this page (&lt;a href=&quot;https://dcreager.net/2021/06/getting-started-with-tree-sitter/&quot;&gt;https://dcreager.net/2021/06/getting-started-with-tree-sitter/&lt;/a&gt;) useful in this sense.&lt;/p&gt;
&lt;p&gt;For this blog post, we will use the Perl grammar in &lt;a href=&quot;https://github.com/tree-sitter-perl/tree-sitter-perl&quot;&gt;https://github.com/tree-sitter-perl/tree-sitter-perl&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Do the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;clone the repository on your disk&lt;/li&gt;
&lt;li&gt;go in the directory&lt;/li&gt;
&lt;li&gt;do &lt;code dir=&quot;auto&quot;&gt;make&lt;/code&gt; (note: it gave me some error, but the library file was generated all the same)&lt;/li&gt;
&lt;li&gt;(on Linux) it creates a &lt;code dir=&quot;auto&quot;&gt;libtree-sitter-perl.so&lt;/code&gt; dynamic library file.
This must be moved in some standard library path (I chose &lt;code dir=&quot;auto&quot;&gt;/usr/lib/x86_64-linux-gnu/&lt;/code&gt; because this is where the &lt;code dir=&quot;auto&quot;&gt;libtree-sitter.so&lt;/code&gt; file was).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pharo uses FFI to link to the grammar library, that’s why it’s a good idea to put it in a standard directory.
You can also put this library file in the same directory as your Pharo image, or in the directory where the Pharo launcher puts the virtual machines.&lt;/p&gt;
&lt;p&gt;The subclasses of &lt;code dir=&quot;auto&quot;&gt;FFILibraryFinder&lt;/code&gt; can tell you what are the standard directories on your installation.
For example on Linux, &lt;code dir=&quot;auto&quot;&gt;FFIUnix64LibraryFinder new paths&lt;/code&gt; returns a list of paths that includes &lt;code dir=&quot;auto&quot;&gt;&apos;/usr/lib/x86_64-linux-gnu/&apos;&lt;/code&gt; where we did put our grammar.so file.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;binding-tree-sitter-in-pharo&quot;&gt;Binding tree-sitter in Pharo&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;We use the Pharo-Tree-Sitter project (&lt;a href=&quot;https://github.com/Evref-BL/Pharo-Tree-Sitter&quot;&gt;https://github.com/Evref-BL/Pharo-Tree-Sitter&lt;/a&gt;) of Berger-Levrault, created by Benoit Verhaeghe, a regular contributor to Moose and this blog.
You can import this project in a Moose image following the README instructions.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Metacello&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;baseline:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;TreeSitter&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;repository:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;github://Evref-BL/Pharo-Tree-Sitter:main/src&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;load&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The README file of Pharo-Tree-Sitter gives an example of how to use it for Python:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;parser&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TSParser&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;tsLanguage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TSLanguage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;python&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;parser&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;language:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tsLanguage&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;[...]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;We want to have the same thing for Perl, so we will need to define a &lt;code dir=&quot;auto&quot;&gt;TSLanguage class &gt;&gt; #perl&lt;/code&gt; method.
Let’s take a look at how it’s done in Python:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;TSLanguage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;#python&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TSPythonLibrary&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;uniqueInstance&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tree_sitter_python&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;It’s easy to do something similar for perl:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;TSLanguage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &gt;&gt; &lt;/span&gt;&lt;span&gt;#perl&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TSPerlLibrary&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;uniqueInstance&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tree_sitter_perl&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;But we need to define the &lt;code dir=&quot;auto&quot;&gt;TSPerlLibrary&lt;/code&gt; class.
Again let’s look at how it’s done for Python and copy that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;create a &lt;code dir=&quot;auto&quot;&gt;TreeSitter-Perl&lt;/code&gt; package&lt;/li&gt;
&lt;li&gt;create a &lt;code dir=&quot;auto&quot;&gt;TSPerlLibrary&lt;/code&gt; class in it inheriting from &lt;code dir=&quot;auto&quot;&gt;FFILibrary&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;define the class method:
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;tree_sitter_perl&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; self &lt;/span&gt;&lt;span&gt;ffiCall:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;TSLanguage * tree_sitter_perl ()&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;and define the class methods for FFI (here for Linux):
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;unix64LibraryName&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;^&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FFIUnix64LibraryFinder&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;findAnyLibrary:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;#( &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;libtree-sitter-perl.so&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; )&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Notice that we gave the name of the dynamic library file created above (&lt;code dir=&quot;auto&quot;&gt;libtree-sitter-perl.so&lt;/code&gt;).
If this file is in a standard library directory, FFI will find it.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;a-first-pharo-ast&quot;&gt;A first Pharo AST&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;We can now experiment “our” parser on a small example:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;parser&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TSParser&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;tsLanguage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TSLanguage&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;perl&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;parser&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;language:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tsLanguage&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;# this is a comment&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;my $var = 5;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;tree&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;parser&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;parseString:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;tree&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rootNode&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This gives you the following window:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&amp;#x22;A first Tree-Sitter AST for Perl&amp;#x22;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;286&quot; height=&quot;273&quot; src=&quot;https://modularmoose.org/_astro/first-AST.CZU8rSz0_Z1fRLyH.webp&quot;&gt;&lt;/p&gt;
&lt;p&gt;That looks like a very good start!&lt;/p&gt;
&lt;p&gt;But we are still a long way from home.
Let’s look at a node of the tree for fun.&lt;/p&gt;
&lt;p&gt;&lt;code dir=&quot;auto&quot;&gt;node := tree rootNode firstNamedChild&lt;/code&gt; will give you the first node in the AST (the comment).
If we inspect it, we see that it is a &lt;code dir=&quot;auto&quot;&gt;TSNode&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;we can get its type: &lt;code dir=&quot;auto&quot;&gt;node type&lt;/code&gt; returns the string &lt;code dir=&quot;auto&quot;&gt;&apos;comment&apos;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;node nextSibling&lt;/code&gt; returns the next TSNode, the “expression-statement”&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;node startPoint&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;node endPoint&lt;/code&gt; tell you where in the source code this node is located.
It returns instances of &lt;code dir=&quot;auto&quot;&gt;TSPoint&lt;/code&gt;:
&lt;ul&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;node startPoint row&lt;/code&gt; = 0 (0 indexed)&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;node startPoint column&lt;/code&gt; = 0&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;node endPoint row&lt;/code&gt; = 0&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;node endPoint column&lt;/code&gt; = 19
That is to say the node is on the first row, extending from column 0 to 19.
With this, one could get the text associated to the node from the original source code.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That’s it for today.
In a following post we will look at doing something with this AST using the Visitor design pattern.&lt;/p&gt;
&lt;p&gt;See you latter&lt;/p&gt;</content:encoded><category>infrastructure</category></item><item><title>First look at GitProjectHealth</title><link>https://modularmoose.org/blog/2025-03-17-first-look-at-gitprojecthealth/</link><guid isPermaLink="true">https://modularmoose.org/blog/2025-03-17-first-look-at-gitprojecthealth/</guid><description>Explore the git history of a project with GitProjectHealth to understand how it evolves.</description><pubDate>Mon, 24 Mar 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;When it comes to understand a software system, we are often focusing on the software artifact itself.
What are the classes? How they are connected with each other?&lt;/p&gt;
&lt;p&gt;In addition to this analysis of the system, it can be interesting to explore how the system evolves through time.
To do so, we can exploit its git history.
In Moose, we developed the project &lt;a href=&quot;https://modularmoose.org/users/git-project-health/getting-started-with-gitproject-health/&quot;&gt;GitProjectHealth&lt;/a&gt; that enables the analysis of git history for projects hosted by GitHub, GitLab, or BitBucket.
The project also comes with a set of metrics one could use directly.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;first-use-of-gitprojecthealth&quot;&gt;First use of GitProjectHealth&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;GitProjectHealth is available in the last version of Moose, it can be easily installed using a Metacello script in a playground.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;Metacello&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;repository:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;github://moosetechnology/GitProjectHealth:main/src&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;baseline:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;GitLabHealth&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;onConflict:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;ex&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;ex&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;useIncoming&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;onUpgrade:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;ex&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;ex&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;useIncoming&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;onDowngrade:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;ex&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;ex&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;useLoaded&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;load&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h2 id=&quot;example-on-famix&quot;&gt;Example on Famix&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;For this first blog post, we will experiment GitProjectHealth on the &lt;a href=&quot;https://github.com/moosetechnology/Famix&quot;&gt;Famix&lt;/a&gt; project.
Since this project is a GitHub project, we first create a &lt;a href=&quot;https://github.com/settings/tokens&quot;&gt;GitHub token&lt;/a&gt; that will give GitProjectHealth the necessary authorization.&lt;/p&gt;
&lt;p&gt;Then, we import the moosetechnology group (that hosts the Famix project).&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;glhModel&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GLHModel&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;githubImporter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GithubModelImporter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;glhModel:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;glhModel&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;privateToken:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;&amp;#x3C;private token&gt;&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;yourself&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;githubImporter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;withCommitsSince:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;(Date&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;today&lt;/span&gt;&lt;span&gt; - &lt;/span&gt;&lt;span&gt;100&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;days&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;group&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;githubImporter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;importGroup:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;moosetechnology&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This first step allows us to get first information on projects.
For instance, by inspecting the group, we can select the “Group quality” view and see the group projects and the last status of their pipelines.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Group Quality view for moosetechnology&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1684&quot; height=&quot;602&quot; src=&quot;https://modularmoose.org/_astro/group-quality-moosetechnology.CNkjTRnL_Z1A4zBH.webp&quot;&gt;&lt;/p&gt;
&lt;p&gt;Then, by navigating to the Famix project and &lt;em&gt;its repository&lt;/em&gt;, you can view the Commits History.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;alt text&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;923&quot; height=&quot;566&quot; src=&quot;https://modularmoose.org/_astro/famix-git-history.BXidQgl7_1IPOQK.webp&quot;&gt;.&lt;/p&gt;
&lt;p&gt;It is also possible to explore the recent commit distribution by date and author&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;commit distribution&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;888&quot; height=&quot;519&quot; src=&quot;https://modularmoose.org/_astro/commit-distribution.CUtFeh7N_Z1aV5jv.webp&quot;&gt;.&lt;/p&gt;
&lt;p&gt;In this visualization, we discover that the most recent contributors are “Clotilde Toullec” and “CyrilFerlicot”.
The &lt;em&gt;“nil”&lt;/em&gt; refers to a commit authors that did not fill GitHub with their email. It is &lt;em&gt;anquetil&lt;/em&gt; (probably the same person as “Nicolas Anquetil”).
The square without name is probably someone that did not fill correctly the local git config for username.&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;who-modified-my-code---code-churn&quot;&gt;Who modified my code? - code churn&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;A popular metric when looking at git history is the code churn.
Code churn refer to edit of code introduced in the past.
It corresponds to the percentage of code introduced in a commit and then modified in other comments during a time period (e.g in the next week).
However many code churn definitions exit.&lt;/p&gt;
&lt;p&gt;The first step is thus to discover what commits modified my code.
To do so, we implemented in GitProjectHealth information about diff in commit.&lt;/p&gt;
&lt;p&gt;To extract this information, we first ask GitProjectHealth to extract more information for the commits of the famix project.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;famix&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;group&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;projects&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;detect:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;project&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;project&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;Famix&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&quot;I want to go deeper in analysis for famix repository, so I complete commit import of this project&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;githubImporter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;withCommitDiffs:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;famix&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;repository&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;commits&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;do:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;commit&lt;/span&gt;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;githubImporter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;completeImportedCommit:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;commit&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;].&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Then, when inspecting a commit, it is possible to switch to the “Commits tree” view.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Commit Tree&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1903&quot; height=&quot;816&quot; src=&quot;https://modularmoose.org/_astro/commit-tree.CFTfAIfD_9BleB.webp&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here how to read to above example&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The orange square “Remove TClassWithVisibility…” is the inspected commit.&lt;/li&gt;
&lt;li&gt;The gray square is the parent commit of the selected ones.&lt;/li&gt;
&lt;li&gt;The red squares are subsequent commits that modify at least one file in common with the inspected commit&lt;/li&gt;
&lt;li&gt;The green squares are commits that modifies other part of the code&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Based on this example, we see that &lt;em&gt;Clotilde Toullec&lt;/em&gt; modifies code introduced in selected commits in three next commits.
Two are Merged Pull Request.
This can represent linked work or at least actions on the same module of the application.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Can we go deeper in the analysis?&lt;/em&gt;&lt;/p&gt;
&lt;div&gt;&lt;h2 id=&quot;connect-gitprojecthealth&quot;&gt;Connect GitProjectHealth&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;It is possible to go even deeper in the analysis by connecting GitProjectHealth with other analysis.
This is possible by &lt;a href=&quot;https://modularmoose.org/developers/create-new-metamodel#introducing-submetamodels&quot;&gt;connecting metamodels&lt;/a&gt;.
For instance, it is possible to link GitProjectHealth with Jira system, of Famix models.
You can look at the first general documentation, or stay tune for the next blog post about GitProjectHealth!&lt;/p&gt;</content:encoded><category>Famix-tools</category><category>Mining Software Repositories</category></item><item><title>Control Flow Graph for FAST Fortran</title><link>https://modularmoose.org/blog/2025-03-08-cfg-for-fast-fortran/</link><guid isPermaLink="true">https://modularmoose.org/blog/2025-03-08-cfg-for-fast-fortran/</guid><description>Build and visualize a Control Flow Graph from a FAST Fortran model.</description><pubDate>Sat, 08 Mar 2025 00:00:00 GMT</pubDate><content:encoded>&lt;div&gt;&lt;h2 id=&quot;a-control-flow-graph-analysis-for-fast-fortran&quot;&gt;A Control Flow Graph analysis for FAST Fortran&lt;/h2&gt;&lt;/div&gt;
&lt;p&gt;Control Flow Graphs (CFG) are a common tool for static analyzis of a computation unit (eg. a method) and find some errors (unreachable code, infinite loops)&lt;/p&gt;
&lt;p&gt;It is based on the concept of &lt;em&gt;Basic Block&lt;/em&gt;: a sequence of consecutive statements in which flow of control can only enter at the beginning and leave at the end. Only the last statement of a basic block can be a branch statement and only the first statement of a basic block can be a target of a branch.&lt;/p&gt;
&lt;p&gt;There are two distinctive basic blocks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Start Block: The entry block allows the control to enter into the control flow graph. There should be only one start block.&lt;/li&gt;
&lt;li&gt;Final Block: Control flow leaves through the exit block. There may be several final blocks.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The package &lt;code dir=&quot;auto&quot;&gt;FAST-Fortran-Analyses&lt;/code&gt; in &lt;a href=&quot;https://github.com/moosetechnology/FAST-Fortran&quot;&gt;https://github.com/moosetechnology/FAST-Fortran&lt;/a&gt; contains classes to build a CFG of a Fortran program unit (a main program, a function, or a subroutine).&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;creating-the-fast-model&quot;&gt;Creating the FAST Model&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;We must first create a FAST model of a Fortran program.
For this we need an external parser.
We currently use &lt;code dir=&quot;auto&quot;&gt;fortran-src-extras&lt;/code&gt; from &lt;a href=&quot;https://github.com/camfort/fortran-src-extras&quot;&gt;https://github.com/camfort/fortran-src-extras&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To run it on a fortran file you do:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;fortran&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;src&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;extras&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;serialize&lt;/span&gt;&lt;span&gt; -&lt;/span&gt;&lt;span&gt;t&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;json&lt;/span&gt;&lt;span&gt; -&lt;/span&gt;&lt;span&gt;v77l&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;encode&lt;/span&gt;&lt;span&gt; &amp;#x3C;&lt;/span&gt;&lt;span&gt;fortran&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;file&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This will produce a json AST of the program that we can turn into a FAST-Fortran AST.&lt;/p&gt;
&lt;p&gt;If you have fortran-src-extras installed on your computer, all this is automated in FAST-Fortran&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;fortran&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;file&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&gt; &lt;/span&gt;&lt;span&gt;asFileReference&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;readStreamDo:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;st&lt;/span&gt;&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;FortranProjectImporter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;getFASTFor:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;st&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;contents&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;This script will create an array of ASTs from the &amp;#x3C;fortran-file.f&gt; given fortran file.
If there are several program units in the file, there will be several FAST models in this array.
In the example below, there is only one program, so the list contains only the AST for this program.&lt;/p&gt;
&lt;p&gt;We will use the following Fortran-77 code:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;PROGRAM EUCLID&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;*     Find greatest common divisor using the Euclidean algorithm&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;PRINT *, &apos;A?&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;READ *, NA&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;IF (NA.LE.0) THEN&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;PRINT *, &apos;A must be a positive integer.&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;STOP&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;END IF&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;PRINT *, &apos;B?&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;READ *, NB&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;IF (NB.LE.0) THEN&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;PRINT *, &apos;B must be a positive integer.&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;STOP&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;END IF&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;IA = NA&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;IB = NB&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;1   IF (IB.NE.0) THEN&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ITEMP = IA&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;IA = IB&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;IB = MOD(ITEMP, IB)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;GOTO 1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;END IF&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;PRINT *, &apos;The GCD of&apos;, NA, &apos; and&apos;, NB, &apos; is&apos;, IA, &apos;.&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;STOP&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;END&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div&gt;&lt;h3 id=&quot;creating-the-cfg&quot;&gt;Creating the CFG&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;From the FAST model above, we will now create a Control-Flow-Graph:&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;FAST&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;model&lt;/span&gt;&lt;span&gt;&gt; &lt;/span&gt;&lt;span&gt;accept:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;FASTFortranCFGVisitor&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The class &lt;code dir=&quot;auto&quot;&gt;FASTFortranCFGVisitor&lt;/code&gt; implements an algorithm to compute basic blocks from &lt;a href=&quot;https://en.wikipedia.org/wiki/Basic_block&quot;&gt;https://en.wikipedia.org/wiki/Basic_block&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This visitor goes throught the FAST model and creates a list of basic blocks that can be inspected with the &lt;code dir=&quot;auto&quot;&gt;#basicBlocks&lt;/code&gt; method.&lt;/p&gt;
&lt;p&gt;There is a small hierarchy of basic block classes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;FASTFortranAbstractBasicBlock&lt;/code&gt;, the root of the hierarchy.
It contains &lt;code dir=&quot;auto&quot;&gt;#statements&lt;/code&gt; (which are FAST statement nodes).
It has methods to test its nature: &lt;code dir=&quot;auto&quot;&gt;isStart&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;isFinal&lt;/code&gt;, &lt;code dir=&quot;auto&quot;&gt;isConditional&lt;/code&gt;.
It defines an abstract method &lt;code dir=&quot;auto&quot;&gt;#nextBlocks&lt;/code&gt; that returns a list of basic blocks that this one can directly reach.
Typically there are  1 or 2 next blocks, but Fortran can have more due to “arithmetic IF”, “computed GOTO” and “assigned GOTO” statements.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;FASTFortranBasicBlock&lt;/code&gt;, a common basic block with no branch statement.
If it is final, its  &lt;code dir=&quot;auto&quot;&gt;#nextBlocks&lt;/code&gt; is empty, otherwise it’s a list of 1 block.&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;FASTFortranConditionalBasicBlock&lt;/code&gt;, a conditional basic block.
It may reach several &lt;code dir=&quot;auto&quot;&gt;#nextBlocks&lt;/code&gt;, each one associated with a value, for example &lt;code dir=&quot;auto&quot;&gt;true&lt;/code&gt; and &lt;code dir=&quot;auto&quot;&gt;false&lt;/code&gt;.
The method &lt;code dir=&quot;auto&quot;&gt;#nextBlockForValue:&lt;/code&gt; returns the next block associated to a given value.
In our version of CFG, a conditional block may only have one statement (a conditional statement).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You may have noticed that our blocks are a bit different from the definition given at the beginning of the blog-post:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;our “common” blocs cannot have several next, they never end with a conditional statement;&lt;/li&gt;
&lt;li&gt;our conditional blocks can have only one statement.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For the program above, the CFG has 10 blocks.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the first block is a common block and contains 2 statements, the PRINT and the READ;&lt;/li&gt;
&lt;li&gt;its next bloc is a conditional block for the IF.
It has 2 next blocs:
&lt;ul&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;true&lt;/code&gt; leads to a common block with 2 statements, the PRINT and the STOP. This is a final block (STOP ends the program);&lt;/li&gt;
&lt;li&gt;&lt;code dir=&quot;auto&quot;&gt;false&lt;/code&gt; leads to the common block after the IF&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;visualize-the-cfg&quot;&gt;Visualize the CFG&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;As a first analysis tool, we can visualize the CFG.
Inspecting the result of the next script will open a Roassal visualization on the CFG contained in the &lt;code dir=&quot;auto&quot;&gt;FASTFortranCFGVisitor&lt;/code&gt;.&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;span&gt;FASTFortranCFGVisualization&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;on:&lt;/span&gt;&lt;span&gt; &amp;#x3C;&lt;/span&gt;&lt;span&gt;aFASTFortranCFGVisitor&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;For the program above, this gives the visualization below.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the dark dot is the starting block (note that it is a block and contains statements);&lt;/li&gt;
&lt;li&gt;the hollow dots are final blocks;&lt;/li&gt;
&lt;li&gt;it’s not the case here, but a block may also be start and final (if there are no conditional blocks in the program) and this would be represented by a “target”, a circle with a dot inside;&lt;/li&gt;
&lt;li&gt;a grey square is a comon block;&lt;/li&gt;
&lt;li&gt;a blue square is a conditional block;&lt;/li&gt;
&lt;li&gt;hovering the mouse on a block will bring a pop up with the list of its statements (this relies on the &lt;code dir=&quot;auto&quot;&gt;FASTFortranExporterVisitor&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt=&quot;&amp;#x22;Viualizing the Control Flow Graph&amp;#x22;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;236&quot; height=&quot;381&quot; src=&quot;https://modularmoose.org/_astro/the-CFG.BXkC-Yvs_27p07N.webp&quot;&gt;&lt;/p&gt;
&lt;p&gt;One can see that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the start block has 2 associated statements (PRINT and READ);&lt;/li&gt;
&lt;li&gt;there are several final blocks, due to the STOP statements;&lt;/li&gt;
&lt;li&gt;there is a loop at the bottom left of the graph where the last blue conditional block is “IF (IB.NE.0)” and the last statement of the grey block (&lt;code dir=&quot;auto&quot;&gt;true&lt;/code&gt; value of the IF), is a GOTO.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;h3 id=&quot;other-analyses&quot;&gt;Other analyses&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;There are little analyses for now on the CFG, but &lt;code dir=&quot;auto&quot;&gt;FASTFortranCFGChecker&lt;/code&gt; will compute a list of unreachableBlocks that would represent dead code.&lt;/p&gt;
&lt;p&gt;Control flow graphs may also be used to do more advanced analyses and possibly refactor code.
For example, we mentioned the loop at the end of our program implemented with a IF statement and a GOTO.
This could be refactored into a real WHILE loop that would be easier to read.&lt;/p&gt;
&lt;p&gt;This is left as an exercise for the interested people 😉&lt;/p&gt;
&lt;div&gt;&lt;h3 id=&quot;adapting-to-other-languages&quot;&gt;Adapting to other languages&lt;/h3&gt;&lt;/div&gt;
&lt;p&gt;Building a control flow graph is language dependant to identify the conditional statements, where they lead, and the final statements.&lt;/p&gt;
&lt;p&gt;But much could be done in FAST core based on &lt;code dir=&quot;auto&quot;&gt;FASTTReturnStatement&lt;/code&gt; and a (not yet existing at the time of writing) &lt;code dir=&quot;auto&quot;&gt;FASTTConditionalStatement&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Inspiration could be taken from &lt;code dir=&quot;auto&quot;&gt;FASTFortranCFGVisitor&lt;/code&gt; and the process is not overly complicated.
It would probably be even easier for modern languages that do not have the various GOTO statements of Fortran.&lt;/p&gt;
&lt;p&gt;Once the CFG is computed, the other tools (eg. the visualization) should be completely independant of the language.&lt;/p&gt;
&lt;p&gt;All hands on deck!&lt;/p&gt;</content:encoded><category>Famix-tools</category><category>FAST</category></item></channel></rss>