Files
TerminalBasic/docs/pcode-bibliotheken.md

8.6 KiB
Raw Permalink Blame History

P-Code-Bibliotheken und Linker

Eine .tbl enthält übersetzte BASIC-Module mit Deklarationen, typisierten Imports, COMMON-Verträgen, DATA, Forms-Anfangsdaten und Quellpositionen. Sie enthält weder BASIC-Programmrümpfe als Quelltext noch native Runtime oder Maschinencode. Dieselben Bytes sind für Windows amd64, macOS arm64 und Linux amd64/arm64 vorgesehen. Der Verbraucher braucht die Bibliotheksquellen nicht.

Befehle

tbc build library.mak --library --output library.tbl
tbc link app.mak library.tbl --output app.tbc
tbc link app.mak library.tbl --exe --target aarch64-apple-darwin --output app

build --library akzeptiert BAS, FRM oder MAK sowie zusätzliche TBL-Eingaben. Ohne --output entsteht eine gleichnamige .tbl. Alle angegebenen Module, einschließlich eingebundener Bibliotheken, werden in Reihenfolge übernommen; Abhängigkeiten werden flach mitgegeben, ohne automatische Paketsuche.

link benötigt ein BASIC-/Form-Hauptmodul oder ein entsprechendes MAK-Projekt. Zusätzliche Argumente müssen TBL-Dateien sein. Ohne --exe entsteht ein vollständig verknüpftes .tbc, standardmäßig neben dem Hauptprojekt. Ein fertiges TBC kann ausschließlich mit tbc link app.tbc --exe verpackt werden; weitere TBL-Dateien sind dabei unzulässig, da das TBC bereits aufgelöst ist.

--library und --exe schließen sich aus. --target und --template sind EXE-Optionen. TBL-/Link-/EXE-Ausgaben überschreiben vorhandene Ziele nur mit --force. Eingaben, Includes, MAK- und TBL-Dateien bleiben auch dann geschützt. build app.mak, run app.mak und check app.mak verwenden denselben Resolver. Beim erneuten build eines MAK mit TBL-Mitgliedern ist ebenfalls --force zum Ersetzen nötig. Der bisherige Aufruf build source.bas bleibt eine TBC-Übersetzung; reine Quellprojekte behalten ihre Standardausgabe.

Für TBL und TBC genügen die ausgelieferten TB-Werkzeuge. Ein C-/Rust-Compiler oder nativer Linker wird beim Anwender nicht aufgerufen. Für EXE gilt der Runtime-Vorlagenvertrag: passende vorgebaute runtimes/<Triple>/tbrt[.exe] mit Metadaten oder ausdrücklich --template; auf macOS die dort beschriebene System-Signierung. Eine fehlende, falsche oder inkompatible Vorlage liefert eine Diagnose und kein fertiges Executable.

Projektmitglieder, Auflösung und Initialisierung

Beispiel app.mak:

' $STARTUP: "main.bas"
main.bas
lib/common.tbl
last.bas

MAK-Pfade sind relativ zur MAK-Datei und werden wie bisher ohne Beachtung der Groß-/Kleinschreibung aufgelöst. Eine TBL wird an ihrer Position in ihre Modulreihenfolge aufgefächert. Zusätzliche CLI-Bibliotheken folgen danach. Das gewählte Quell-Startmodul steht zuerst; ohne explizite Wahl ist es das erste Quellmitglied. Eine TBL ist weder Textdokument noch Startdatei. Die Form-Startauswahl gehört dem Verbraucher; eine Bibliothek speichert keine aktive Startform. Reine Forms-Projekte behalten ihren bisherigen Startvertrag.

Alle globalen Anfangswerte und Array-Initialisierungen stehen vor den Modulrümpfen bereit. Die Rümpfe folgen der erweiterten Projektreihenfolge mit dem normalen BASIC-Kontrollfluss: ein END im Hauptmodul beendet auch das Gesamtprogramm. Ein Prozeduraufruf führt keinen zusätzlichen Modulrumpf aus. RUN ohne Ziel erzeugt die gesamte Runtime einschließlich Bibliotheksvariablen, DATA-Zeiger, Forms und Textbildschirm erneut. Gespeicherte physische Quellorte und BASIC-Zeilenlabels bleiben für Laufzeitfehler verfügbar.

Die vorhandene Sichtbarkeit gilt: lokale Definitionen gewinnen, fremde Prozeduren müssen eindeutig sein, Konstanten und TYPE-Deklarationen werden vor der Verbraucher-Semantikanalyse importiert. Prozedurparameter und Ergebnisse werden nach dem UDT-Remapping geprüft; COMMON wird nur bei kompatiblen Typen und Array-Grenzen geteilt. Offene DECLARE-Imports dürfen in einer TBL verbleiben, müssen aber im ausführbaren Endprodukt aufgelöst sein. Nicht aufgerufene reine DECLARE-Prototypen sind keine Imports und werden aus dem Endprodukt entfernt; Aufrufe in mitgelieferten Prozedurrümpfen müssen auch dann auflösbar sein, wenn diese Prozedur noch nicht aufgerufen wird. Die bereits vorhandenen nativen Runtime-Dialogfunktionen bleiben Runtime-Imports. Doppelte Modulidentitäten, etwa durch überlappende flache Bibliotheken, sind Fehler. Bibliotheksdateien werden bei jedem Build nach ihrem tatsächlichen Inhalt gelesen; gleiche Dateigröße oder Zeitstempel können alte Deklarationen oder alten Code nicht im Ergebnis festhalten.

