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 filemica.externallands 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": { ... }
}
]
}| Field | Values | Meaning |
|---|---|---|
name | string | the namespace the import names: imp Touch : micacallsc |
language | c · mica | which side of the boundary the library was written on — it decides calling and failure semantics |
type | external · system · internal | external 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_protected | boolean | when 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 |
contract | object | the surface itself: link, types, constants, functions, generic_templates |
The link block
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:
kind | Declares | Carries |
|---|---|---|
record | a field sequence | fields, optional packed, optional layout |
enum | named literals | literals, base_type |
subrange | a bounded integer | base_type, lower_bound, upper_bound |
array | a fixed array | element_type, dimensions (each with index_type and both bounds) |
dynamic_array | an array of T | element_type |
set | a set over an ordinal | base_type |
bitset | a fixed-width bit set | base_type |
bitrecord | named bit fields in one carrier | bit_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": "borrowed_pointer", "to": {"kind": "named", "name": "Sqlite"}}
{"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 borrowed_pointer carries no ownership with it: the
cell it designates belongs to someone else — a C library’s own handle
above all — so the importing program’s ownership analysis demands no
release for it. It is how a Mica library’s borrowed pointer T result
crosses an emitted contract whole. 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"
}| Field | Values | Meaning |
|---|---|---|
language_name | PascalCase | the name Mica source calls |
external_name_utf8 / external_name_utf32 | symbol names | the 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 |
parameters | list | each with name, type, and passing_mode — call_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_type | type reference | omitted or {"kind": "void"} for none |
variadic | boolean | the C ... — a Mica-borne entry never carries it, because the language has no variadic functions |
format_string | none · write · read | declares 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 |
errors | object | see below |
abi | object | optional; its aggregate_return_mode — register or hidden_return — states how the C side returns an aggregate by value, where the two conventions differ |
blocking | boolean | optional, 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 |
parks | boolean | optional, 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_flags | list | additional compiler or linker flags this one function needs on the link line |
description | string | one sentence; surfaces in editor hover |
interface_file | string | the 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.
Callback slots
A C library that takes a function pointer declares that parameter a callback slot: the parameter itself carries the void-pointer type — the pointer-sized code address is what actually crosses — and the slot beside it states everything the compiler holds a binding to:
{
"name": "visit",
"type": {"kind": "pointer", "to": {"kind": "void"}},
"passing_mode": "call_by_value",
"callback": {
"class": "during_call",
"parameters": [
{"name": "context", "type": {"kind": "pointer", "to": {"kind": "void"}},
"passing_mode": "call_by_value"},
{"name": "value", "type": {"kind": "builtin", "name": "int64"},
"passing_mode": "call_by_value"}
],
"return_type": {"kind": "builtin", "name": "int64"},
"userdata_index": 2
}
}| Field | Values | Meaning |
|---|---|---|
class | during_call · registered | when the library fires the bound callback: during_call only inside the imported call itself, so the caller’s frame outlives every firing; registered stores the callback and fires it after the call returns — a class this release declares but does not yet serve |
parameters / return_type | type references | the C shape a bound callback declaration must match, position for position; a slot position declared void-pointer admits any Mica pointer, which is how the callback declares the pointer to its own context record |
userdata_index | zero-based ordinal | the sibling parameter carrying the userdata pointer the library passes through unchanged; omitted when the API declares none |
The only thing that may stand at a callback slot is the name of a Mica
callback declaration — the third declared subprogram kind beside task
and generator. A callback is never called from Mica and never a value;
the library behind the slot performs every firing, and the callback’s
whole environment is the explicit context record its userdata pointer
carries plus the unit’s own root storage.
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.
convention | The C idiom it lifts |
|---|---|
negative_errno | a negative return announces failure — most of POSIX: read, write, open, the socket family |
null_errno | a 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.