Start here — from nothing to your first debugged program, then onward.

One clone is the whole setup. mica-lang/mica-container is the starter for Mica: the dev container, the whole example suite, the benchmarks, F5 debugging across every one of them, and the working files this series is written against.

git clone https://gitlab.com/mica-lang/mica-container.git
code mica-container      # then: Reopen in Container

Nothing is installed on your machine but Docker and VS Code. If you would rather not clone anything, part 1 below builds the same setup from four files you paste yourself.

Two courses

Program in Mica

The tutorial series

A guided path from a first program through the type system, the memory model and the concurrency model — written against the shipping compiler, with every example compiled and every command run before it is published. Each tutorial uses one example, and the examples live in the tutorial repository.

The path grows a section at a time. Within a section the order is the reading order; between sections, a tutorial says at the top what it assumes.

Getting started

PartTutorialYou end up with
1Get started with Micaa dev container, your first program, and a debugger session — breakpoints, variables, stepping
2The shape of a Mica programthe four parts every program has, why nothing is ambient, and a format string checked before the build
3Types that change, and what it costswhen a value widens on its own, when you must write as, and what a narrowing cast does to a number that will not fit
4Choices and repetitionthe two ways a program decides and the three ways it repeats — each loop stating what it knows before it runs, on one walk whose output checks itself
5Procedures and parametersthe same walk with its work named — arguments as snapshots, results as values, and the one write into your variable spelled address where you can see it
6The first failurea function that admits it can fail in its signature, a call the compiler makes you finish, and a missing file that arrives as a name, not a number
7The crossroadsone program using the whole numbered path plus its first record — and the guided map into the themed tutorials

Alongside them: installing Mica, the project file, Mica as a scripting language, and the two small features every program leans on — initializers, and the leave family.

Values and data

TutorialYou end up with
Ordinals: values that have a positionwhy one property explains for, case, array indexing and sets at once — arrays indexed by an enumeration rather than by an integer, and the two boundaries (wide integers, error codes) worth knowing
Values, and arrows drawn by handwhat an assignment copies — everything — and the one construct that shares: a pointer created with address, dereferenced with value, visible at every call site that can change your variable
Records, arrays, and bounds you chooseshapes named once in type, matrices as one type with two ranges, copies that reach all the way down — and an index checked at compile time or trapped at its named line
Dynamic arrays: growth under the value ruleAppend and Length, jagged tables spelled as what they are, and an assignment that still copies — so no callee can grow your list behind your back
Order and disorderSort as a native generic heapsort — in place, no allocation, worst case equals best — SubArray as the named piece, and a seeded Shuffle that is bit-stable on every machine
Conformant arrays: bounds as parametersone routine for fixed arrays of any bounds, a constant view that provably cannot write, and a pointer view consented to with address at the call
The sequence families: four faces, one lawfixed array, vector, dynamic array and span side by side — one reader vocabulary over all four, a copy that owns its elements all the way down, a borrow spelled where it is taken, the element verbs, and a whole value written as one list
Sets: membership as a valueset of a domain you named, the + - * algebra, the recovery-set idiom every recursive-descent parser needs — and bitset[N] when the positions are raw
Maps: two reading moods, one value rulea typed container where Get traps on the key you promised was there, Has/GetOr ask first, snapshots walk in insertion order — and assignment deep-copies, no hidden sharing
Bit records: bits with namestyped fields packed into exactly N bits, at pins the compiler proves against the derived layout, and the masked case whose arms read like the datasheet’s command table

Math and shapes