TBL-Version 1

Alle Ganzzahlen sind Little Endian und haben feste Breiten; Zeichenketten sind UTF-8 mit u32-Byteanzahl. Es werden keine Rust-Structlayouts serialisiert.

Feld Darstellung
Magic vier Bytes TBL\0
TBL-Version u16, aktuell 1
P-Code-Version u16, aktuell TBC 4
Runtime-Vertragsversion u32, aktuell 1; gemeinsam mit EXE-Vorlagen
Modulanzahl u32, 1 bis 65535
Module je u32-Abschnittslänge und Abschnittsbytes
Prüfsumme u64 FNV-1a über alle vorherigen Bytes; erkennt Beschädigung, authentisiert keine Herkunft

Ein Modulabschnitt enthält in dieser Reihenfolge:

  1. Modulname und Quellposition (source, line, column, jeweils u32).
  2. Exportdeklarationen mit u32-Anzahl: Prozedur (Tag 0), TYPE (Tag 1), aufgelöste Konstante (Tag 2). Jede Deklaration hat eine Quellposition. Prozeduren speichern Art, Name, Suffix und Parameter mit Name, Suffix, Array-Markierung und optionalem Typ. TYPE speichert Namen und geordnete Felder. Konstanten speichern Name, Suffix und gefaltetes f64 oder String.
  3. Deklarationsorte (Name/Position) und Namen tatsächlich definierter Prozeduren, jeweils mit u32-Anzahl. Die übrigen typisierten Prozedurzeilen im Modulprodukt sind Imports. Es werden keine vollständigen ASTs gespeichert.
  4. COMMON-Zeilen mit Slot (u16), optionalem Blocknamen, Schlüssel, HIR-Typ, Position und optionalen Array-Grenzen (i32, einzeln optional).
  5. u32-Länge und Bytecode-Produkt mit dem bestehenden TBC-Codec. Dieses Produkt ist unverknüpft und auf genau ein Modul begrenzt: eigene Quell-IDs, Typen, Globals, Prozeduren, Strings, DATA, Sprungtabellen, Objektkatalog, Ereignisse und eigene Forms-Anfangswerte. Es ist kein umbenanntes fertiges Projekt-TBC.

Optionen und Booleans sind strikt 0/1; Suffixe sind 0 oder das ASCII-Zeichen %, &, !, #, $, @. Typ-Tags 09 stehen für INTEGER, LONG, SINGLE, DOUBLE, CURRENCY, STRING, festen STRING (i64 Länge), FORM, CONTROL und TYPE (UTF-8-Name). Konstantenwert-Tags sind 0 (f64) und 1 (String).

Der Leser prüft Prüfsumme, Versionen, Abschnittsgrenzen, Restbytes, Tags, Tabellen- und Symbolreferenzen, Export-/Bytecode-Signaturen, COMMON sowie Forms-Anfangsdaten vor der Weitergabe. Der Linker prüft auch die vereinigten Tabellengrenzen und remappt alle Typ-, Global-, Prozedur-, String-, DATA-, Sprung-, Objekt-, Ereignis- und Quellreferenzen. Veröffentlichungen verwenden die gemeinsame temporäre Datei mit erneuter Validierung, Abbruchprüfung und atomarer Freigabe. Fehler erhalten vorhandene Ziele und Eingaben.

Reproduzierbare Abnahme und Übergabe

tests/libraries/portable.tbl ist das gemeinsame unveränderte TBL-Artefakt. Seine SHA-256 lautet 5d25c2f8c95ae535e55a6c84c1ddd0d964358863f4f3c780c50ac4a2eb3594df. portable.bas dokumentiert den einmaligen Ursprung; die Verbraucherprobe liest oder übersetzt diese Quelle nicht.

python3 tests/support/library-abnahme.py --bin-dir target/release

Auf jedem echten Ziel werden dieselben TBL-Bytes geprüft, ein separater Verbraucher zu TBC und EXE verknüpft und nach Entfernen von Quellen, TBL, TBC und Runtime-Vorlage das Executable mit leerem PATH ausgeführt. Resultate, Dateieffekt und Neustart durch RUN werden geprüft. Die JSON-Ausgabe nennt Host-Target, Prüfsumme und Ergebnis. Ein Cross-Compile ersetzt diesen Lauf nicht. Die vier JSON-Nachweise gehören in die Plattform-/Gitea-Abnahme.

Die IDE nutzt denselben Compiler-/Linkdienst für Start, Check, Debugger, Make Library und Make EXE. TBL-Mitglieder sind nicht editierbar. Die Make- Dialoge verwenden ungespeicherte Puffer und veröffentlichen nur weiterhin gültige Aufträge; Bedienung und Voraussetzungen. Change 05 führt den identischen Verbrauchercheck auf allen vier echten Zielsystemen aus. Change 06 baut die vier nativen Compiler-/Runtime-Pakete zentral auf dem Linux-arm64-Gitea-Runner per Cross-Kompilierung und bindet die echten Verbraucherprüfungen für die entpackten Pakete an Revision und Paketprüfsumme. Vier native Buildrunner sind dafür nicht erforderlich.