A contract is how a Mica program learns what a foreign library offers: its functions, their exact machine-level names, the types that cross the boundary, and how each function announces failure. The compiler consumes contracts instead of parsing C headers — the contract states the facts once, in one reviewable file, and every import resolves against it.

This page is the normative reference for the format. The guided introduction is Mica calls C; the failure-lifting discipline has its own article in error domains.

Where contracts come from, and where they are found

Three roads produce a contract file:

  • You author one beside a C library you want to call — the MicaCallsC example is a full worked instance, and DebugWalk a minimal one.
  • The compiler emits one when linking a Mica library with --emit-contract: the file mica.external lands beside the archive, so another program can import the library by resolving that contract.
  • Some ship inside the compiler. The C standard library, POSIX, and Linux surfaces are embedded contract sets selected by imp ... : c, : posix, : linux — nothing on disk is consulted. The Dragon SDK’s curated contract is installed for reading at /usr/share/doc/mica-dragon-sdk/dragon-engine.json, a real contract over a real shipped archive you can open on your own machine.

A consumed contract is found beside the sources, named explicitly with --external-contract, or listed in mica.project. The published JSON schema ships in the container as reference/library_contracts.schema.json.

The file

One JSON document: a description and a list of libraries. Every name a program imports resolves against exactly one library entry.

{
  "description": "External library contracts for the MicaCallsC example",
  "libraries": [
    {
      "name": "micacallsc",
      "language": "c",
      "type": "external",
      "contract": { ... }
    }
  ]
}
FieldValuesMeaning
namestringthe namespace the import names: imp Touch : micacallsc
languagec · micawhich side of the boundary the library was written on — it decides calling and failure semantics
typeexternal · system · internalexternal links an archive the link block names; system names an external system library; internal marks a surface embedded in the compiler — you author external, and system where the linker should find the library itself
import_protectedbooleanwhen true, the library’s names are protected only at their import site — other units stay free to declare the same names for their own containers. The class a vocabulary unit wants: the bits unit’s Count beside the maps unit’s Count. The standard library carries this class, so a program may declare Length or Capacity for itself and reach the library’s own entry through the namespace it imported, std.Length(values); importing the entry and declaring the name in one unit is what the import site refuses
contractobjectthe surface itself: link, types, constants, functions, generic_templates

What joins the link line when any function of this library is consumed — stated per link profile, chosen by the --external flag:

"link": {
  "static": { "flags": ["../build/MicaCallsC/libmicacallsc.a"] },
  "shared": { "flags": ["-lmicacallsc"] }
}

Both profiles are required; each is a list of linker arguments, spelled exactly as they should reach the linker.

Types

Types declared here become importable Mica types, and they are the only types that may cross the boundary by name. kind selects the shape:

kindDeclaresCarries
recorda field sequencefields, optional packed, optional layout
enumnamed literalsliterals, base_type
subrangea bounded integerbase_type, lower_bound, upper_bound
arraya fixed arrayelement_type, dimensions (each with index_type and both bounds)
dynamic_arrayan array of Telement_type
seta set over an ordinalbase_type
bitseta fixed-width bit setbase_type
bitrecordnamed bit fields in one carrierbit_fields (each with bit_offset and bit_width), base_type

Everywhere a type is referenced — a field, a parameter, a return — the reference is an object with its own kind:

{"kind": "builtin", "name": "int32"}
{"kind": "named",   "name": "ScalarPacket"}
{"kind": "pointer",       "to": {"kind": "named", "name": "ScalarPacket"}}
{"kind": "const_pointer", "to": {"kind": "builtin", "name": "uint8"}}
{"kind": "dynamic_array", "element": {"kind": "builtin", "name": "float64"}}
{"kind": "void"}

pointer and const_pointer differ exactly as the C qualifier does, and the compiler holds an import to it: a const_pointer parameter cannot be written through. A record whose shape genuinely differs per target may declare variants keyed by architecture (amd64, arm64) in place of the base fields — it must state every supported architecture, so a port cannot silently inherit the wrong layout. An emitted contract may additionally carry layout (sizes, alignments, field offsets) and a fingerprint — both are the compiler talking to itself across compilations; an authored contract omits them.

Functions