TutorialYou end up with
Vectors and matricesshape carried in the type — products refused when dimensions cannot meet, elementwise arithmetic with the scalar meet, * as the linear-algebra product with Dot and Transpose named beside it, and copies that stay copies
Dynamic tensorsvectors and matrices whose extents live in the value: Resize and the shape readers, the same operators at run-time extents under an always-on shape guard, static and dynamic mixing under one dimension-wise law, broadcasting spelled with RowSpread and ColumnSpread, Sum along a constant axis, and the rank-general tensor word above the pair
Linear algebraSolve, Invert, Cholesky, and Qr over dynamic matrices — singularity as an expected answer on the failure channel, the value model as the working storage, and every verification written in the operators themselves
Quantized tensorsthe one-byte element families int8 and uint8: storage the inference world packs its weights into, refused operators that name the road instead, and WideningProduct — the integer matmul whose int32 accumulation stands in its own name
Tracked values and the tapethe autograd surface as a language feature: the tracked pair, the recording window in the program’s own body, one backward walk answering every blame — with the recorded vocabulary, fan-out accumulation, the two honest zeros, and every wall quoted from the shipped binary
Model deptha model as records of tracked places and the optimizer walk as your own visible loop: the depth loop recording through blocks[k].w, Gradient per place, an Adam step over plain twin records through the conformant borrow, and the retrain window proving the cycle
The learning toolkitthe everyday pieces of a training loop: Relu/Gelu/Silu and RmsNorm recorded with their rules, the visible dropout pair whose gradient is the printed mask, MseLoss, the update family SgdStep/AdamWStep/ClipGradNorm/CosineSchedule, the elementwise HadamardMap (the SwiGLU gate’s own verb), and the seeded XavierInit/HeInit
Batched trainingpytorch’s training shape whole: a batched two-block transformer with the Gather embedding, Reshape on both sides of the causal batched attention, seeded dropout, the batched CrossEntropy over a matrix of targets, and the visible AdamW walk under the cosine schedule — every digit oracle-checked
Image networksthe convolutional family: Conv2d over channels-first tensors, the pooling pair with the documented tie, BatchNorm whose running statistics are your own visible values with ChannelScale as the inference line, and a small classifier trained end to end — every digit oracle-checked
The GPU, without kernelsa complete GPU program with no kernel in it: a tensor declared on gpu, the two transfer verbs, the mixing refusal quoted — and the same mathematics printing identical digits on host and device
The math unitgeneric scalar verbs at full type fidelity, constants that are declarations, IEEE classification through pure arithmetic, and the libm seam one import block tells whole
Big integersint128 to uint256 over a parameterized wide family, and the unbounded bigint with its verb arithmetic — 25 factorial printed whole, and the checked tier trapping where int64 would lie

AI — from the first guess to your own GPT

The course has its own page: Learn AI with Mica, with the map of a GPT part by part.

A course for readers with no machine-learning background, ending with a GPT you train yourself. It keeps one promise the whole way: every number you print is the same every run — learning you can repeat digit for digit.

TutorialYou end up with
The guessing machinewhat learning is, before any mathematics — a machine that fits a rule to observations with nothing but guess, measure, nudge, and a loss that falls to zero
Downhill in the fogthe gradient: direction and stride read off the guess itself, the measured and the computed slope agreeing to the last digit, and the descent that replaces search with arithmetic
The notebook that runs backwardthe tape: ’tracked’ knobs, the recording window, and one ‘Backward’ walk answering every slope — chapter 2’s descent reproduced digit for digit with the algebra done by the machine
Many knobs at oncevectors and the dot product: the same loop when the guess is a vector and a bias, one backward walk answering a whole gradient vector, and the shape checked before the run
The bent wirethe wall no weighted sum can climb — XOR’s loss flattening at exactly one — and ‘Tanh’, the one bend that climbs it with the same descent
Layerswhat a hidden layer learns: the four corners’ hidden coordinates printed before and after training, the want-1 corners landing together, and the one weighted sum that reads the learned space
Blame flows backwardbackpropagation by hand, exactly once: three per-link rules, a ledger walked from the loss to the knobs, and the tape’s answers matching yours to the last digit
The art of the stepone unfair valley descended three ways: the wall pricing the plain step, momentum saving it, and Adam — with the GPT’s own β₁ and β₂ — repealing it
Text becomes numberstokens, one-hot rows, and the embedding as learned meaning — closed by the smallest language model there is, trained to exactly 1.000000 on its three transitions, with the unseen character learning exactly nothing
Looking at everything at onceone attention head at the smallest honest size: query, key, and value in five recorded lines, the causal mask’s exact zero, the soft split’s exact halves, and blame walked backward through the softmax — exactly
The GPT, assembledGpt.mica read as one page: the eighteen-sentence window with each line’s home chapter, the 786944-parameter arithmetic, nine tensors, and the few honest newcomers — scale, residuals, layer norm, cross-entropy
Train your own GPTa corpus, one command, minutes of training, and text in your corpus’s style — reproducible to the digit, run after run, with the device twin’s diff showing exactly what moving training to a GPU means
Deterministic reductionsSum, Mean, the extremes and their indices on one documented pairwise tree — the same tree serially and in parallel, on both architectures, so a float reduction is a promise of the language
WYSIWYG slicingevery slice a named copy — Row, Column, SubMatrix, Window — shaped values built off the target’s declaration, with no view-or-copy roulette
Spans and the lending lawspan of T as the borrowed view in var, parameter and return positions — RowView, WindowView, and the lending law keeping every borrow inside a lifetime the caller can see

