System programming has a dialect: call, compare against -1, read errno
before anything else clobbers it, map the number to a meaning, repeat six
hundred times. Every C program speaks it; most languages above C wrap it
one syscall at a time, by hand, forever.
MicaCallsLinux
is a program that walks identity, filesystem, and file-descriptor surfaces
of the kernel — and contains no -1 and reads no errno, anywhere.
Curated contracts, embedded
imp
GetPid, MkDir, Rename, Access, Close, Dup, Lseek, OsError : posix;
GetTid, MemFdCreate, EventFd, EventFdRead, GetAuxVal : linux;The posix and linux namespaces resolve against contracts embedded in
the compiler binary — no contract file accompanies the example, no flag
names one, and nothing installation-resident could change what the
compiler believes about these functions. The same is true on every road:
build, run mode, and the language server all see one truth.
The failure channel reaches the kernel
The contract entry for each function declares its C error convention —
close announces failure as a negative return with errno set — and
as the error-domain tutorial showed, the compiler
synthesizes the whole dance behind the call: check the return, read
errno first, translate to the curated OsError domain, hand the code to
the ordinary consumption machinery. An imported system function is a
fails function:
MkDir(TempDir, 493) on fail e do WriteLn(" (directory already existed - fine)"); { 0755 }
Access(TempFile, R_OK) on fail e do readable := False;
Rename(TempFile, TempFileRenamed) on fail leave;MicaCallsLinux — POSIX and Linux through the failure channel
POSIX filesystem lifecycle
directory ready: /tmp/mica_posix_demo
created file: /tmp/mica_posix_demo/note.txt
set file mode to 0644
access probes: readable=1 writable=1
renamed to: /tmp/mica_posix_demo/note-renamed.txt
removed file and directory - the walk leaves no trace
File descriptors: memfd, lseek, dup, eventfd
memfd fd=3 sized to 4096 bytes
dup: fd 3 and fd 4 name the same open file
eventfd delivered the counter: 7
All sections completed through the failure channel — no return code was ever checked.(The identity section also prints pids and hardware capabilities — real values from the running kernel, volatile by nature, which is why the lines above quote the deterministic sections.)
The last line is the example’s whole thesis. Every one of those operations
can fail; every failure road exists in the source as an on fail clause
you can point at in review; and the successful run costs one flag test per
call — no wrapper objects, no exceptions, no allocation.
Linux beyond POSIX
The linux namespace carries the kernel’s own vocabulary — memfd_create,
eventfd, getauxval, sched_getcpu — under the same rules. An
EventFdRead that would block is a failure value; a MemFdCreate is an
anonymous file whose descriptor works with every POSIX verb beside it. The
two namespaces compose because nothing about either is special-cased: they
are contracts, all the way down.
What this does not do
- No sockets story here — the echo server and the closed-peer lesson
live in the test corpus and arrive with the networking unit planned for
6.13, where
sendon a hung-up peer comes back as a failure value instead of a process-killing SIGPIPE (the runtime already sends with the no-signal flag; the tutorial waits for the unit that makes it a story). - Paths are UTF-8 at this boundary. The path-taking externals publish
UTF-8 symbols, so the example builds on the utf-8 platform and prints
with
%s— the encoding choice doing exactly what it is for. - Not every syscall is curated yet. The surface grows by contract entries, each with its convention declared — a missing function is an addition to a JSON table, not a new binding layer.
Try it
git clone https://gitlab.com/mica-lang/mica-container.git
make -C mica-container/examples/MicaCallsLinux runChange Close(ends[0]) to close the same descriptor twice and watch
EBADF arrive as an ordinary domain code in an on fail binding — then
try to write the same double-close handling in C without forgetting the
errno read ordering, and enjoy the comparison.
Next
Debugging across the boundary — everything these three tutorials built, stopped in a debugger: Mica frames above C frames above Mica frames, with a monomorphized generic in the middle.