Module iface

Module iface 

Source
Expand description

.becki — the published module signature, and the separate-compilation firewall.

docs/03-type-and-effect-system.md §3.6, whose heading is “Modularity and separate compilation (do not defer)”, and whose rule is one sentence:

Placement, effects, and event/command types are part of a module’s published signature. Inference is intra-module; boundaries are declared.

docs/01-vision-and-premise.md §1.6 says why this is the item that cannot slip: it is the historical killer of tierless languages. A language that must see every module to place any of them has a build time proportional to the whole program and an API surface nobody can review.

§What a .becki is

A file in the ordinary Beck surface, generated by beck iface, checked in, and reviewed like an .mli. It contains the module’s types verbatim and one bodyless def per published name:

# orders.becki — generated by `beck iface`. This is the module's published contract.

model Order:
    id: OrderId
    total: Int

@on(any)
def recent(customer: Str, limit: Int) -> list[Order]

@signal
@on(data)
def orders() -> Signal[Map[OrderId, Order]] uses durable

Two decisions worth stating, because §3.6’s illustrative syntax suggests otherwise:

  • It is Beck, not a second notation. §3.6 sketches orders : Signal[…] ! { durable } @on(server), which would need a parser of its own. A bodyless def says the same thing in a grammar the lexer, parser, printer, formatter and editor already handle, and beck fmt keeps it tidy for free. The one parser change it needed — a def may have no body — is a declaration, which is a thing the language wanted anyway (a trait’s method signature is one).
  • A published signal is a nullary declaration, marked @signal. A signal is a value of type Signal[T], and declaring a value with no arguments is what an interface file has always done; the marker distinguishes it from a function that happens to return one.

§Why the digest matters

Interface::digest is the firewall in one value. A body edit does not change it, so a downstream module’s check is served from the memo; an effect or a type or a placement change does change it, so the downstream module is re-checked — and, if the change is breaking, beck check --wire-compat says so before the deploy does.

Structs§

Export
What an importing module learns about one imported name.
Interface
A module’s published signature.
Item
One published name.

Enums§

Kind

Functions§

render_item
One published name, as a .becki line.
structural
A type’s structure, transitively — every field of every variant, through every named type it reaches.