Zum Inhalt

JDL – Modulsystem und FFI

Status: Draft
Geltungsbereich: Sprachebene (keine VM-Implementierungsdetails)


Warum Dieses Dokument Existiert

Sobald aus Sprachfeatures echte Projekte werden, entstehen zwei Druckpunkte:

  • Modulgrenzen müssen klar sein (Sichtbarkeit, Imports, API-Kontrolle).
  • FFI muss sicher eingebettet werden, ohne das Effektsystem zu verwässern.

Dieses Dokument fixiert genau diese Übergänge.


0. Priorität

Ergänzt:

  • 00-refinements.md
  • 01-grundlagen.md
  • 02-typsystem.md
  • 03-runtime.md

Bei Widerspruch gelten 00 bis 03.


1. Leitbild

  • modulare Struktur über Dateipfade,
  • klare Trennung zwischen service (Vertrags-/Abstraktionsebene) und extern (FFI-Deklaration),
  • eine einzige Service-Zuordnungsform: provide Service for Handler.

2. Modulsystem

2.1 Grundregeln

  • Dateipfad bestimmt Modulname (users/service.jdl -> users::service).
  • mod.jdl ist optionales API-Root.
  • Sichtbarkeit folgt der Namespace-Spec: privat (default), package, pub.
  • Zyklische Modulabhängigkeiten sind Compilerfehler.

2.2 Sichtbarkeit

// users/service.jdl
def validateEmail(email: str) -> bool { ... } // privat
package def normalizeEmail(email: str) -> str

pub def findUser(email: str) -> Result[User, UserError]
pub type User: struct { ... }

2.3 Importformen

import users::service
import users::service : User, findUser
import users::service : User as AppUser

Vollimport ist explizit, kein impliziter Wildcard-Trick.

2.4 mod.jdl als API-Schicht

// users/mod.jdl
pub import package::model   : User, UserId
pub import package::service : findUser, registerUser

Damit kann öffentliche API bewusst geformt werden.

Module unter einem internal-Teilbaum folgen zusätzlich der Namespace-Spec und sind außerhalb des aktuellen Packages/Plugins nicht importierbar.

2.5 Lokale Imports

Erlaubt für lokale Lesbarkeit, aber kein Ersatz für explizite Service-Parameter oder Effect[R, E, D]-Rückgabetypen.


3. Service vs. extern

3.1 Rollen

  • protocol: typbezogenes Verhalten,
  • service: Vertrags-/Abstraktionsebene, die über provide Service for Handler an konkrete Implementierungen gebunden wird,
  • extern: rohe FFI-Bindings.

3.2 Harte Trennung

  • extern-Blöcke sind nie selbst Service-Abstraktionen,
  • extern-Blöcke enthalten nur def-Deklarationen,
  • Domänenlogik/Fehlermapping im Handler (provide ... for ...),
  • implements existiert nicht.

3.3 Verbindliche Zuordnung

provide ServiceName for HandlerType { ... }

Nicht zulässig:

  • provide HandlerType for ServiceName
  • extern X : implements Y

4. FFI-Modell

4.1 Grundsyntax

extern LibSQLite {
    def query(db: DbHandle, sql: str) -> Result[RowSet, SqliteError] { 
      ... 
    } :> CSymbol("sqlite3_exec")
} :> FFILink("sqlite3")

4.2 Service darüber anbieten

service Db {
    def query(sql: str) -> Result[RowSet, DbError]
}

type SqliteHandler: struct { db: DbHandle }

provide Db for SqliteHandler {
    def query(self, sql: str) -> Result[RowSet, DbError] {
        LibSQLite.query(self.db, sql)
            |> Result.mapErr(DbError.from)
    }
}

4.3 Syntaxkonsistenz

def innerhalb von extern-Blöcken, nicht fn.

4.4 FFI-Typsicherheit

Erlaubt:

  • primitive Skalare,
  • ptr[T] nur an expliziten FFI-Grenzen,
  • opaque Handles,
  • ABI-kompatible Struct/Enum-Repräsentationen.

Nicht erlaubt:

  • captured Closures,
  • arena-gebundene Typen über falsche Grenzen,
  • lokale Share-Typen über unzulässige Übergänge,
  • unklare generische ABI-Signaturen.

5. Normative Invarianten

  1. Service-Zuordnung nur via provide Service for Handler.
  2. implements ist kein Sprachbestandteil.
  3. extern-Blöcke sind keine Service-Abstraktionen und werden nicht direkt als Vertragsoberfläche verwendet.
  4. extern-Blöcke enthalten keine Domänenlogik.
  5. FFI-Einstieg benutzt def innerhalb von extern-Blöcken.
  6. Symbolbindung läuft über Refinements (:> CSymbol(...)).
  7. Library-Linkage läuft über :> FFILink(...) auf dem extern-Block.

6. Offene Punkte (Phase 2)

  • Callback-Brücken,
  • detaillierte ABI/Calling-Convention-Policies,
  • formale repr: C-Regeln,
  • Paketmanager-/Versionsauflösung außerhalb Sprachkern.