Strings

TutorialYou end up with
Text: the value, the builder, and the windowthe immutable string value that counts runes, the unit whose verbs answer new strings, the builder for the loops where + would copy — and the borrowed window that tokenizes with zero allocation
UTF sources: any script, one meaningidentifiers in any script with nothing special about them, rune counts no encoding can change, and the build-time encoding choice whose entire porting cost is one letter per format specifier
Pattern matchingpatterns compiled once into a linear-time engine no input can make pathological, a closed escape list refused loudly at compile — and rewriting, counting and groups over runes

Files

TutorialYou end up with
Files: the typed file and the failure channeltext out and back through one builder, a missing file as Enoent by name, byte positions you can ask for — and the two error kingdoms drawn through one surface
Typed transfers: whole values, and a file as an arrayWriteValue/ReadInto sized by the type itself, the plain constraint that refuses to write a heap descriptor’s bytes, and Seek arithmetic that indexes a file of records like an array
Paths and directoriesthe paths unit as pure text algebra — total, failure-free, industry semantics verb by verb — and the directory walk where a path meets the filesystem and its failure channel

Memory

TutorialYou end up with
Memory classes: hosted, and a fixed arenathe same source under the OS heap and under one fixed block — five thousand activations through a 16 KiB arena, and a budget that fails loudly at its named line
Heap, end to endan allocation as an obligation with exactly four discharges, use-after-free and double-free as compile-time reports, and the checked tier guarding what no proof can reach
Ownership and borrowingone owner per cell, borrowed as the checked word for everyone else, and the back edge that gives owned structures parents without a cycle of owners
What the compiler proves about your heapthe fourteen-row table: every classic heap bug and its exact fate — a refusal or a named-line trap — each produced by a real build or run
Defer, end to endcleanup registered beside the resource, run newest-first at the exit with exit-time values — and the exact rules for early leaves and loops

Errors

TutorialYou end up with
The failure channel: errors as valuesa function that admits it can fail in its signature, four clauses at the call site checked at compile time — and cleanup plus a propagation trace riding the failure exit for free
Error domains: the type behind the failurea domain that loops and indexes like any ordinal, walls that keep each layer’s failure story its own, conversion as a translation table the compiler completes — and -1-and-errno lifted into codes at the C boundary

Programs in the large

TutorialYou end up with
Generics: one algorithm, many typesthe gen clause with thirteen capability words, constraints that check the body and the call both ways, and monomorphization proved by an int64 that would not fit an int32
Units and libraries: surfaces, by declarationexp as the API decision, one import rule with no special cases, and a library whose contract the compiler emits so consumers can never drift from the source
Qualified namesimp cstd; making a namespace addressable and cstd.Sqrt saying where a word lives — two import granularities, one lookup mechanism, and a dot that is simply an import in disguise
The clocka monotonic Now whose differences alone carry meaning, duration constants making 250 * Millisecond read as meant, and a Sleep whose floor survives signals

