====== LPM — Compiler-Integration ======
→ [[lyx_-_programmiersprache:tools:lpm|Zurück zu LPM]] · [[lyx_-_programmiersprache:tools:compiler-parameter|CLI-Referenz des Compilers]]
Diese Seite beschreibt, was ''lpm'' für die automatische Import-Auflösung bereitstellt und was auf der Compiler-Seite dafür nötig wäre.
**Die Compiler-Seite ist nicht umgesetzt.** ''lyxc'' ruft ''lpm'' heute nicht auf; ein ''import net.http'' ohne lokal vorhandene Datei scheitert weiterhin mit ''Modul nicht gefunden''. Was hier steht, ist die fertige Schnittstelle von ''lpm'' aus gesehen — samt der Fundstellen im Compiler, die eine Umsetzung berühren würde.
Stand: 2026-08-15, ''lpm'' 0.1.0, ''lyxc'' 1.0.21A.
----
===== Das Ziel =====
import net.http; // liegt lokal nicht vor
lyxc main.lyx
→ Import nicht auffindbar
→ lpm resolve net.http
→ lpm lädt das Paket und meldet, wo es liegt
→ lyxc setzt dort fort
----
===== Was lpm liefert =====
==== lpm resolve <name> [--entry] ====
Löst ein Paket auf, lädt es bei Bedarf herunter, prüft den SHA256 und entpackt es in den Cache. Der Aufrufvertrag ist bewusst eng gehalten, damit ein Compiler die Ausgabe **ohne Parser** verwenden kann:
^ Kanal ^ Zusage ^
| **stdout** | bei Erfolg **genau eine Zeile**: ein Pfad, mit ''\n'' abgeschlossen. Sonst nichts |
| **stderr** | alle Meldungen — Fortschritt, Warnungen, Fehler, auch unter ''--verbose'' |
| **Exit 0** | Paket liegt im Cache, der Pfad auf stdout ist gültig |
| **Exit 1** | nicht auflösbar; stdout bleibt **leer** |
Ohne ''--entry'' ist die Ausgabe das **Paketverzeichnis**:
$ lpm resolve net.http
/home/andreas/.lpm/cache/net/http/0.3.0
Mit ''--entry'' die **Unit-Datei**:
$ lpm resolve net.http --entry
/home/andreas/.lpm/cache/net/http/0.3.0/http.lyx
==== Warum --entry der interessantere Modus ist ====
''lyxc'' sucht zu ''import net.http'' eine //Datei// — nach heutiger Logik ''<root>/net/http.lyx'' (''src/sema.lyx:1746-1757''). Der Cache liefert aber ein //Verzeichnis//:
~/.lpm/cache/net/http/0.3.0/
lyx.toml
http.lyx ← die Unit
FILES.sha256
Ein Include-Root, unter dem ''net/http.lyx'' läge, gibt es nicht — und soll es auch nicht geben, weil im Cache mehrere Versionen desselben Pakets nebeneinander liegen. ''--entry'' löst das auf der ''lpm''-Seite auf: gesucht wird zuerst ''[build] entry'' aus der ''lyx.toml'' des Pakets, dann ''<letztes Namenssegment>.lyx'', dann dasselbe mit ''.lyu''. **Der Compiler muss das Paketlayout damit nicht kennen.**
==== Weitere Eigenschaften ====
* **Importnamen werden übersetzt.** ''net.http'' → ''net/http''. Enthält der übergebene Name schon einen Schrägstrich, bleibt er unverändert. Der Compiler kann den Importnamen also unverändert durchreichen.
* **Der Lock-Eintrag hat Vorrang.** Steht das Paket in der ''lyx.lock'' des aktuellen Verzeichnisses, wird dessen Version genommen, nicht die neueste. Eine Übersetzung sieht damit dasselbe wie ein ''lpm install''.
* **Ein Treffer im Cache ist billig.** Liegt die gelockte Version im Cache, antwortet ''lpm resolve'' ohne Netzzugriff und ohne die Uhr anzufassen — gemessen 19 ms. Ein Aufruf je unaufgelöstem Import ist damit vertretbar.
* **''--offline'' wird beachtet.** Dann wird nur der lokale Cache befragt.
* **''--registry=<url>''** wählt eine andere Registry.
----
===== Was auf der Compiler-Seite nötig wäre =====
Die Fundstellen beziehen sich auf ''aurum'' @ ''878189b5''.
==== Der Import wird an drei Stellen unabhängig aufgelöst ====
^ Stelle ^ Fundstelle ^ Suchpfad ^
| Sema | ''src/sema.lyx:1700'' (''_sema_processImport''), Kaskade in ''_sema_readFile'' ''src/sema.lyx:1420'' | CWD → ''-I'' → ''--std-path'' → ''/usr/include/lyx/units'' |
| Codegen | ''src/codegen_x86.lyx:16732'' (''cg_processImportAs'') | eigene Kaskade, liest Imports ein **zweites** Mal |
| IR-Lowering | ''src/ir_lower.lyx:5065-5090'' | nur relativ, kein Rückfallweg |
Ein Hook allein in Sema würde die Übersetzung später im Codegen scheitern lassen, weil der Import dort erneut gesucht wird. Die Fehlerstelle, an der ein Hook ansetzen könnte, ist ''src/sema.lyx:1804'' — ''"Modul nicht gefunden (weder .lyx noch .lyu)"''.
==== includePath ist heute ein einzelner Pfad ====
''src/sema.lyx:417'' und ''src/codegen_x86.lyx:790'' halten je einen ''pchar'', keine Liste. „Den Include-Pfad ergänzen" hat also kein bestehendes Konstrukt. Zwei Wege:
- **Ein eigenes Feld** für den von ''lpm'' gelieferten Pfad, neben ''includePath''. Kleiner Eingriff, kein Umbau an bestehendem Code.
- **''includePath'' zu einer echten Liste** ausbauen. Größerer Umbau, macht nebenbei mehrfaches ''-I'' für Menschen nutzbar — heute wirkt nur der letzte angegebene Pfad.
Mit ''--entry'' entfällt die Frage teilweise: der Compiler bekommt einen fertigen Dateipfad und muss ihn nur öffnen, statt einen Suchpfad zu erweitern.
==== Subprozess-Bausteine sind vorhanden ====
''sys_fork'', ''sys_execve'', ''sys_pipe'', ''sys_pipe2'', ''sys_dup2'', ''sys_dup3'' und ''sys_wait4'' sind als Builtins registriert (''src/sema.lyx:6229-6254'') und werden emittiert (''src/codegen_x86.lyx:9923ff'', ''10020ff''). **Neue Intrinsics braucht es nicht.**
Im Compiler selbst wird bisher nur in ''src/tooling/self_test.lyx:21-32'' ein Kindprozess gestartet — **ohne** dessen stdout zu lesen. Ein fertiges Muster dafür steht in ''std/process.lyx:161'' (''SpawnWithPipes''), das ''lyxc'' heute nicht importiert.
==== Vorsicht bei IRLower ====
''src/ir_lower.lyx:5069-5072'' hält fest, dass neue Methoden an ''IRLower'' die vtable verschieben und der Seed-Compiler daran schon einmal gescheitert ist.
==== Bootstrap ====
''lyxc'' ist selbstkompilierend: Quelle ''src/lyxc.lyx'', Seed ''src/lyxc_bootstrap'', Fixpunktprüfung ''make singularity'' (S3 == S4). Laut ''Makefile:5-14'' muss der Seed neu verankert werden, sobald sich die **Ausgabe des Codegens** ändert. Reine Frontend- und Sema-Änderungen kommen mit ''make build'' + ''make bootstrap'' aus, solange die Singularitätsprüfung hält.
==== Flags ====
Vorgesehen ist:
lyxc --pkg-resolve=auto # Standard: auflösen, wenn lyx.toml vorhanden
lyxc --pkg-resolve=always # immer
lyxc --pkg-resolve=never # nie (CI, offline)
Das Parsen gehört nach ''parseLongFlag'' (''src/lyxc.lyx:751''); das Muster für ''--x=wert'' gibt es dort bereits bei ''--include-path='' (''src/lyxc.lyx:828-831'') und ''--std-path='' (''src/lyxc.lyx:833-836''). Hilfetext bei ''src/lyxc.lyx:1399ff''.
----
===== Empfohlener Ablauf im Compiler =====
Import nicht auffindbar
└─ --pkg-resolve=never? → bisheriger Fehler, Ende
└─ auto und kein lyx.toml da? → bisheriger Fehler, Ende
└─ lpm resolve --entry
├─ Exit 0 → stdout ist der Pfad zur Unit-Datei; diese öffnen und
│ fortsetzen. Den Pfad merken, damit Codegen denselben
│ Import nicht erneut auflösen muss.
└─ Exit 1 → bisheriger Fehler, ergänzt um die stderr-Ausgabe von lpm
Drei Absicherungen, die ''lpm'' nicht abnehmen kann:
* **Kein wiederholter Aufruf je Import-Versuch.** Ein Import, den ''lpm'' schon einmal nicht auflösen konnte, sollte nicht erneut angefragt werden.
* **Ein Zeitlimit** für den Kindprozess — ''lpm'' geht ins Netz.
* **stdout strikt lesen.** Genau eine Zeile, führende und folgende Leerzeichen abschneiden, bei mehr als einer Zeile abbrechen statt zu raten. Das ist die Gegenprobe zum Vertrag oben.
----
===== Der Vertrag lässt sich ohne Compiler prüfen =====
Vollständig von der Kommandozeile nachvollziehbar:
$ cd /tmp/leer && printf '[package]\nname="x"\nversion="0.1.0"\n' > lyx.toml
$ lpm resolve net.http --entry; echo "exit=$?"
/home/andreas/.lpm/cache/net/http/0.3.0/http.lyx
exit=0
$ lpm resolve net.http --entry 2>/dev/null | wc -l
1
$ lpm resolve gibts.nicht --entry; echo "exit=$?"
lpm: error: Paket nicht in der Registry — gibts/nicht (*)
lpm: error: gibts/nicht liess sich nicht aufloesen.
exit=1
Der letzte Fall zeigt beides: Exit 1 und leeres stdout — nachgemessen, ''wc -l'' auf stdout ergibt dort 0.