{
  "language_name": "InotifyInit",
  "external_name_utf8": "inotify_init1",
  "external_name_utf32": "",
  "parameters": [
    {"name": "flags", "type": {"kind": "builtin", "name": "int32"},
     "passing_mode": "call_by_value"}
  ],
  "return_type": {"kind": "builtin", "name": "int32"},
  "variadic": false,
  "format_string": "none",
  "errors": {
    "convention": "negative_errno",
    "domain": "posix.OsError"
  },
  "description": "Create an inotify instance ...",
  "interface_file": "sys/inotify.h"
}
FieldValuesMeaning
language_namePascalCasethe name Mica source calls
external_name_utf8 / external_name_utf32symbol namesthe machine-level symbol per source encoding. A function that exists for one encoding only leaves the other empty, and consuming it from the wrong encoding is a compile error
parameterslisteach with name, type, and passing_modecall_by_value, call_by_constant_value (the const promise on a scalar or small value, enforced on the Mica side), or call_by_constant_address (the const promise on a plain aggregate wider than 16 bytes: the value arrives as one pointer into caller-owned read-only storage, so a C consumer declares the parameter const T *)
return_typetype referenceomitted or {"kind": "void"} for none
variadicbooleanthe C ... — a Mica-borne entry never carries it, because the language has no variadic functions
format_stringnone · write · readdeclares a printf/scanf-class function, which turns on compile-time checking of the format against the variadic arguments; format_string_index is the format parameter’s zero-based position — 0 for the printf shape, 1 for fprintf, 2 for snprintf
errorsobjectsee below
abiobjectoptional; its aggregate_return_moderegister or hidden_return — states how the C side returns an aggregate by value, where the two conventions differ
blockingbooleanoptional, default false: this C entry waits on the outside world by design — the fsync class. The stamp sharpens the compiler’s boundary-under-mark warning from “may stall” to “is declared to wait”; it never rejects a call
parksbooleanoptional, default false: the call may park the calling task on a descriptor. A parking entry’s external names must name a __mica_ parking shim — the runtime routine that tries the operation without blocking and suspends only the calling task until readiness
requires_flagslistadditional compiler or linker flags this one function needs on the link line
descriptionstringone sentence; surfaces in editor hover
interface_filestringthe C header documenting the function — documentation, not consumed

Two more fields appear only in contracts the compiler writes, never in one you author: effects on a Mica-borne entry records what the exporting unit’s transitive effect walk proved about the body (an empty object is the walked-and-clean statement), and intrinsic names an entry the compiler realizes inline at each call site — the embedded standard-library surface’s own bookkeeping.

The errors block

The errors block is what turns a C failure idiom into Mica’s failure channel: the compiler synthesizes the check the convention describes and lifts the failure, so the caller handles it with on fail like any Mica failure — no -1 tests in user code, ever.

conventionThe C idiom it lifts
negative_errnoa negative return announces failure — most of POSIX: read, write, open, the socket family
null_errnoa null pointer return announces failure — getcwd, the fopen class
sentinel:<value>a stated sentinel value announces failure — mmap’s all-ones is the classic

domain names the Mica error domain the lifted code lands in (posix.OsError above). A language: "mica" entry never carries the block: a Mica-borne callee speaks the failure channel natively, with nothing to lift.

Constants

{"name": "InotifyCloexec", "type": {"kind": "builtin", "name": "int32"}, "value": 524288}

A constant carries name, type, and value — or values keyed per target architecture for the rare constant whose value depends on it. Enum literals do not repeat here; declaring the enum type already imports its literals.

Mica-borne libraries: generic templates

A contract with language: "mica" may carry generic_templates — the gen blocks of a Mica library, travelling as source because generics instantiate in the consuming compilation. Each entry names the template, its kind (type or function), its type parameters with their constraints, and the imports its body needs. You do not author these: the compiler emits them with the rest of the contract under --emit-contract.

Reading order for a new contract

Author top-down, the order the compiler resolves: the library entry and its link block first (the import now resolves and links), then the types the boundary needs, then functions one at a time — each one testable as soon as it is declared — and the errors block on every fallible entry before the function is called in anger. The MicaCallsC worked instance follows exactly this order, and every field this page documents appears in it, in the compiler’s shipped contracts, or in both.