Concurrency

TutorialYou end up with
Tasks and the task treeconcurrency where the block is the lifetime — a join no exit path can skip, arguments that are snapshots, and cancellation that still runs your cleanup
Generators and streamsa body that produces values one at a time and suspends between them, an instance you can pause and resume, and pipelines that compose
Carriers, multicore and busy loopsone thread or many as a build flag: what stays exact when you switch, and why a compute loop with no suspension point still gives way
Data-race freedom, proved at compile timethe rule behind synchronized, the two holes it closes that most languages leave open, and an honest account of its edges
Channel streams: the push halfthe same generator body scheduled as a producing task behind a bounded ring — fan-in, concurrent pipelines, select with a timeout, and the one exclusivity rule that keeps it all lock-free
When a stream failsa generator that admits fails in its type, the pull loop’s own consumption clause, cleanup that provably runs before the consumer hears — and the same word crossing a bounded ring
A server is a loopnetworking where a connection is a value and a wait suspends one task — so the readable spelling of a server is the scalable one, with no callback anywhere
A room is a streamthe multicore chat: one reading task per connection, one relay loop, and the fan-in stream where the conversations cross — plus a shutdown that is nobody’s job
The worker pool: fan-out over a ringone producer, one ring, N workers — a stream of parameter on a task as the fan-out shape, every value landing in exactly one worker, and a pull chain that still refuses with the fix spelled out
MPMC: the ring underneathfan-in and fan-out at once — M producers, N workers, one bounded ring, totals that prove exactly-once delivery on one carrier or four, and the partition-don’t-share discipline the compiler enforces
The value stream over the wiretyped values crossing a connection as framed transfers, a stream end that crosses with them — clean, or failing with the producer’s reason — and one on fail consuming every way the wire can go wrong
The client roadan address named three ways, the half-close that says “that was all” with the answer still owed, frames assembled from whatever pieces arrived — and the deadline that reaches a parked wait
The IPC roadthe same verbs with a kernel-namespace name instead of a port — no number to pick, no firewall in the way, nothing left behind, and a refusal that answers a health check by name

The boundary, and the debugger

TutorialYou end up with
Mica calls C: a contract, not a headera C library declared once in a schema-published JSON contract, lifted into Mica with full type checking at every call — scalars, packed aggregates and strings crossing both ways with no adapter
C calls Mica: an archive and a naming rulea plain C program linking a Mica archive like any static library — the target-name linkage rule, the shared ABI story told from both ends, and no runtime to initialize
Mica calls Linux: the kernel, without the -1POSIX and Linux through contracts embedded in the compiler, every system call an honest fails function — the errno dance compiled, never written
Callbacks at the boundarythe third declared subprogram kind: a routine a C library calls back into while your call runs — named only at a contract’s callback slot, never a value, its whole environment the context record you hand over
A notes application with sqlitethe road through the sqlite library: open, migrate, insert with binds, pull rows through a generator, read text columns — and the callback road when you want sqlite’s own shape
Debugging across the boundaryone gdb session over two languages: the Mica→C→Mica backtrace, both specializations of a generic inspected with their concrete types, the full VS Code setup — every transcript a real captured session
Profiling a Mica programfour instruments on one optimized binary: hyperfine for the headline, callgrind for the instruction-exact attribution by procedure and line, gdb stopping inside an inlined function under its own name, perf sampling on a cloud machine — every transcript a real captured session

Deep dives

Build a compiler with Mica — a complete working compiler, small enough to read in an afternoon, taken apart a piece at a time and rebuilt into native code, chapter by chapter, with Wirth’s 1975 original alongside.

The compiler, exported — one flag writes every intermediate representation to the build directory: fourteen numbered stages from token stream to heap narration, walked over one real program.

The advanced series spans values, strings, files, memory, errors, concurrency and the boundary — every example compiled, run and validated on both architectures before publication.

If you teach, or are working through Mica yourself and find a gap, we would like to hear about it: info@mica-dev.com.