Die Arbeiten am INTERLIS-Compiler der Herzen gingen weiter:

Reduktion globaler Zustand

Im Original teilten sich verschiedene Compilerläufe überraschend viel globalen Zustand. Ein globaler Mutex sorgte letztlich dafür, dass im selben Prozess immer nur eine Kompilierung gleichzeitig stattfinden konnte. Im Fork gehört der Compilerzustand nun weitgehend zu einer Session beziehungsweise zu genau einem Compilerlauf. Mehrere unabhängige Modelle können deshalb gleichzeitig kompiliert werden, ohne Modellregistries, Quelldateien oder Fehlermeldungen miteinander zu vermischen. Für ein klassisches Kommandozeilenprogramm ist das nicht wirklich schlimm. Blöd wird es, wenn man den Compiler als Bibliothek einsetzen will und verschiedene Benutzer zur gleichen Zeit compilieren wollen. Dann können Fehlermeldungen etc. vermischt werden.

Inkrementelle Kompilierung

Ist jetzt sicher nicht das Killerfeature aber nice to have (natürlich verbunden mit Komplexität). Importiert ein Datenmodell Main ein anderes Datenmodell Base und nach dem ersten Lauf ändern wir etwas in Main, muss das Modell Base nicht mehr ein zweites (oder n-tes) Mal geparst werden. Es ist nicht so, dass ilic gar nichts mehr mit dem Base-Modell macht - es muss weiterhin die semantische Kompilierung gemacht werden - aber für gewisse Anwendungen ist alleine das ein guter Gewinn.

Verbesserte Fehlerdiagnostik

Statt mehr oder weniger freien Fehlermeldungstexten gibt es nun einen DiagnosticCatalog mit stabilen Fehlercodes, Severity, Phase, relatedInformation, helpId, Fingerprint usw. Ranges werden zentral inklusive UTF-16/LSP-Konvertierung behandelt. Parserfehler werden übersetzt und Kaskaden aufgrund expliziter Ursache-Abhängigkeiten unterdrückt statt anhand von Meldungstexten.

Conformance-Suite als Regression-Gate

Im ersten Beitrag zu ilic habe ich geschrieben, dass ich für den Vergleich zu ili2c dessen Tests genommen habe und eine Conformance-Suite gemacht habe. Das war aber im Nachhinein ein nicht geglückter Ansatz: Bei den Tests dünkte mich das eher chaotisch gewählt und das Tooling war komplett over-engineered. Ich habe zwischenzeitlich einen besseren Ansatz bei der Auswahl der Tests gewählt und auch das Tooling massiv vereinfacht. Ilic wird bei jedem Commit gegen diese Testsuite geprüft.

WebAssembly

Die spannendste Neuerung ist die WebAssembly-Version des ilic-Compilers. Das Erstellen von WebAssembly ist wegen der C++-Codebasis viel einfacher als mit ili2c und Java. Es gibt zwar verschiedene Ansätze wie man aus Java(-Byte-)Code WebAssembly herstellen kann aber das steckt noch eher in den Kinderschuhen.

Mit dem WASM-Port können wir auch Modelle compilieren wie mit dem nativen ilic. Wir benötigen ein Node.js-Script, z.B. compile.mjs:

import { readFile } from "node:fs/promises";
import { createCompiler } from "@ilic/compiler-wasm";

const filename = process.argv[2];

if (!filename) {
  console.error("Usage: node compile.mjs <model.ili>");
  process.exit(2);
}

const source = await readFile(filename, "utf8");

const compiler = await createCompiler();
const session = compiler.createSession();

try {
  session.putSource(filename, source);

  const result = session.compile({
    roots: [filename]
  });

  for (const line of result.transcript ?? []) {
    console.log(line);
  }

  process.exitCode = result.success ? 0 : 1;
} finally {
  session.dispose();
}

Installation:

npm install @ilic/compiler-wasm@snapshot

Dann beispielweise:

node compile.mjs NewModel.ili

Das entspricht:

ilic NewModel.ili

Was mit dem Node.js-Script nicht geht, ist das automatische Herunterladen von importierten Modellen. Das hat einen technischen Hintergrund: Bei der nativen C++-Version kann ilic benötigte INTERLIS-Modelle selbst über das Netzwerk laden und lokal cachen. Die WebAssembly-Version läuft dagegen in einer vom Betriebssystem abgeschirmten Umgebung. Netzwerk- und Dateizugriffe werden deshalb vom JavaScript-Host erledigt; dieser lädt die Modelle und übergibt sie anschliessend an den eigentlichen ilic-Compiler. Dazu haben wir ein eigenes @ilic/tools-Paket gemacht, welches diese Arbeiten übernimmt.

Was man mit der WebAssembly-Version des ilic-Compilers machen kann? 🥁🥁🥁 … tadaaa! 🎉 Eine INTERLIS IDE komplett im Browser, komplett lokal. Achtung: Die INTERLIS-Modellablagen müssen CORS korrekt konfigurieren, sonst können die Modelle nicht gelesen werden. Für die wichtigsten drei Ablagen habe ich bei uns einen Mirror erstellt, nicht jedoch für kantonale Ablagen.

INTERLIS Web IDE

Links:

Meme