[{"content":"This article is a practical introduction to writing Mica programs. It assumes familiarity with at least one compiled or structured language — the concepts are standard, but the syntax and semantics are Mica\u0026rsquo;s own. Mica is syntactically descended from Pascal, with influences from Modula-2 and Oberon, but it is a distinct language with its own type model, pointer semantics, and interoperability design.\nEach section is anchored to a working example from the official tutorials repository, available at gitlab.com/mica-lang/mica-tutorials. You will build and run them as you go.\nThe article covers the language surface introduced in Mica 4.5 — the first public release. It does not cover C interoperability, library construction, or the full standard library. For the complete type system specification and compiler internals, see the Technical Portrait.\n◈ Before You Start Requirements Ubuntu latest AMD64. The Mica compiler is developed and tested on this platform. Other Linux distributions may work but are not actively tested.\nMica compiler. Download the .deb package from mica-dev.com and install it:\nsudo apt install ./mica_latest_amd64.deb mica --version VS Code with the Mica language extension (mica-development-ug.mica-language) from the VS Code Marketplace. The extension provides syntax highlighting, inline error markers, and hover documentation for Mica source files.\nGDB for step debugging. Install it if it is not already present:\nsudo apt install gdb Getting the examples Clone the tutorials repository and open it in VS Code:\ngit clone https://gitlab.com/mica-lang/mica-tutorials.git code mica-tutorials All examples use a consistent Makefile interface. Run these commands from the repository root:\nmake -C examples/\u0026lt;Name\u0026gt; # build make -C examples/\u0026lt;Name\u0026gt; run # build and run make -C examples/\u0026lt;Name\u0026gt; clean # remove build artifacts Build output goes to examples/build/\u0026lt;Name\u0026gt;/. The default build produces full debug information, so every binary you produce is immediately debuggable without a separate step.\n◈ A First Program Open examples/Cast/Cast.mica. At 66 lines it is the smallest complete example in the repository, and it covers the mandatory skeleton of every Mica program.\nprogram Cast; imp WriteLn : std; var i32 : int32; i64 : int64; f32 : float32; f64 : float64; procedure PrintHeader(); begin WriteLn(\u0026#34;Mica Official Example: Cast\u0026#34;); WriteLn(\u0026#34;Part of the Mica compiler tutorial suite (Mica compiler project)\u0026#34;); end; begin PrintHeader(); i64 := 42; WriteLn(\u0026#34; int32 literal -\u0026gt; int64: %lld\u0026#34;, i64); f32 := 3.14159265359 as float32; WriteLn(\u0026#34; float64 literal as float32: %f\u0026#34;, f32); WriteLn(\u0026#34;Done.\u0026#34;); end. The skeleton Every Mica executable begins with program \u0026lt;Name\u0026gt;;. This line declares the compilation unit as an executable and names it — the compiler uses this name for the output binary.\nThe imp block imports identifiers from libraries or other compilation units. The format is Identifier : source. Here, WriteLn is imported from std, the standard output library. Multiple identifiers from the same source can be listed on one line, separated by commas.\nThe var block declares variables at module scope. Every variable carries an explicit type annotation, separated from the name by a colon. There is no type inference; every declaration states its type.\nThe main execution block starts with begin and ends with end. — note the period. This is the program entry point. Procedure and function bodies close with end; (semicolon); only the final end. of a compilation unit carries a period. This distinction is consistent throughout Mica.\nAssignment and comparison use distinct operators that differ from most C-derived languages:\nPurpose Operator Example Assignment := i64 := 42; Equality = if a = b then Inequality # if a # b then WriteLn is variadic and uses C-style format strings. It always appends a newline. Write is the same without the newline.\nBuild and run make -C examples/Cast run Output:\nMica Official Example: Cast Part of the Mica compiler tutorial suite (Mica compiler project) ---------------------------------------------------------------- == Implicit promotions == ---------------------------------------------------------------- int32 literal -\u0026gt; int64: 42 constant folding (release build): 60 == Intended promotions (casts) == ---------------------------------------------------------------- float64 literal as float32: 3.141593 float64 -\u0026gt; float32 -\u0026gt; float64: 3.141593 int32 -\u0026gt; int8 -\u0026gt; int32: 127 int32 -\u0026gt; int16 -\u0026gt; int64: 1000 negative int32 -\u0026gt; int16 -\u0026gt; int64: -42 Done. Compilation unit types Mica has three kinds of compilation unit:\nKeyword Role Main block program Executable entry point begin...end. — runs at program start object Single-function compilation unit begin...end. — required but empty library Multi-function library module begin...end. — required but empty The object and library keywords are covered in the Object Units section below.\n◈ Types and Variables Numeric types Mica provides a complete set of fixed-width integer and floating-point types:\nType Width Signed Range (approx.) int8 8-bit yes −128 to 127 int16 16-bit yes −32,768 to 32,767 int32 32-bit yes −2.1 billion to 2.1 billion int64 64-bit yes −9.2 × 10¹⁸ to 9.2 × 10¹⁸ uint8 8-bit no 0 to 255 uint16 16-bit no 0 to 65,535 uint32 32-bit no 0 to 4.3 billion uint64 64-bit no 0 to 1.8 × 10¹⁹ float32 32-bit IEEE 754 — ±3.4 × 10³⁸ float64 64-bit IEEE 754 — ±1.8 × 10³⁰⁸ Additional scalar types:\nType Description bool 8-bit boolean; values are True and False string UTF-32 wide string descriptor unicode Single UTF-32 code point Declarations Variables are declared in a var block, one or more names followed by a colon and the type. Multiple variables of the same type can share a declaration line:\nvar i32 : int32; i64 : int64; f32 : float32; f64 : float64; a, b, c : int32; { three int32 variables } Variables declared at the top of a compilation unit are module-scoped. Variables declared inside a procedure or function body are local to that routine and are not visible outside it.\nExplicit casting When you need a value interpreted as a narrower or different type, use the as keyword. The cast is explicit and visible in the source:\nf32 := 3.14159265359 as float32; { truncate double literal to float32 } i32 := 127 as int8; { cast through int8 range, then widen to int32 } i64 := 1000 as int16; { value fits; no truncation } i64 := -42 as int16; { signed cast preserved correctly } Integer and floating-point literals are implicitly promoted to the declared target type when the assignment is widening. Narrowing always requires an explicit as.\nFormat specifiers WriteLn and Write use C printf-style format strings. The specifier for each type:\nType Specifier Notes int8 %hhd int16 %hd int32 %d int64 %lld uint8 %hhu also used for bool (prints 0 or 1) uint16 %hu uint32 %u uint64 %llu float32 %f scientific: %e float64 %lf scientific: %le string %ls wide string unicode %lc wide character The examples/Playground example exercises every numeric type and its format specifier in a single run — a useful reference when writing output for unfamiliar types.\n◈ Procedures and Functions Procedures A procedure is a named routine with no return value. Parameters are declared in a comma-separated list, each with an explicit type annotation:\nprocedure PrintSection(name : string); begin WriteLn(\u0026#34;== %ls ==\u0026#34;, name); end; Local variables live in a var block placed between the procedure signature and its begin:\nprocedure ShowRepeatUntil(); var n : int32; total : int32; begin n := 1; total := 0; repeat total := total + n; n := n + 1; until n \u0026gt; 10; WriteLn(\u0026#34; sum (repeat until n \u0026gt; 10) = %d\u0026#34;, total); end; Functions A function is a routine that returns a value. The return type is declared after the parameter list. The return value is set by assigning to the function\u0026rsquo;s own name — there is no return keyword:\nfunction IncrementAndReturnTrue() : bool; begin counter := counter + 1; IncrementAndReturnTrue := True; end; Assigning to the function name sets the return value. Execution continues to the end of the body unless leave is used to exit early.\nThe leave statement leave exits a procedure or function immediately at any point in its body. In functions it is used after assigning the return value:\nfunction Fibonacci(n : int32) : int64; begin if n \u0026lt;= 1 then begin Fibonacci := n as int64; leave; { exit; skip the recursive case } end else Fibonacci := Fibonacci(n - 1) + Fibonacci(n - 2); end; leave takes no argument. It is the sole mechanism for early exit from a routine.\nCalling convention Mica functions comply with the System V AMD64 ABI — the same calling convention used by C on Linux x86_64. There is no overhead at the boundary between Mica and C. This is covered in depth in the interoperability examples (MicaCallsC, CCallsMica).\nNested procedures Mica supports nested procedure definitions. An inner procedure declared inside an outer routine is lexically scoped to that routine — it has access to the outer procedure\u0026rsquo;s local variables, and it is not visible outside the enclosing scope. The examples/Nesting example demonstrates five levels of nesting with shared variable mutation across each level.\nbegin\u0026hellip;end vs. begin\u0026hellip;end. This distinction is worth stating clearly:\nLocation Terminator Example Inside a procedure or function end; begin ... end; Main block of a compilation unit end. begin ... end. The period appears exactly once per source file, at the very end.\n◈ Control Flow The examples in this section are taken from examples/Playground/Playground.mica and examples/ShortCircuit/ShortCircuit.mica.\nif / then / else if actual = expected then begin WriteLn(\u0026#34; [PASS] %ls: result=%hhu\u0026#34;, testName, actual); passed := passed + 1; end else begin WriteLn(\u0026#34; [FAIL] %ls: result=%hhu (expected %hhu)\u0026#34;, testName, actual, expected); failed := failed + 1; end; No parentheses are required around the condition. A single-statement branch does not require begin...end; multi-statement branches do. The else branch is optional.\nfor / to / downto The for loop iterates a declared ordinal variable over a range. to is ascending; downto is descending:\n{ Ascending } sum := 0; for i := 1 to 10 do sum := sum + i; WriteLn(\u0026#34; sum 1..10 = %d\u0026#34;, sum); { 55 } { Descending } sum := 0; for i := 10 downto 1 do sum := sum + i; WriteLn(\u0026#34; sum 10 downto 1 = %d\u0026#34;, sum); { 55 } The loop variable must be declared in the enclosing var block. Enum types are valid loop variables — the loop iterates the ordinal sequence from one enum constant to another:\nfor c := Red to Yellow do begin case c of Red: WriteLn(\u0026#34; Red\u0026#34;); Green: WriteLn(\u0026#34; Green\u0026#34;); Blue: WriteLn(\u0026#34; Blue\u0026#34;); Yellow: WriteLn(\u0026#34; Yellow\u0026#34;); end; end; repeat / until repeat...until is a post-test loop. The body always executes at least once; the loop continues until the condition becomes True:\nn := 1; total := 0; repeat total := total + n; n := n + 1; until n \u0026gt; 10; WriteLn(\u0026#34; sum (repeat until n \u0026gt; 10) = %d\u0026#34;, total); { 55 } n := 5; repeat WriteLn(\u0026#34; countdown: %d\u0026#34;, n); n := n - 1; until n = 0; WriteLn(\u0026#34; liftoff!\u0026#34;); The repeat and until keywords serve as delimiters — no begin...end is needed around the body.\nwhile / do while...do is a pre-test loop. The body does not execute if the condition is initially False:\nx := -2; y := -1; while x + y \u0026lt; 3 do begin x := x + 1; y := y + 1; WriteLn(\u0026#34; loop step: x =%3d y =%3d\u0026#34;, x, y); end; For a single-statement body, begin...end may be omitted.\ncase The case statement dispatches on an integer or ordinal value. Each branch is a constant (or comma-separated list of constants) followed by a colon and a statement:\nday := 3; case day of 1: WriteLn(\u0026#34; Monday\u0026#34;); 2: WriteLn(\u0026#34; Tuesday\u0026#34;); 3: WriteLn(\u0026#34; Wednesday\u0026#34;); 4: WriteLn(\u0026#34; Thursday\u0026#34;); 5: WriteLn(\u0026#34; Friday\u0026#34;) else WriteLn(\u0026#34; Weekend\u0026#34;) end; The final branch before end or else does not require a trailing semicolon. The else branch catches any value not matched by the listed cases; if else is omitted and no branch matches, execution continues after end.\nEnum constants work as branch labels:\ncolor := Blue; case color of Red: WriteLn(\u0026#34; warm tone\u0026#34;); Green: WriteLn(\u0026#34; natural tone\u0026#34;); Blue: WriteLn(\u0026#34; cool tone\u0026#34;); Yellow: WriteLn(\u0026#34; bright tone\u0026#34;); end; Short-circuit evaluation and and or evaluate left to right and stop as soon as the result is determined. For True or expr, the right side is never evaluated. For False and expr, the right side is never evaluated. This matters when the right-side expression has side effects:\ncounter := 0; result := True or IncrementAndReturnTrue(); { counter is still 0 — right side was not called } counter := 0; result := False or IncrementAndReturnTrue(); { counter is 1 — right side was called } counter := 0; result := False and IncrementAndReturnTrue(); { counter is 0 — right side was not called } The examples/ShortCircuit example verifies this behavior across 27 test cases. Build and run it:\nmake -C examples/ShortCircuit run == Test summary == ---------------------------------------------------------------- Passed: 27 Failed: 0 ALL TESTS PASSED ◈ Pointers and Mutation Mica uses explicit pointers for any mutation through a reference. There is no implicit pass-by-reference: every parameter is passed by value unless it is declared as a pointer type.\nThe three operators Syntax Meaning pointer T A type: pointer to T address x Take the address of variable x (analogous to \u0026amp;x in C) value p Dereference pointer p (analogous to *p in C) A function that reads and then mutates through a pointer:\nfunction AllNumericTypesAsPointers(aInt32 : pointer int32, ...) : bool; begin WriteLn(\u0026#34; *int32: %d\u0026#34;, value aInt32); { read through pointer } value aInt32 := value aInt32 + 1; { mutate through pointer } end; Calling it by passing the address of a variable:\nAllNumericTypesAsPointers(address i32, ...); WriteLn(\u0026#34;Modified from main: int32=%d\u0026#34;, i32); After the call, i32 has been incremented. The mutation is visible in the caller because the function received a pointer, not a copy. The change of ownership is explicit and visible at the call site.\nConst pointers When a procedure needs to read through a pointer but must not mutate, declare the parameter as const pointer T. The value dereference is read-only:\nfunction F(const p : pointer int32) : int32; begin F := value p + G(p); { read and pass the const pointer further } end; function G(const p : pointer int32) : int32; begin G := value p + H(value p); { read through const pointer; pass the value } end; function H(p : int32) : int32; begin H := p + 84; end; This pattern from examples/ReadLnUsage shows how a const pointer passes through a call chain without copying the pointed-to value at each call boundary.\nPointers and input ReadLn takes addresses as arguments, in the same style as C\u0026rsquo;s scanf:\nWrite(\u0026#34;Enter an integer: \u0026#34;); r := ReadLn(\u0026#34;%d\u0026#34;, address a); WriteLn(\u0026#34; int32 value: %d (result=%d)\u0026#34;, a, r); ReadLn returns the number of items successfully scanned. The scan count lets you detect malformed input. Read is the non-newline-consuming variant.\nWhy explicit pointers Mica has no implicit reference semantics. Any routine that modifies the caller\u0026rsquo;s data must declare a pointer parameter, and the caller must explicitly pass address variable. Mutation is auditable at the call site — there is no hidden aliasing to reason about.\n◈ Object Units and Multi-File Builds As a program grows, its functions are split across multiple source files. Mica uses two unit types for this: object for single-function units, and library for multi-function modules.\nThe object keyword An object unit exports one or more functions or procedures for use by other units. It has the same structure as a program, but the begin...end. block is empty — the unit has no independent execution path.\nFrom examples/Playground/Fibonacci.mica:\nobject Fibonacci; { Recursive Fibonacci (shows leave) } function Fibonacci(n : int32) : int64; begin if n \u0026lt;= 1 then begin Fibonacci := n as int64; leave; end else Fibonacci := Fibonacci(n - 1) + Fibonacci(n - 2); end; begin { Objects include an empty compound statement } end. The function Fibonacci is exported automatically. Any program unit compiled alongside this object can import and call it.\nImporting The imp block in a program names what to import and where it comes from:\nimp WriteLn : std; ProgramName, ArgCount, Arg : process; Fibonacci : Fibonacci; FibonacciIterative : FibonacciIterative; Each line reads: import Identifier from unit UnitName. The unit name matches the object or library declaration in the corresponding source file.\nRecursive vs. iterative The Playground example includes both Fibonacci implementations as separate object units. The iterative version in FibonacciIterative.mica uses a for loop:\nobject FibonacciIterative; function FibonacciIterative(n : int32) : int64; var a, b, temp : int64; i : int32; begin a := 0; b := 1; if n \u0026lt;= 1 then begin FibonacciIterative := n as int64; leave; end else begin for i := 2 to n do begin temp := a + b; a := b; b := temp; end; FibonacciIterative := b; end; end; begin { Objects include an empty compound statement } end. Both produce identical results for inputs they share. The iterative version handles arbitrarily large n without stack growth — the recursive version becomes impractical past around Fib(40):\nFib(40) = 102334155 { both versions return the same value } Fib(90) = 2880067194370816120 { iterative only; recursive is not shown } Multi-file compilation Build the Playground example to compile all three source files together:\nmake -C examples/Playground run The Makefile invokes the compiler with all source files listed under --source:\nmica --compile --link \\ --optimize debug \\ --platform linux,amd64,utf-32 \\ --assembly intel \\ --source Playground.mica,Fibonacci.mica,FibonacciIterative.mica \\ --build ./build The compiler resolves imp declarations by matching unit names in the source file headers against the supplied source list. There is no separate manifest or registry file.\n◈ Debugging in VS Code The tutorials repository ships a pre-configured .vscode/launch.json with three debug profiles:\nDebug Current Mica Binary — builds and debugs the example corresponding to the active editor Debug MicaCallsC — cross-language session: Mica program calling a C library Debug CCallsMica — cross-language session: C program calling a Mica library For the basics, the first profile is the one to use.\nWalkthrough Open examples/Playground/Playground.mica in VS Code.\nSet a breakpoint inside ShowForLoops — click the gutter to the left of the line sum := 0; that begins the ascending loop. A red dot appears.\nPress F5. VS Code presents the launch profile selector; choose Debug Current Mica Binary. The Makefile builds the example first (producing a binary with full DWARF v5 debug information), then GDB attaches to it and execution halts at your breakpoint.\nThe Run and Debug panel on the left shows Locals, Watch, Call Stack, and Breakpoints.\nPress F10 (step over) to advance one line at a time. Watch i and sum update in the Locals panel as the loop iterates.\nPress F11 (step into) to descend into a procedure call. Press Shift+F11 (step out) to return to the caller.\nThe debugger maps each machine instruction back to the Mica source line that produced it — you step through source, not assembly. This is source-level debugging with no extra configuration.\nAssembly view If you want to see the generated instructions alongside the source, use the Disassembly View button in the debug toolbar, or right-click a breakpoint and choose \u0026ldquo;Open Disassembly View\u0026rdquo;. The assembly is in Intel syntax throughout.\nDebug vs. release builds The default Makefile target builds with --optimize debug — fast compilation, full debug information, minimal optimization. Stepping through this build behaves as expected: each source line corresponds to a discrete machine sequence.\nTo build with optimizations enabled:\nmake -C examples/ConstantFolding MICA_OPTS=release,constant_folding Stepping through an optimized build can be surprising. The compiler may reorder, inline, or eliminate code. Use the debug build for debugging and the release build for benchmarking or assembly inspection.\n◈ What to Explore Next The tutorials repository covers progressively more of the language surface. After working through the examples above, the natural next steps are:\nAll numeric type boundaries — examples/Playground exercises the complete scalar type set including pointer parameters for every type, all control flow constructs, ordinal types (enums, subranges, sets with the in membership operator), and packed aggregates.\nFormatted input — examples/ReadLnUsage adds Read and ReadLn with scan-count return values, unicode character input, and a const-pointer call chain.\nBoolean evaluation semantics — examples/ShortCircuit is a self-contained verification of short-circuit behavior across 27 test cases, organized by expression complexity.\nConstant folding — examples/ConstantFolding demonstrates how the compiler evaluates constant expressions at compile time under the release,constant_folding profile. Compare the assembly sizes before and after to see the effect directly.\nMath library — examples/MathPower covers the float32 and float64 transcendental functions: Sin, Cos, Tan, Sqrt, Exp, Pow, Ln, Log10, and more, with a precision comparison between the two widths.\nLinux system calls — examples/MicaCallsLinux calls POSIX and Linux-specific interfaces directly from Mica source across two namespaces: posix (process identity, file operations) and linux (scheduler, memory file descriptors, kernel personality).\nC interoperability — examples/MicaCallsC, examples/CCallsMica, and examples/MicaCallsMica demonstrate the full JSON-contract model for calling C libraries from Mica and Mica libraries from C. All three use the same shared Utilities library across four calling surfaces: scalar packets, ordinal wrappers, packed aggregates, and text.\nFor the complete language specification — the type system, operators, scoping rules, compilation pipeline, optimization passes, and ABI details — the Technical Portrait is the authoritative reference. The Roadmap describes what is scheduled for version 4.6 and beyond.\n","permalink":"https://mica-website.gitlab.io/learning/mica-basics/","summary":"\u003cp\u003eThis article is a practical introduction to writing Mica programs. It assumes familiarity with at\nleast one compiled or structured language — the concepts are standard, but the syntax and semantics\nare Mica\u0026rsquo;s own. Mica is syntactically descended from Pascal, with influences from Modula-2 and\nOberon, but it is a distinct language with its own type model, pointer semantics, and\ninteroperability design.\u003c/p\u003e\n\u003cp\u003eEach section is anchored to a working example from the official tutorials repository, available at\n\u003ca href=\"https://gitlab.com/mica-lang/mica-tutorials\"\u003egitlab.com/mica-lang/mica-tutorials\u003c/a\u003e. You will\nbuild and run them as you go.\u003c/p\u003e","title":"Learning Mica — The Basics"},{"content":"Version 4.5 · Released March 2026\nStructured clarity. C control. Born for AI.\nA note on accuracy\nMica is developed by a single engineer working with AI assistance. This portrait represents the best current description of the language and compiler — but it is a living document. Specific names, API spellings, library namespaces, and feature boundaries will change as implementation reveals what actually works. Inaccuracies and inconsistencies can and do occur.\nWhat will not change is the direction and the vision. The platform philosophy, the commitment to explicit semantics, the structured-language foundation, and the AI trajectory are stable. Everything else is subject to revision as the compiler grows.\nMica 4.5 is the first public release. The compiler is verified by a test harness spanning 576 Mica programs, but as with any first release, unexpected limitations may still be encountered. The compiler, the VS Code extension, and the tutorials are under intensive development throughout 2026 — changes can and will occur. The primary goal for 2026 is a consistent, well-designed Mica core language with a complete standard library. Known gaps — including heap memory allocation, a string library, and further standard library coverage — will be addressed in the course of this work.\n◈ What Is Mica? Mica is a systems programming language designed for readability, explicit control, and a long-range trajectory toward AI-native compiler semantics. It brings clean, structured syntax together with the low-level control that systems programmers need — without hiding the machine behind abstractions you didn\u0026rsquo;t ask for.\nThe Mica compiler is written in pure Go with zero external dependencies. It compiles Mica source code all the way down to native Linux x86_64 ELF binaries with DWARF v5 debug information, using only the GNU assembler and linker as final tools. There is no LLVM. There is no GCC backend. Every phase of compilation — from lexical analysis through register-level peephole optimization — is implemented from scratch inside this single repository.\nAfter two and a half years and 1,844 commits of quiet, disciplined development, Mica 4.5 is the first public release: a real compiler that produces real binaries you can run, inspect in GDB, and call from C.\n◈ At a Glance Metric Value Implementation language Go 1.26, pure standard library Compiler Go source files 322 Compiler gross lines (Go, incl. comments \u0026amp; whitespace) 75,545 Test harness Go implementation files 27 Test harness gross lines (Go) 5,404 Mica test programs (.mica files) 576 Mica test program gross lines 151,958 Standard library (C23, mica-stdlib.c) 778 lines Assembly runtime routines 4 Assembly runtime instructions ~31 Total project gross lines ≈ 234,000 Packages 25 Test cases 538 (execution, errors, IL, assembly) Execution tests 266 Error tests 200 IL tests 49 ASM tests 23 Total commits 1,844 First commit December 27, 2023 Current version 4.5.0 Target platform Linux x86_64, System V AMD64 ABI Debug format DWARF v5 Binary format ELF External toolchain GNU assembler (as) + GNU linker (ld) License MCL-1.0 (non-commercial; commercial licensing available) Stress test timings (StressLOC series):\nTest Time StressLOC100k (100,000-line program) 6.687 s StressLOC10k 718 ms StressLOC1k 142 ms Assembly runtime — Mica emits a small set of hand-written x86_64 routines directly into each compiled binary. The current four routines (~31 instructions total) handle static link traversal for nested procedures, byte-level string comparison via repe cmpsb, and the non-returning runtime failure path. They are deliberately minimal: each routine does exactly one well-defined job, carries precise register documentation, and stays out of the way of the C standard library. The set will grow as the language grows — heap allocation, bounds checking, and concurrency primitives are natural additions — but the design principle remains the same: keep the runtime small, keep it correct, and let the platform handle everything it already does well.\n◈ Why Mica Exists There is a space between languages that is surprisingly empty.\nSome languages are easy to read but stay far from the machine. Others give you raw control but demand constant vigilance against misuse. Few bridge both worlds cleanly — and fewer still have a credible direction for what programming should look like in an AI-shaped future.\nMica occupies that space deliberately:\nDimension What Mica delivers Why it matters Readability Clean block structure, nested functions, records, arrays, sets, ordinal types, structured control flow Code that communicates intent, teachable from day one, analyzable without context Control Explicit pointers, explicit address/dereference, direct ABI compatibility, contract-based interop Systems behavior is predictable; FFI cost is visible, never hidden Direction Compiler-driven optimization, mathematical notation, tensor-native semantics (planned) A language shaped toward AI and numerical computing from the start, not retrofitted after the fact Mica is not trying to become an object-oriented language with classes and inheritance. Mica is not building a package-manager ecosystem. Abstraction in Mica comes from records, procedures, nested functions, and contract-defined interfaces — proven structures that stay readable at any scale.\n◈ The Platform Vision Mica does not build a private ecosystem. It opens the one that already exists.\nThe world already has decades of proven C libraries, POSIX interfaces, Linux kernel APIs, and battle-tested system runtimes. They are not going anywhere. Every HTTP client, every database driver, every numerical toolkit, every operating system interface — already written, already tested, already running on billions of machines. Mica\u0026rsquo;s goal is not to replace any of that. It is to make all of it immediately and safely accessible from structured, readable source code.\nMost new languages ask developers to wait while an ecosystem is built from scratch. Mica takes the opposite position: the ecosystem already exists. It is the entire C ABI world — and Mica is designed to reach every part of it directly.\nThe JSON contract system is the mechanism. Every C library surface, every POSIX API, every Linux syscall that follows a stable ABI can be described in a contract file and reached from Mica source with full type checking, format-string validation, and compile-time safety. A Mica binary and a C library binary are the same kind of object. They link together directly under the System V AMD64 ABI. There is no adapter layer. There is no runtime bridge. There is no reimplementation required.\nThis principle shapes every architectural decision in Mica:\nThe standard library grows by surfacing what already exists, not by reimplementing it in a closed language-specific world. WriteLn and ReadLn are not new I/O systems — they resolve directly to wprintf and wscanf (or printf/scanf on UTF-8 platforms). The compiler selects the right platform function; the developer writes one clean call. The planned posix and linux contract packs will give Mica programs access to the full Linux OS API surface without leaving the language. C interop is first-class, not an escape hatch. A contract file is how you reach any C library — whether it ships with Mica, was authored by a third party, or was written ten years before Mica existed. Mica programs and C programs share one binary world. They call each other, link together, and cooperate under the same ABI with no performance tax at the boundary. Two languages sharing a platform are not competitors. A Mica binary and a C binary can be linked into the same executable. A Mica library can be called from C. A C library can be called from Mica. The platform is the ecosystem — and Mica belongs to it without trying to displace it.\nThe measure of success is not how many libraries Mica ships. It is how quickly a developer can reach any library that already exists — including libraries written years from now — with the same structured, safe, readable source model that defines the rest of the language.\nMica augments the platform. It does not compete with it.\n◈ A First Look at Mica The best way to introduce a language is to show it. Every snippet below is real, compiled code from the 4.5 test suite.\nThe language reads like structured intent type Color = (Red, Green, Blue); var c : Color; begin c := Green; case c of Red: WriteLn(\u0026#34;red\u0026#34;); Green: WriteLn(\u0026#34;green\u0026#34;); Blue: WriteLn(\u0026#34;blue\u0026#34;); end; end. No integer casts. No fall-through hazards. No magic numbers. The source says exactly what the program means — and the compiler enforces the domain. A Color variable cannot accidentally hold an integer, and an integer cannot silently become a Color.\nEnumerations carry their domain into arrays type Month = (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec); Calendar = array[Month] of int32; var days : Calendar; begin days[Jan] := 31; days[Feb] := 28; days[Mar] := 31; end. The array is indexed by Month values, not integers. The compiler enforces domain correctness at every index site. There is no invisible month - 1 translation, no risk of an off-by-one born from a zero-based convention, and no way to index a calendar with an unrelated integer.\nEvery pointer operation is spelled out procedure Scale(p : pointer Point; factor : float64); begin p.x := p.x * factor; p.y := p.y * factor; end; pointer Point in the signature is an unambiguous statement: Scale modifies the caller\u0026rsquo;s record. Not T*, not an implicit reference — a readable description of intent, visible at every call site. Adding a field to Point does not silently change the calling convention. Passing a Point by value requires writing p : Point, nothing more.\nNotice that p.x works directly — no explicit dereference required. When the base of a field selection chain is a pointer to a record, the compiler lowers the dereference automatically during semantic analysis. The explicit form value p.x is also valid and produces identical machine code. More on this in the semantic analysis chapter.\nImports are platform calls, not a private ecosystem imp WriteLn : std; Sin : math; WriteLn resolves to wprintf. Sin is libm. The names are clean and readable, but nothing is invented underneath — the compiled binary calls the exact same functions every C program on the system uses. There is no separate I/O runtime, no reimplemented math library, no translation layer. The import statement names a library and a contract; the platform provides the rest.\n◈ What Makes This Compiler Different Zero external dependencies. The Mica compiler is written in pure Go with no external libraries. go build ./... is all you need. The standard library links against as and ld and nothing else. This is an intentional discipline: the compiler should be understandable, buildable, and modifiable by any engineer with a Go toolchain — on any machine, without first assembling a dependency graph.\nEvery stage is inspectable. Every intermediate representation can be exported and examined: the token stream from the scanner, the AST from the parser, human-readable Spectra IL from the generator, x86_64 assembly in Intel or AT\u0026amp;T syntax, and the final ELF binary with DWARF v5 debug information. This makes Mica not just a compiler but a teaching instrument. You can watch a program transform step by step from source to machine code and read exactly what happened at each stage.\nHarness-first development. The 538 test cases are not regression tests — they are the specification of what the compiler can do. No feature lands without harness coverage across execution, error, IL, and assembly tests, with variants for different compiler configurations. This discipline has kept the compiler honest across 1,844 commits and two and a half years of development.\nABI truthfulness. The type system knows exactly how every type is classified under the System V AMD64 ABI — INTEGER, SSE, or MEMORY. The function call emitter uses that classification directly. The DWARF debug information describes what was actually generated. When you step through a Mica program in GDB, the stack frames look exactly like what the ABI specification says they should — because they are built that way from the ground up, not adjusted afterward.\n◈ What Mica Looks Like All examples below are real, compiled programs from the 4.5 test suite.\nHello, Mica program ConstExpression; imp WriteLn : std; const Sum = 5 + 7 * 2; Difference = (20 - 3) * 2; Product = (6 as int64) * 7; Ratio = 9.0 / 2.0; Check = (Sum = 19) and (Difference \u0026gt; 30); var i32 : int32; i64 : int64; f64 : float64; flag : bool; begin i32 := Sum; WriteLn(\u0026#34; Sum = %d\u0026#34;, i32); i64 := Product; WriteLn(\u0026#34; Product = %lld\u0026#34;, i64); f64 := Ratio; WriteLn(\u0026#34; Ratio = %.2lf\u0026#34;, f64); flag := Check; WriteLn(\u0026#34; Check = %hhu\u0026#34;, flag); end. This is a complete, compilable Mica program. The structure is clean and readable — program, const, var, begin\u0026hellip;end. — alongside C-level type specificity (int32, int64, float64) and familiar format-string I/O. The standard library function name WriteLn follows Mica\u0026rsquo;s PascalCase naming convention for callable library symbols.\nConstant expressions like 5 + 7 * 2 are evaluated entirely at compile time. The variable Sum never generates a runtime computation.\nRecursive Functions function Factorial(n : int32) : int64; begin if n \u0026lt;= 1 then Factorial := 1 else Factorial := (n as int64) * Factorial(n - 1); end; Functions return values by assigning to their own name. The as keyword performs explicit type conversion. This is real recursive code generating real call frames, traced correctly by DWARF and GDB.\nNested Functions with Lexical Scoping function Outer(base : int32) : int32; var offset : int32; function Inner(input : int32) : int32; begin Inner := input + offset; end; begin offset := 10; Outer := Inner(base); end; Inner reads offset from its enclosing scope. The compiler implements this through a static link chain in activation records — a real frame-pointer chain that GDB can follow and that the test suite verifies at every nesting level.\nThe for Loop program ForIntegralLoops; imp WriteLn : std; var i : int32; sum : int32; begin sum := 0; for i := 0 to 3 do sum := sum + i; WriteLn(\u0026#34;ascending sum = %d\u0026#34;, sum); for i := 3 downto 0 do WriteLn(\u0026#34;i = %d\u0026#34;, i); end. The for loop supports to (ascending) and downto (descending) directions. Loop bounds are evaluated exactly once before the first iteration — verified by a dedicated test ForBoundsEvaluatedOnce that counts function call invocations. The control variable is read-only inside the loop body: direct assignment, address-of, and outer-scope access are all compile-time errors.\nThe loop also handles terminal-bound safety correctly. When the control variable reaches the final bound and would need to overflow to continue, Mica exits before the step — making for i := MaxInt32 - 1 to MaxInt32 safe with exactly two iterations.\n{ For loops work with enum control variables too } type Color = (Red, Green, Blue); var c : Color; begin for c := Red to Blue do begin if c = Red then WriteLn(\u0026#34;color = Red\u0026#34;); if c = Green then WriteLn(\u0026#34;color = Green\u0026#34;); if c = Blue then WriteLn(\u0026#34;color = Blue\u0026#34;); end; end. Subrange and enum types are fully supported as control variable types. The loop domain is checked at compile time: boolean and set types are rejected with clear error messages.\nThe repeat ... until Loop program RepeatSimple; imp WriteLn : std; var i : int32; begin i := 1; repeat WriteLn(\u0026#34;i = %d\u0026#34;, i); i := i + 1; until i \u0026gt; 3; WriteLn(\u0026#34;done, i = %d\u0026#34;, i); end. repeat ... until is the post-test loop: the body always executes at least once, and execution continues until the condition becomes True. This is the natural companion to while — and its semantics are verified by a dedicated RepeatExecutesOnce test that confirms guaranteed first-iteration execution even when the condition is already true at entry.\n{ Leaving early from a repeat loop } repeat if i = 2 then leave; total := total + i; i := i + 1; until i \u0026gt; 3; leave exits the enclosing procedure, not just the loop. The test suite covers leave inside while, for, and repeat bodies.\nThe case Statement program CaseEnumMatch; imp WriteLn : std; type Color = (Red, Green, Blue); var color : Color; begin color := Green; case color of Red: WriteLn(\u0026#34;red\u0026#34;); Green: WriteLn(\u0026#34;green\u0026#34;); Blue: WriteLn(\u0026#34;blue\u0026#34;); end; end. The case statement dispatches on any ordinal selector — integers, subranges, enumerations. Each arm is a constant label followed by a statement or begin...end block. An optional else branch handles unmatched values.\n{ case with integer selector and else branch } case selector of 1: WriteLn(\u0026#34;one\u0026#34;); 2: WriteLn(\u0026#34;two\u0026#34;) else WriteLn(\u0026#34;other\u0026#34;) end; The 4.5 implementation covers single constant labels with optional else. The compiler enforces that labels must be ordinal, must be compile-time constants, must be compatible with the selector type, and must not repeat. The no-semicolon-before-else rule is enforced consistently across both if and case — tested by dedicated error cases in the harness.\nProcess Arguments program ProcessArguments; imp * : std; * : process; begin if ProgramName() # Empty then WriteLn(\u0026#34;program=present\u0026#34;) else WriteLn(\u0026#34;program=empty\u0026#34;); WriteLn(\u0026#34;count=%d\u0026#34;, ArgCount()); if Arg(1) = \u0026#34;alpha\u0026#34; then WriteLn(\u0026#34;arg1=match\u0026#34;); if Arg(2) = \u0026#34;Grüße\u0026#34; then WriteLn(\u0026#34;arg2=match\u0026#34;); end. The process library exposes program arguments through three clean functions: ProgramName(), ArgCount(), and Arg(n). The program declaration stays parameterless — no C-style argc/argv in the entry point — and all argument access goes through ordinary library calls. This is tested in both UTF-32 and UTF-8 execution modes, including Unicode argument values.\nRecords, Pointers, and Explicit Memory type Point = record x : int32; y : int32; end; var point : Point; ptr : pointer Point; begin point.x := 4; point.y := 9; ptr := address point; { Explicit form — always valid } value ptr.x := value ptr.x + point.y; { Auto-deref form — also valid for pointer-to-record field selection } ptr.x := ptr.x + point.y; WriteLn(\u0026#34;x = %d\u0026#34;, point.x); WriteLn(\u0026#34;y = %d\u0026#34;, point.y); end. This is where Mica\u0026rsquo;s memory model comes into focus:\npointer Point — a pointer type, declared in plain words address point — takes the address of a variable (no \u0026amp; operator) value ptr — dereferences a pointer to read or write the full pointed-to value (no * operator) value ptr.x — explicit dereference-then-select, reading naturally left to right Pragmatic auto-deref for pointer-to-record field selection. Mica is explicit about memory by principle — but not dogmatic about it. For pointer-to-record field selection chains specifically, writing value is optional. When the semantic analyzer encounters ptr.x and ptr is a pointer Point, it recognizes the pattern and the lowering pass automatically inserts a dereference node before code generation. The rewrite p (*struct) → dereference(p) produces identical machine code to the explicit value ptr.x form — there is no runtime difference, no extra indirection, no overhead of any kind.\nThis is a deliberate pragmatic choice. Requiring value on every field access through a pointer adds ceremony without adding clarity — the field selector already names the target unambiguously. The value keyword carries its weight where it matters: full pointer dereference to read or write the complete pointed-to value, passing a dereferenced value as an argument, or any case where the dereference is not immediately followed by a named field.\nThe rule is precise and local: auto-deref applies only to pointer-to-record identifier bases in selection chains. Everything else remains explicit. Arrays do not decay to pointers. Aggregate types carry no implicit reference semantics. The auto-deref is typed, deterministic, and lowered during semantic analysis — not a runtime behavior.\nSets, Subranges, and Membership type N = 0..3; NSet = set of N; function Build(lo : N, hi : N) : NSet; begin Build := [lo..hi]; end; function Contains(v : N, s : NSet) : bool; begin Contains := v in s; end; Sets are first-class values. They can be passed to and returned from functions, constructed with range expressions at runtime, and queried with in. The set constructor [lo..hi] generates real machine code for dynamic bounds.\nShort-Circuit Evaluation { The right side is NEVER evaluated when left side is False for and, or True for or. The compiler generates conditional jumps, not eager calls. } result := False and IncrementTrue(); { counter stays 0 — right side was skipped } result := True or IncrementFalse(); { counter stays 0 — right side was skipped } Checked Arithmetic program CheckedArithmeticPolicyDebugRelease; imp WriteLn : std; var a, b, c : int64; begin a := MaxInt64; b := 1; c := a + b; WriteLn(\u0026#34;signed_add_result=%lld\u0026#34;, c); end. This single program produces three different behaviors depending on the compiler\u0026rsquo;s optimization policy:\n--optimize debug or release: hardware wrap semantics, overflow is silent --optimize checked: compiler-inserted overflow detection terminates the program with a diagnostic including source file and line number The harness verifies all three behaviors automatically via test variants — same source, different flags, independently validated expected output.\nAll Numeric Types Mica provides the full set of fixed-width types that systems programmers expect:\nCategory Types Signed integers int8, int16, int32, int64 Unsigned integers uint8, uint16, uint32, uint64 Floating-point float32, float64 Boolean bool Character unicode (32-bit code point) String string (UTF-32, descriptor-based) Every type has a precise size, a precise ABI classification, and predictable behavior at every optimization level.\n◈ The Ordinal Universe One of the most powerful ideas in Mica\u0026rsquo;s type system is the concept of ordinal types and the rich type algebra that flows from them.\nIn most languages, \u0026ldquo;number\u0026rdquo; and \u0026ldquo;sequence\u0026rdquo; are the same thing. Arrays start at zero. Loops count upward. Enumerations are secretly integers. Sets are bit masks. The programmer\u0026rsquo;s domain model — months, colors, grades, directions — is expressed in raw integers and the meaning is carried only in the programmer\u0026rsquo;s head.\nMica offers a different way of thinking.\nWhat Is an Ordinal? An ordinal type is any type whose values form a finite, ordered, discrete sequence with a well-defined first element, last element, and successor function. Every value in an ordinal type can be counted, compared, and used as an index.\nMica\u0026rsquo;s ordinal types are:\nType Domain Example Values bool {False, True} 2-element binary ordinal int8\u0026hellip;int64 Integer intervals -128..127, 0..2147483647 uint8\u0026hellip;uint64 Unsigned intervals 0..255, 0..18446744073709551615 unicode Unicode code points 'a', 'π', '漢' Enumeration Named constants Red, Green, Blue Subrange Restricted interval 1..31, 0..9 Ordinals — Domain Knowledge Carried by the Type System This is not just a programming convenience. Mica\u0026rsquo;s type system carries ordinal domain knowledge natively — ordinals know their bounds, and the compiler uses that knowledge structurally throughout the language.\nEvery ordinal type — integers, booleans, unicode, enumerations, and subranges — has computable domain bounds: the compiler knows its exact lower and upper values. Dedicated type system functions resolve the [lower, upper] interval of any ordinal type, determine whether a constant value lies within that domain, find the common ordinal type for binary operations, and establish the underlying arithmetic base type for ordinal calculations. Whether one ordinal value can be assigned to another ordinal type is governed by explicit domain-aware rules, not silent integer coercions.\nThat domain knowledge drives a surprising amount of the language:\nArray sizes are computed from ordinal index domains, not raw constants Set cardinalities are computed from the ordinal domain of the element type for loop bounds are validated against the ordinal domain of the control variable case label validation checks that each label is within the ordinal domain of the selector Subrange assignment is checked against the declared interval The type system doesn\u0026rsquo;t just permit ordinals — it knows their domains and uses that knowledge everywhere those types appear. The rest of this section shows what that enables.\nEnumerations — Naming the Domain type Color = (Red, Green, Blue, Yellow); Direction = (North, East, South, West); Month = (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec); An enumeration is not a shorthand for integer constants. It is a new type with its own named domain. Red is not 0. It is Red. The compiler knows the type is Color, knows the domain has four elements, and can reject nonsense like assigning a Direction to a Color variable.\nThe ordinal ordering of enum values follows their declaration order. Red \u0026lt; Green \u0026lt; Blue \u0026lt; Yellow holds. You can use enum values as array indices, set elements, and for-loop bounds — all of which become semantically meaningful rather than numerically arbitrary.\nSubranges — Restricting the Domain type Day = 1..31; Month = 1..12; Digit = 0..9; Grade = 1..5; Slot = 1..3; A subrange declares that a variable holds values only within a specified interval. Day is not int32. It is a type whose domain is exactly {1, 2, ..., 31}. The compiler knows the bounds. Arrays indexed by subranges have a known and exact size. Sets over subranges have a known and exact cardinality.\nThis changes what you can express in a type signature. A function that accepts a Day is telling the truth about what values it accepts. A function that accepts int32 and happens to only use values 1..31 is carrying its contract only in comments.\nArrays with Ordinal Index Types — and Lower Bounds That Mean Something This is where the ordinal model becomes concretely powerful.\nIn most languages, arrays start at zero. Always. That is a hardware convention that leaked into language design: memory addresses start at zero, so array indices start at zero. The problem is that most real-world domains do not start at zero. Months start at 1. Floors in a building are numbered. A temperature sensor covers −20 to 60. A population table runs from 1900 to 2100. A convolution kernel is centered at zero and runs from −2 to 2.\nEvery time the domain doesn\u0026rsquo;t start at zero, the programmer carries an invisible translation burden: daysInMonth[month - 1], population[year - 1900], kernel[offset + 2]. That subtraction is not part of the problem. It is an artifact of the storage model leaking into the logic. Forget it once and you read the wrong data — silently.\nMica arrays have a lower bound that belongs to the type, not to the programmer\u0026rsquo;s memory. The index type is an ordinal type, and the array spans exactly the domain of that type:\ntype Month = (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec); DaysInMonth = array[Jan..Dec] of int32; { Years 1900 to 2100 — the lower bound is part of the type } PopulationTable = array[1900..2100] of int64; { A convolution kernel centered at zero — negative lower bound } Kernel = array[-2..2] of float64; { Workdays 1..5, not 0..4 } WeekdayHours = array[1..5] of int32; DaysInMonth[Jan] is the number of days in January. Not daysInMonth[0]. Not daysInMonth[MONTH_JAN - 1]. The index is the month, because the array\u0026rsquo;s domain is the month domain.\npopulation[1970] is the population in 1970. Not population[1970 - 1900].\nkernel[-1] is the kernel value at offset −1. Not kernel[-1 + 2].\nThe compiler knows both bounds. It computes the array\u0026rsquo;s size from upper - lower + 1 — no programmer arithmetic required, no opportunity to get it wrong. Constant index accesses outside the declared range are a compile-time error.\nvar pop : PopulationTable; k : Kernel; begin pop[1900] := 1_600_000_000; pop[2000] := 6_100_000_000; k[-2] := 0.0625; k[-1] := 0.25; k[0] := 0.375; k[1] := 0.25; k[2] := 0.0625; end. This code reads exactly like the problem it models. A reader who knows the domain immediately understands the code. A reader who doesn\u0026rsquo;t know the domain can read the type declaration and immediately understands the valid range. There is nothing to decode, no constant to subtract, no comment needed to explain why the index starts where it does.\nWith enum-typed indices the benefit compounds further:\ntype Color = (Red, Green, Blue, Yellow); ColorWeights = array[Red..Yellow] of float64; var weights : ColorWeights; begin weights[Red] := 0.2126; weights[Green] := 0.7152; weights[Blue] := 0.0722; weights[Yellow] := 0.0; end. There is no index 4 that silently writes past the end. There is no integer 0 standing in for Red. The array has exactly as many elements as the domain has values — computed by the compiler from the type, not declared by the programmer as a separate constant that can drift out of sync.\nMulti-dimensional arrays compose naturally, mixing index types freely:\ntype Grid = array[1..3, Red..Blue] of int32; var g : Grid; begin g[1, Red] := 10; g[2, Green] := 20; g[3, Blue] := 30; end. Sets — Membership, Not Bit Manipulation type Color = (Red, Green, Blue, Yellow); ColorSet = set of Color; var palette : ColorSet; warm : ColorSet; combined : ColorSet; begin palette := [Red, Green, Blue]; warm := [Red, Yellow]; if Red in palette then WriteLn(\u0026#34;Red is in the palette\u0026#34;); if not (Yellow in palette) then WriteLn(\u0026#34;Yellow is not in the palette\u0026#34;); end. Sets in Mica are mathematical sets over an ordinal domain. They are not bit flags. They are not integers with \u0026amp; and |. They are sets. Membership is tested with in. Construction uses set literal syntax [...] with optional range expressions [lo..hi].\nCompare this to typical C:\n/* C: the programmer manually maintains the bit-shift contract */ #define RED (1 \u0026lt;\u0026lt; 0) #define GREEN (1 \u0026lt;\u0026lt; 1) #define BLUE (1 \u0026lt;\u0026lt; 2) #define YELLOW (1 \u0026lt;\u0026lt; 3) int palette = RED | GREEN | BLUE; if (palette \u0026amp; RED) { ... } /* is this testing bit 0? who knows */ In Mica, the set is typed. The domain is known at compile time. The element type is Color, not int. Red in palette reads like the question it is asking.\nSets also combine with ranges in constructors:\ntype Digit = 0..9; DigitSet = set of Digit; var evens : DigitSet; odds : DigitSet; begin evens := [0, 2, 4, 6, 8]; odds := [1, 3, 5, 7, 9]; odds := [1..9]; { range constructor } end. For Loops Over Ordinal Domains The for statement\u0026rsquo;s natural home is the ordinal type:\n{ Enumerate all colors — no off-by-one possible } for c := Red to Yellow do begin schedule[c] := ComputeValue(c); end; { Iterate over a subrange domain } for day := 1 to 31 do WriteLn(\u0026#34;Day %d\u0026#34;, day); { Count down through an enum } for d := Blue downto Red do WriteLn(\u0026#34;color index = %d\u0026#34;, d as int32); The loop domain is the domain of the ordinal type. For an enum, the loop visits every named value in declaration order. For a subrange, it visits every integer in the interval. The control variable is read-only inside the loop body — the compiler enforces this, because a for loop means iteration over a domain, not arbitrary mutation of a counter.\nThe Semantic Expressiveness This Enables When ordinal types, arrays with ordinal indices, and sets work together, the code says what it means — not just how it computes:\ntype WorkDay = (Mon, Tue, Wed, Thu, Fri); WorkDaySet = set of WorkDay; HourTable = array[Mon..Fri] of int32; var meetings : WorkDaySet; workHours : HourTable; total : int32; begin meetings := [Mon, Wed, Fri]; workHours[Mon] := 8; workHours[Tue] := 9; workHours[Wed] := 6; workHours[Thu] := 9; workHours[Fri] := 7; total := 0; for day := Mon to Fri do begin if day in meetings then workHours[day] := workHours[day] - 1; total := total + workHours[day]; end; end. No magic integers. No enum-to-int casts for array indexing. No bit-mask arithmetic for set membership. The code reads like the domain model it describes. A compiler — or a reader — can verify it locally without knowing any context outside the type declarations.\nNested Ordinal Types — Records Containing Sets Containing Ordinals The real power emerges when these concepts compose:\ntype Color = (Red, Green, Blue, Yellow); Digit = 0..9; Slot = 1..3; DigitSet = set of Digit; ColorSet = set of Color; ScoreArray = array[1..3] of int32; ColorArray = array[Red..Yellow] of int32; Item = record id : Digit; flags : DigitSet; scores : ScoreArray; end; Inventory = record rows : array[1..3] of Item; palette : ColorArray; enabled : ColorSet; end; This data structure is fully verified by the compiler:\nItem.id must be in 0..9 — the type enforces it Item.flags is a set over 0..9 — membership uses in, not bit shifts Item.scores has exactly 3 elements, indexed 1 to 3 — not 0 to 2 Inventory.palette is indexed by Color values, not by integers 0–3 Inventory.enabled is a set of Color — Red in inv.enabled just works And all of this is passed by value, returned by value, nested at arbitrary depth — all with real machine code, DWARF annotations, and verified by the test suite.\nLooking Forward — Ordinals in the AI Trajectory The ordinal type system is infrastructure for Mica\u0026rsquo;s long-range direction.\nWhen Mica eventually adds fixed-shape vector and matrix types, the shape dimensions will naturally be expressed as ordinal types or subranges. An array indexed by 0..3 and an array indexed by AxisX..AxisW are the same machine layout — but the latter carries meaning that enables compile-time shape checking:\n{ Future Mica syntax — not implemented yet } type Axis = (X, Y, Z, W); Vec4 = vector[Axis] of float32; Mat4x4 = matrix[Axis, Axis] of float32; The connection from today\u0026rsquo;s array[Red..Blue] of int32 to tomorrow\u0026rsquo;s matrix[Axis, Axis] of float32 is direct. The type system already knows how to represent, index, and validate ordinal-indexed aggregates. The AI trajectory builds on the same foundation, not a different one.\nSets over ordinal types become natural precursors to predicate types and domain restrictions in a type system that reasons about data shapes. Subranges become natural representations for index bounds in tensor operations. The for loop over an ordinal domain becomes the natural surface for shape-driven iteration over tensor dimensions.\nMica is not retrofitting these ideas into a language that was built around raw integers. It is growing them out of a foundation that was designed for them.\n◈ A Language for the Platform — Not Above It The goal is not to replace the platform. The goal is to meet it.\nOperating systems, native libraries, and hardware interfaces represent decades of accumulated engineering. Linux, glibc, POSIX, BLAS, OpenSSL, SDL, Vulkan — these exist, they are stable, they are fast, and they are documented. The problem with many modern language ecosystems is that they build a second world on top of this first one: a second memory manager, a second I/O runtime, a second type system for FFI, a second dependency graph, a second security model. The developer ends up living in the second world and treating the first as a distant, hostile country they occasionally have to visit.\nMica makes the opposite bet. Every C library on the system is a Mica library, described by a JSON contract and callable directly — no wrappers, no glue layers, no marshaling overhead. The system allocator is the allocator. The ELF loader is the loader. The OS scheduler is the scheduler. GDB is the debugger, because Mica binaries carry accurate DWARF v5 debug information.\nWriteLn and ReadLn are not new I/O systems This is the vision made concrete. When a Mica developer writes:\nWriteLn(\u0026#34;Balance = %d EUR\u0026#34;, balance); ReadLn(\u0026#34;%d\u0026#34;, n); there is no Mica I/O runtime underneath. The compiler resolves WriteLn to wprintf and ReadLn to wscanf — the same wide-character standard C library functions that every C program on the system has always used. On a UTF-8 platform the contract resolver selects printf and scanf instead. The developer writes one call. The compiler selects the right platform function based on the target encoding. No new I/O ecosystem. No new runtime. No new abstraction to learn, document, or maintain.\nThis is not a special case. It is the design rule. When you import * : math;, you are importing the same libm that every C program on your system uses. When you link a Mica library as a .so, it is a regular shared object that any C program can dlopen. The binary is a first-class citizen of the platform from the first line of compiled code.\nConsequences that matter The entire ecosystem is already available. Every C library reachable from the system is reachable from Mica, through a contract file, with compile-time type safety and format-string validation — today, not after an ecosystem matures. Native tooling works without configuration. Profilers, debuggers, address sanitizers, linker scripts, and ELF inspection tools all work because the binary is a normal ELF binary with normal DWARF information. Mica binaries and C binaries are equal citizens. They link together, call each other, and share the same ABI with no performance tax at the boundary. There is no bootstrapping problem. There is no \u0026ldquo;Mica ecosystem\u0026rdquo; that must reach critical mass before useful programs can be written. The contract system A JSON contract describes a C library\u0026rsquo;s type surface, calling conventions, and ABI layout precisely enough that the Mica compiler can validate calls at compile time — including format strings, argument types, and cross-unit type fingerprints. The developer gets compile-time safety without runtime overhead and without writing a single line of binding code.\nAs the Mica standard library grows, every piece of it is designed to delegate to the native platform for what the platform already does well. Mica\u0026rsquo;s UTF-32 string model sits on top of wchar_t. The math library is libm with a clean contract. The planned posix and linux contract packs will be curated access layers over real POSIX syscalls and Linux kernel APIs — not reimplementations.\nMica augments the platform. It does not compete with it.\n◈ The Compilation Pipeline Mica implements a textbook-clean compilation pipeline with explicit phase boundaries. Every intermediate representation can be inspected, exported, and reasoned about independently.\n┌───────────────┐ │ Source Code │ UTF-8 encoded .mica files └───────┬───────┘ ▼ ┌───────────────┐ │ Scanner │ Lexical analysis → Token stream └───────┬───────┘ ▼ ┌───────────────┐ │ Parser │ Recursive descent → Abstract Syntax Tree └───────┬───────┘ ▼ ┌───────────────┐ │ Analyzer │ 8 semantic passes → Enriched, validated AST └───────┬───────┘ ▼ ┌───────────────┐ │ Generator │ AST traversal → Spectra IL (three-address code) └───────┬───────┘ ▼ ┌───────────────┐ │ Emitter │ IL → x86_64 assembly instructions └───────┬───────┘ ▼ ┌───────────────┐ │ Optimizer │ 17 peephole passes → Cleaned assembly └───────┬───────┘ ▼ ┌───────────────┐ │ ELF/DWARF │ Binary encoding + DWARF v5 debug information └───────┬───────┘ ▼ ┌───────────────┐ │ GNU Binutils │ as + ld → Executable, static library, or shared object └───────────────┘ ◈ Phase 1 — The Scanner Package: scanner/ · ~10 files\nThe scanner converts UTF-8 source bytes into a stream of tokens. It sets the tone for Mica\u0026rsquo;s philosophy: careful, position-tracked, and fully Unicode-aware.\nToken Categories Literals: Integer, FloatingPoint, String, Unicode character Operators: +, -, *, /, =, #, \u0026lt;, \u0026lt;=, \u0026gt;, \u0026gt;= Symbols: (, ), [, ], ,, :, ;, ., .., := Keywords: Over 45 reserved words, including (as of 4.5): program, library, function, procedure, record, array, set, pointer, address, value, if, then, else, while, do, for, to, downto, repeat, until, case, of, begin, end, leave, and, or, not, mod, odd, as, in, imp, const, var, type, packed Numeric Literals The scanner supports decimal, hexadecimal (0x), and binary (0b) integer literals with optional digit separators. Floating-point literals support scientific notation (1.0e20, 3.4028235e+38).\nComments { Block comments can span multiple lines } // Line comments run to end of line x := 5; // Inline comments too Position Tracking Every token carries its source line and column. This propagates through the entire pipeline — from scanner through DWARF debug information — so error messages, runtime failures, and debugger breakpoints always point to exact source locations.\n◈ Phase 2 — The Parser Package: parser/ · ~32 files\nThe parser is a classic recursive descent implementation that transforms the token stream into an Abstract Syntax Tree. It handles the full Mica grammar: declarations, type expressions, all statement forms, and expressions with correct operator precedence.\nProgram Structure Every Mica source file begins with either program (for executables) or library (for reusable modules), followed by declaration sections in order:\nprogram/library → imp → const → type → var → procedures/functions → begin...end. Operator Precedence Level Operators Category 1 (highest) not, -, +, odd Unary 2 *, /, mod Multiplicative 3 +, - Additive 4 =, #, \u0026lt;, \u0026lt;=, \u0026gt;, \u0026gt;=, in Comparison / Membership 5 and Logical AND (short-circuit) 6 (lowest) or Logical OR (short-circuit) Statements (Complete 4.5 Surface) Statement Form Notes Assignment x := expr Including value ptr.field := expr Call Proc(args) Procedure or discarded function call Compound begin ... end Sequence of statements If if cond then stmt [else stmt] No semicolon before else While while cond do stmt Pre-test loop For for v := init to/downto final do stmt Control variable read-only Repeat repeat stmts until cond Post-test, always executes once Case case sel of labels... [else stmt] end Ordinal selector only Leave leave Exits current procedure Type Expressions Form Syntax Example Record record fields end Point = record x, y : int32; end Packed record packed record fields end No internal padding Array array[bounds] of T array[1..10] of float64 Multi-dim array array[b1, b2] of T array[1..2, Red..Blue] of int32 Set set of OrdinalType set of Digit Subrange Low..High 1..31 Enum (Name1, Name2, ...) (Red, Green, Blue) Pointer pointer BaseType pointer Point File file of T file of int32 Nesting Depth Functions and procedures can be nested up to 16 levels deep. The parser tracks nesting depth and propagates it through the AST for static-link generation.\nError Recovery The parser implements token-level synchronization to continue after syntax errors. A single compilation can report multiple diagnostics rather than stopping at the first problem.\n◈ Phase 3 — The Abstract Syntax Tree Package: ast/ · 67 files (the largest single package)\nThe AST is the central data structure of the compiler. It represents every syntactic construct as a typed node in a tree, and it serves as the shared currency between parsing, analysis, code generation, and export.\nNode Taxonomy The AST defines 26+ node kinds organized into five categories:\nDeclarations — the things a program defines: Import, Constant, Parameter, Variable, Signature, Function, DataType, RecordField\nExpressions — the things a program computes: Arithmetic, UnaryArithmetic, Comparison, Logical, UnaryLogical, Memory (address-of, dereference), Conversion (casts), Selection (field / index)\nType Expressions — the shapes of data: Record, Array, Set, Subrange, Enum, File, SetConstructor\nStatements — the things a program does: Assignment, Call, Leave, If, While, For, Repeat, Case, Compound\nUses — references to declared things: IdentifierUse, LiteralUse\nThe For, Repeat, and Case statement node kinds each carry their semantics as typed fields: direction for For, condition for Repeat, selector and arm list for Case.\nThe Visitor Pattern The AST is traversed using the visitor pattern with double dispatch. This separates the structure of the tree (defined once in ast/) from the operations on it (defined in analyzer/, generator/, and other packages).\nTraversal orders supported: PreOrder, InOrder, PostOrder, LevelOrder.\nThe Global Registry For multi-file compilation, the AST package maintains a global registry that coordinates declarations across compilation units. Imports are validated through type fingerprinting — a deterministic digest of the type\u0026rsquo;s structure that detects ABI mismatches before linking.\nSymbol Annotations Each declaration node carries metadata that enriches through the pipeline:\nFlatName — internal name for intermediate code (e.g., f2.1) GlobalName — external symbol name for library exports Value — compile-time constant value (when applicable) PassingMode — how the parameter travels at the ABI level NestingDepth — scope level for static-link generation ◈ Phase 4 — The Type System Package: typesystem/ · 37 files\nThe type system is the backbone of Mica\u0026rsquo;s static guarantees. It describes every data type, tracks its properties, and determines what operations are legal.\nType Kinds Kind Examples Notes Signed integers int8, int16, int32, int64 1/2/4/8 bytes Unsigned integers uint8, uint16, uint32, uint64 1/2/4/8 bytes Floating-point float32, float64 IEEE 754 Boolean bool 1 byte Unicode unicode 4 bytes, 32-bit code point String string Descriptor: pointer + length, UTF-32 Record user-defined Ordinary or packed layout Array user-defined Fixed-size, multi-dimensional, custom index bounds Set user-defined Over any ordinal domain Subrange user-defined Restricted ordinal interval Enumeration user-defined Named ordinal constants Pointer pointer T Explicit pointer to any type File file of T Typed file I/O Function / Procedure callable types Parameter types, return type Type Capabilities Rather than a hard-coded switch statement, Mica uses a capability bit-mask system. Each type advertises what it can participate in:\nCapability Meaning Numeric Supports +, -, *, / Ordered Supports \u0026lt;, \u0026lt;=, \u0026gt;, \u0026gt;= Equality Supports =, # Logical Supports and, or, not Integral Integer-specific operations Fractional Float-specific operations Dereferenceable Can use value to dereference Addressable Can use address to take address Convertible Can use as to cast Negatable Supports unary - Callable Can be called as a function Selectable Supports .field access Indexable Supports [index] access Ordinal Has a discrete ordered domain (required for for, case, set) This design keeps the analyzer clean: \u0026ldquo;is this type valid as a for-loop control variable?\u0026rdquo; is a single capability query, not a sprawling type switch.\nABI Awareness The type system is ABI-aware from the ground up. Every type knows:\nIts size in bytes on the target platform Its alignment requirement How it is passed to functions (integer register, SSE register, hidden pointer) How it is returned from functions Its System V AMD64 classification: INTEGER, SSE, or MEMORY This means function signatures tell the truth. Adding a field to a record does not silently change how it is passed. An array does not decay to a pointer. The performance model is visible in the source.\n◈ Phase 5 — Semantic Analysis Package: analyzer/ · 22 files · Package: evaluation/ · 20 files\nThe analyzer validates that a syntactically correct program is also semantically correct — names resolve, types match, constants fold, and every operation and statement form obeys its rules.\nEight Coordinated Passes Pass 1 ─── StaticShallow ─────────── Register top-level declarations Pass 2 ─── StaticImportAttach ────── Resolve imports across files Pass 3 ─── StaticResolveDeferred ─── Resolve forward references Pass 4 ─── StaticDeep ───────────── Full semantic validation Pass 5 ─── Lowering ─────────────── Normalize expression forms Pass 6 ─── TypeCoercion ─────────── Insert implicit conversions Pass 7 ─── ConstantFolding ──────── Evaluate compile-time constants Pass 8 ─── StaticWarn ───────────── Report unused declarations Pass 1 — StaticShallow registers all top-level names without analyzing bodies, allowing later passes to resolve references regardless of declaration order.\nPass 2 — StaticImportAttach connects imported declarations from other compilation units, matching them to their exported symbols.\nPass 3 — StaticResolveDeferred handles forward-reference dependencies, such as mutually referential types.\nPass 4 — StaticDeep is the main validation pass. It resolves every identifier use to its declaration, checks every operation against its operand types, validates call argument counts and types, checks array index types, validates set membership, detects uninitialized pointers, enforces for-loop control-variable rules (read-only in body, correct ordinal domain, no address-of, no outer-scope reuse), validates case labels (ordinal, constant, compatible with selector, no duplicates), and checks until conditions are boolean. This pass produces over 100 distinct error codes with precise diagnostic messages.\nPass 5 — Lowering normalizes expressions into canonical forms the code generator expects.\nPass 6 — TypeCoercion inserts explicit conversion nodes where implicit widening is allowed, making coercions visible and explicit in the tree.\nPass 7 — ConstantFolding evaluates constant expressions at compile time. 5 + 7 * 2 becomes the integer 19 before any code is generated. The evaluation/ package implements the full set of compile-time arithmetic, comparison, logical, and cast operations — including detecting division by zero, infinity, and NaN in constant expressions.\nPass 8 — StaticWarn detects unused variables, parameters, and imports.\nQuality Gates The analyzer includes a quality gate system — internal consistency checks that verify the compiler\u0026rsquo;s own transformations are correct. These are compiler self-tests that run during development, not user-facing guards.\nFor-Statement Analysis The analyzer enforces the full for contract in Pass 4:\nControl variable must be a local variable (not a parameter, constant, return variable, or outer-scope variable) Control variable type must be integral, enum, or subrange (not boolean, set, record, or array) Inside the loop body, the control variable is marked active and any assignment or address-of operation is rejected Nested for loops cannot reuse an active outer control variable Case-Statement Analysis Selector must have an ordinal type Each label must be a compile-time constant of an ordinal type compatible with the selector Duplicate labels are rejected No semicolon is permitted immediately before else ◈ Phase 6 — Spectra: The Intermediate Language Package: intermediate/ · 14 files · Package: generator/ · 16 files\nBetween the high-level AST and the low-level x86_64 assembly sits Spectra — Mica\u0026rsquo;s three-address code intermediate language. Spectra is where the program stops being a tree and becomes a flat sequence of operations that map almost directly to machine instructions.\nWhat Three-Address Code Looks Like Each Spectra instruction is a quadruple: an operation with up to three addresses (two inputs and one output). Here is the IL for a simple loop:\nv1.1:int32 = literal 0:int32 { i := 0 } store v1.1:int32, i m1.2:int32 = literal 3:int32 { final bound, evaluated once } store m1.2:int32, _final .loop_test: m1.3:int32 = load i m1.4:int32 = load _final jumpGreater m1.3:int32, m1.4:int32, .loop_exit { loop body here } m1.5:int32 = load i m1.6:int32 = literal 1:int32 m1.7:int32 = add m1.5:int32, m1.6:int32 store m1.7:int32, i jump .loop_test .loop_exit: Every value has a name (like m1.3), a type annotation (like :int32), and a clear origin. The m prefix denotes a temporary, v denotes a variable, p denotes a parameter.\nThe Instruction Set Spectra defines 37 operations across clean categories:\nArithmetic — add, subtract, multiply, divide, modulo Unary — negate, odd Comparison — equal, notEqual, less, lessEqual, greater, greaterEqual Logical — and, or, not Conversion — cast Memory — literal, load, store Structure — loadField, storeField Array — loadElement, storeElement Set — clearSet, includeSetValue, includeSetRange, containsSetValue Control flow — jump, jumpEqual, jumpNotEqual, jumpLess, jumpLessEqual, jumpGreater, jumpGreaterEqual, branchTarget Functions — argument, call, loadReturn, storeReturn, prologue, epilogue\nAddress Design A key architectural decision is the separation of identity from storage. An address name like m2.3 is a lookup key into the symbol table — not a memory location. The actual storage (which register, which stack slot) is decided later during activation record layout and emission.\nAddresses carry memory modifiers:\nValue (default) — direct access to the value Address — address-of Indirect — dereference through a pointer And projections for structured access:\nm1.1:int32 = loadField v1.1.point.x:int32 { record field } m1.2:int64 = loadElement v2.1[]:int64, idx { array element } For-Loop IL The generator produces a specific pattern for for loops that reflects the guarantee of exactly-once bound evaluation and exit-before-step terminal safety:\n{ Evaluate and save both bounds before the loop } m_init = \u0026lt;initial expression\u0026gt; m_final = \u0026lt;final expression\u0026gt; { evaluated exactly once, stored } store m_init, control_var .test: m_cur = load control_var { ascending: jumpGreater cur, final, .exit } { descending: jumpLess cur, final, .exit } { body } { Step — only if we haven\u0026#39;t hit the bound yet } { ascending: check overflow before increment } m_next = add/subtract m_cur, 1 store m_next, control_var jump .test .exit: The IL tests ILForLoopTo and ILForLoopDownto verify this pattern with CHECK directives against the exact generated intermediate representation.\nThe Expression Stack — Compile-Time Slot Management One of the more interesting internal mechanisms in the code generator is the expression stack — and the important thing to understand about it is that it exists entirely at compile time. It leaves no trace in the generated code.\nWhen the generator traverses an expression tree — say a + b * c — it produces a sequence of Spectra IL instructions, each yielding a temporary result. In a naive implementation, those temporaries might be pushed and popped on the CPU stack at runtime. Mica takes a fundamentally different approach: every temporary result is assigned a pre-calculated, fixed slot in the activation record during code generation, before any assembly is emitted.\nHow it works:\nWhen a sub-expression produces a result, the generator finds the lowest-numbered slot that is not currently occupied by any live temporary — across both the expression stack and any held scopes — and assigns that name to the result (for example m1.1, m1.2, m1.3). The temporary is recorded as live.\nWhen a consumer needs that result, the temporary is popped from the compile-time stack in LIFO order and its slot number becomes available for reuse by the next temporary.\nSlot reuse is what keeps activation records compact. If the temporary in slot m1.1 is consumed before the next temporary is created, the next temporary reuses slot 1. At any point, the number of occupied slots equals the maximum depth of simultaneously live temporaries — not the total number of temporaries ever produced.\nFor expressions that cannot be consumed in strict LIFO order — short-circuit logical operators, set constructors, call argument sequences — the generator opens a held scope. While a held scope is open, its temporaries remain marked as live and their slots are protected from reuse even after being consumed by the generating code. When the scope closes, the held temporaries return to the caller for further use.\nThe outcome: by the time the activation record layout is calculated, every temporary already has a deterministic name pointing to a fixed offset below RBP. The emitter generates mov instructions to load and store values at those offsets. There are no runtime push/pop sequences for expression evaluation. The CPU stack pointer moves exactly once per function call — in the prologue — and never again.\nThis is a deliberate architectural choice about where complexity belongs. The expression stack ensures that complexity lives in the compiler, not in the generated code. The output is simple, predictable, and debugger-friendly.\nActivation Record Layout Before any assembly is emitted, the compiler calculates a complete activation record layout for every function:\nCALLER\u0026#39;S FRAME ┌──────────────────────────────────────────┐ │ [rbp+16] 7th argument (stack-passed) │ │ [rbp+8] Return address │ │ [rbp+0] Saved RBP │ ◄── RBP ├──────────────────────────────────────────┤ │ [rbp-8] Static link │ │ [rbp-16] Param 1 home (rdi copy) │ │ [rbp-24] Param 2 home (rsi copy) │ │ ... │ │ [rbp-N] Local variable 1 │ │ [rbp-N-8] Local variable 2 │ │ ... │ │ [rbp-M] Temporary storage section │ │ ... │ ◄── RSP (16-byte aligned) └──────────────────────────────────────────┘ CALLEE\u0026#39;S FRAME Every offset is fixed at compile time. Same-named temporaries share a single stack slot sized to the largest type that occupies it. All section boundaries are 16-byte aligned per the ABI.\nNested Function Access For nested functions accessing enclosing-scope variables, Spectra tracks the scope depth of each access. A variable reference v3.2^1 means \u0026ldquo;variable v3.2 from one scope level up.\u0026rdquo; The emitter translates this into a chain of static-link dereferences at runtime.\n◈ Phase 7 — The Emitter Package: emitter/ · 58 files (including sub-packages)\nThe emitter is where Spectra IL becomes real x86_64 machine instructions. It is the largest subsystem in the compiler, because x86_64 is an intricate architecture with intricate calling conventions.\nInstruction Selection The emitter translates each IL operation into one or more x86_64 instructions. This is not a simple 1:1 mapping: integer addition, unsigned addition, and floating-point addition generate different instruction sequences. Signed division requires cqo + idiv. Comparisons produce cmp followed by setCC. Function calls must marshal arguments into the ABI-specified registers in the correct order. The case statement generates a sequence of comparisons and conditional jumps.\nSupported x86_64 Instructions Base x86_64: mov, lea, push, pop, add, sub, imul, idiv, div, neg, and, or, xor, shr, shl, sar, cmp, test, jmp, je, jne, jl, jle, jg, jge, jb, jbe, ja, jae, jo, jno, sete, setne, setl, setle, setg, setge, call, ret, nop, cqo, ud2, and more\nSSE2 (floating-point): movsd, movss, addsd, addss, subsd, subss, mulsd, mulss, divsd, divss, ucomisd, ucomiss, cvtsi2sd, cvtsi2ss, cvttsd2si, cvttss2si, xorpd, xorps, and more\nRegister Allocation The emitter uses all 16 general-purpose registers and all 16 SSE registers, following the System V AMD64 calling convention:\nInteger arguments: rdi, rsi, rdx, rcx, r8, r9 Float arguments: xmm0–xmm7 Return values: rax/rdx (integers) or xmm0/xmm1 (floats) Caller-saved: rax, rcx, rdx, rsi, rdi, r8–r11 Callee-saved: rbx, r12–r15, rbp Checked Arithmetic When --optimize checked is selected, the emitter inserts overflow detection after every signed arithmetic operation. For addition, this means a jo (jump-on-overflow) instruction branching to a runtime failure handler. The handler prints a diagnostic with source file, line number, and operation description — then terminates.\nThis is compiler-generated code, not a library flag. Every arithmetic site in the program gets the check woven in at the instruction level.\nAssembly Syntax The emitter supports both Intel and AT\u0026amp;T syntax from the same internal representation:\n; Intel syntax (--assembly intel) mov rax, [rbp-8] add rax, rcx ; AT\u0026amp;T syntax (--assembly att) movq -8(%rbp), %rax addq %rcx, %rax ◈ Phase 8 — The Peephole Optimizer Package: emitter/optimizer/ · 20 files\nAfter the emitter produces assembly, the optimizer runs 17 peephole passes that clean up inefficiencies without changing program semantics. These are local, conservative transformations — each one provably safe and independently tested.\nFor a source-level walkthrough of this stage, read Peephole Optimization in the Mica Compiler. This chapter keeps the pipeline view; the dedicated optimizer article covers the pass groups, rewrite patterns, and safety rules in more detail.\nPass What it eliminates Adjacent store/load store → load pairs on the same location Redundant load Load where the value is already in a register Load/store forwarding Load replaced by a previously stored value Dead store Store overwritten before being read Copy propagation Unnecessary register-to-register moves Literal propagation Register references replaced by immediate constants Arithmetic temp folding Temporaries folded into arithmetic operands Boolean temp folding Temporaries folded into conditional set instructions Compare temp folding Temporaries folded into comparison operands Compare cleanup Redundant comparison instructions Push/pop elimination Balanced push/pop pairs Stack adjustment folding Adjacent sub rsp/add rsp combinations Call argument forwarding Intermediate moves in argument setup Call return forwarding Intermediate moves for return values SSE argument forwarding Floating-point argument passing String descriptor forwarding String parameter passing Windowed store/load Broader-window store/load pattern matching The optimizer tracks statistics — instructions before and after each pass, count of each pattern matched — so improvement is measurable and verifiable.\n◈ Phase 9 — ELF and DWARF Package: emitter/elf/ · ~6 files · Package: emitter/x86_64/ · ~13 files\nELF Binary Generation The compiler produces standard ELF binaries with correct section layout:\n.text — executable code .data — initialized data .rodata — read-only data (string literals, float constants) .bss — zero-initialized data Output artifacts:\nExecutables — standalone programs Static libraries (.a archives) — for linking into other programs Shared objects (.so) — dynamically loadable libraries DWARF v5 Debug Information Most hobby compilers stop at binary output and omit debug information entirely. Mica generates full DWARF v5 debug information — the current standard — across four dedicated ELF sections:\n.debug_info — type descriptions, variable locations, function boundaries .debug_abbrev — abbreviation tables for compact encoding .debug_str — name string table (deduplicated identifier strings) .debug_line — source line mapping (statement→address table) A Language in the Registry Each compilation unit\u0026rsquo;s DIE carries a custom language identifier, DW_LANG_Mica, registered in the DWARF user-defined range. GDB recognises the source language as Mica — not C, not Pascal, not an unknown value — because the compiler emits its own identity in every binary it produces.\nType System Fidelity The DWARF generator traverses the full Mica type graph recursively, deduplicating entries by name and emitting a dedicated DIE for every type kind the language supports:\nMica type DWARF tag Integer, Float, Boolean, Char DW_TAG_base_type with encoding (signed, float, boolean, UTF) Pointer DW_TAG_pointer_type → value type DIE Record DW_TAG_structure_type with DW_TAG_member children Array DW_TAG_array_type with DW_TAG_subrange_type children Set DW_TAG_set_type with element type reference Enum DW_TAG_enumeration_type with DW_TAG_enumerator children Subrange DW_TAG_subrange_type with base type and closed bounds File DW_TAG_base_type (opaque handle, no encoding) Mica arrays carry their declared lower and upper bounds directly in the DW_TAG_subrange_type children via DW_AT_lower_bound and DW_AT_upper_bound, encoded in SLEB128. An array declared array[1900..2100] appears in GDB with exactly those bounds — not zero-based. The debugger sees the same domain the programmer declared.\nEnum DIEs include every named literal as a DW_TAG_enumerator child with its SLEB128 ordinal value, so GDB prints Red instead of 0 when you inspect an enum variable.\nVariable Location Expressions Every variable, parameter, and constant DIE carries a DW_AT_location expression that describes where the value lives at runtime. The expression uses DW_OP_fbreg with a SLEB128-encoded CFA-relative offset. The CFA (Canonical Frame Address) is defined as RSP + 16 at function entry — the standard System V AMD64 definition — so stack unwinding and variable location work together correctly.\nBecause all activation record offsets are fixed at compile time (see § Expression Stack), every location expression is a compile-time constant. There are no dynamic location expressions, no location lists, no live-range splits. The DWARF is simple, correct, and consistent with the rest of the compiler\u0026rsquo;s design.\nSource Coordinates Every DIE for a type declaration, record field, variable, parameter, or function carries DW_AT_decl_file, DW_AT_decl_line, and DW_AT_decl_column. These are derived from the token stream index preserved through every compilation phase. A breakpoint set in GDB on a source line lands on the correct instruction because the line table was built from the same source positions the scanner assigned at Phase 1.\nSubprogram Descriptors Functions are emitted as one of three DW_TAG_subprogram variants: procedure (no return type), function (with DW_AT_type), or entry point (the main equivalent). Each carries DW_AT_frame_base = DW_OP_call_frame_cfa so GDB can unwind the call stack correctly. The function-name return variable — the mechanism Mica uses for function results — is emitted as an artificial variable (DW_AT_artificial = 1), clearly distinguished from user-declared locals.\nIn Practice Load a Mica binary in GDB. Set a breakpoint by source line. Step through statements. Inspect variables by their Mica names — enum values print as names, array indices display with their declared bounds, record fields are accessible by name. Step into nested functions and watch the static-link chain resolve. Everything works correctly because the DWARF information describes what the compiler actually generated — no approximations, no placeholder encodings.\n◈ The Compiler Driver Package: compiler/ · ~11 files\nThe driver orchestrates the entire pipeline: parses CLI options, manages compilation phases, handles multi-file builds, and invokes the GNU toolchain.\nCLI Interface scripts/bin/mica \\ --compile --link \\ --source program.mica \\ --build build/output \\ --optimize debug \\ --assembly intel \\ --stdlib scripts/bin/mica-stdlib.a Flag Purpose --compile / -c Run compilation phases --link / -l Link into final binary --source / -s Input source files (comma-separated) --build / -b Build output directory --optimize / -o Policy: debug, release, checked --assembly / -asm Syntax: intel or att --stdlib / -sl Standard library archive --platform / -pf Target platform components --external / -ext Link profile: static or shared --export / -exp Export intermediate representations --no-pie / -np Disable position-independent executable Phased Concurrency The compiler driver uses a phased parallel execution model. Within each phase, all compilation units run concurrently. Between phases, the driver inserts a barrier — ensuring, for example, that all files complete parsing before semantic analysis begins, because cross-file import resolution requires all declarations to be registered first.\nThe phases and their execution mode in 4.5:\nPhase Execution Notes parse Parallel Each source file is parsed independently analyze — StaticShallow Parallel Each unit analyzed independently in this pass analyze — StaticImportAttach / Deep / Warn Sequential Require shared global registry state publish Sequential Mutates shared global registry generate Sequential Requires stable shared registry controlFlow Parallel CFG built per unit independently emit Parallel Assembly generated per unit independently persistAssemblyCode Parallel Write .s files concurrently export Parallel Export IL/AST/binary artifacts concurrently Persist and export complete the end-of-pipeline parallel picture. Writing assembly files to disk and exporting intermediate representations are independent per-compilation-unit operations with no reason to run sequentially.\nLock-free by design. The parallel() helper at the core of this system spawns one goroutine per compilation unit and waits for all of them with a single sync.WaitGroup. It needs no mutex, no channel, no lock for data access, because each goroutine writes exclusively to its own pre-allocated index slot in a result slice. Reading from shared immutable data (the global registry, type registry, interop contracts) is safe without locks because those structures are read-only during parallel execution. Worker panics are captured, re-thrown in deterministic input order on the caller goroutine after all workers complete.\nThe result is a pipeline that scales linearly with the number of source files in the parallel phases, and has no synchronization overhead beyond the WaitGroup itself.\nMulti-File Compilation scripts/bin/mica --compile --link \\ --source main.mica,utilities.mica \\ --build build/app \\ --stdlib scripts/bin/mica-stdlib.a Each file is a separate compilation unit with its own namespace. Files communicate through imp declarations and contract-based resolution.\n◈ C Interoperability and Contracts Package: interop/ · ~7 files\nMica calls C libraries and can be called from C. This interoperability is built on a disciplined JSON contract system, not ad-hoc FFI.\nJSON-Based Library Contracts Every external library is described by a JSON contract that specifies its types, functions, calling conventions, and ABI classification. The compiler ships with embedded contracts for:\nContract Contents std Mica standard I/O: WriteLn, ReadLn, Write, Empty process Program arguments: ProgramName, ArgCount, Arg limits Numeric bounds: MaxInt8, MinInt32, MaxFloat64, etc. cstd C standard library functions math Mathematical functions: Sin, Cos, Sqrt, Pow, etc. The limits Contract Instead of injecting numeric bounds as hardcoded constants from Go code, Mica 4.5 exposes them through the limits embedded contract:\nimp * : limits; var x : int64; begin x := MaxInt64; WriteLn(\u0026#34;%lld\u0026#34;, x); end. This makes the constant surface consistent and data-driven from the same JSON contract model used for all other library imports.\nType Fingerprinting When two compilation units share a type definition, Mica computes a deterministic fingerprint (digest) for the type. Fingerprint mismatches — caused by field changes, type layout differences, or packing differences — are caught at compile time with a clear error, not at runtime with a crash.\nFormat String Analysis When you call WriteLn with format specifiers like %d or %lld, the compiler validates the format string against the actual argument types at compile time. A mismatch is a compiler error, not a runtime surprise.\nReal-World Interop Examples MicaCallsC — Mica calling C printf, sin, cos, pow CCallsMica — C code calling Mica-compiled functions MicaCallsMica — Multi-file Mica projects with cross-unit imports MicaCallsLinux — Direct Linux system calls via contracts ◈ The Standard Library Mica\u0026rsquo;s standard library is a C23 implementation in interop/standard/mica-stdlib.c. It provides:\nI/O functions — WriteLn, ReadLn, Write: delegate to the appropriate UTF-32 or UTF-8 C library calls transparently based on the target encoding.\nProcess functions — ProgramName, ArgCount, Arg: access program arguments without exposing C-style argc/argv in the language entry point.\nString runtime — UTF-32 string handling and descriptor-based string management (pointer + length + capacity).\nRuntime support — Static link creation and traversal for nested functions, runtime failure reporting with source context for checked arithmetic.\nThe library compiles to mica-stdlib.a and is linked into every Mica binary.\nAutomatic UTF-8 / UTF-32 Argument Passing One of the subtler things Mica does for you — and one that developer-facing languages frequently get wrong — is handle the string encoding boundary between the language and the platform completely automatically.\nThe platform is a mix. The Linux kernel and most C APIs use UTF-8 narrow strings. But Mica itself works in UTF-32 as its primary string encoding. These two worlds have to talk to each other at function boundaries, and doing it wrong means either silent data corruption or a layer of explicit conversion code in every program.\nMica\u0026rsquo;s contract system solves this at the compiler level.\nWhen the type registry initializes, it is told the target platform\u0026rsquo;s string encoding (UTF-32 for the default Linux target). The contract resolver uses this encoding flag to select the correct external symbol for every library function that handles strings:\nLibrary function UTF-32 → resolves to UTF-8 → resolves to WriteLn wprintf printf ReadLn wscanf scanf Write fwprintf fprintf This selection happens inside the compiler during contract resolution. Your Mica source always says WriteLn. The compiled binary calls the right external symbol for the platform\u0026rsquo;s encoding. You never write wprintf or printf yourself.\n{ This Mica code is identical for UTF-32 and UTF-8 targets. The compiler selects the right symbol automatically. } program HelloEncoding; imp WriteLn : std; begin WriteLn(\u0026#34;Grüße aus Mica — 日本語 — Ελληνικά\u0026#34;); end. The process library follows the same pattern. ProcessArguments and ProcessArgumentsUtf8 are separate tests precisely to verify that both encoding paths work correctly for Unicode argument values. Your application code is the same in both cases; only the target encoding contract changes.\nThis design means that porting Mica to a UTF-8-first target — or supporting a narrow-string execution mode for embedded work — requires no changes to Mica source code. The encoding boundary is in the contracts, not in the programs.\nThe PascalCase API The public Mica callable surface follows a consistent naming rule:\nConvention Applies to lowercase Keywords, library namespace names (std, math, process) PascalCase All callable library API symbols (WriteLn, ArgCount, Sin) This rule makes the source surface self-consistent and readable. Old lowercase spellings are not present in the shipped Mica source artifacts.\nString Encoding Mica uses UTF-32 as its default string encoding. String literals are stored as zero-terminated UTF-32 sequences in read-only data. The contract system resolves the correct encoding-specific external names transparently — wprintf for UTF-32, printf for UTF-8 — so you never see this detail in Mica source code.\n◈ The Test Harness Package: tests/ · 538 test cases · 27 Go implementation files\nThe test harness is one of the most impressive parts of the project. It is a first-class development tool that has driven every feature from day one. No feature lands without harness coverage.\nTest Categories Category Count What it validates execution 266 Full pipeline: compile → link → run → check stdout and exit code errors 200 Compiler error messages and diagnostics il 49 Spectra intermediate language output asm 23 Generated x86_64 assembly instructions Total 538 Manifest-Driven Testing Every test is defined by a test.json manifest:\n{ \u0026#34;name\u0026#34;: \u0026#34;ForIntegralLoops\u0026#34;, \u0026#34;category\u0026#34;: \u0026#34;execution\u0026#34;, \u0026#34;sources\u0026#34;: [\u0026#34;ForIntegralLoops.mica\u0026#34;], \u0026#34;expect\u0026#34;: { \u0026#34;stdout\u0026#34;: \u0026#34;expected/stdout.txt\u0026#34;, \u0026#34;exit_code\u0026#34;: 0 } } Adding a test is: write the Mica source, write the expected output, create the manifest. Done.\nTest Variants A single test can run under multiple compiler configurations:\n{ \u0026#34;name\u0026#34;: \u0026#34;CheckedArithmeticPolicyDebugRelease\u0026#34;, \u0026#34;category\u0026#34;: \u0026#34;execution\u0026#34;, \u0026#34;compiler\u0026#34;: { \u0026#34;optimize\u0026#34;: [\u0026#34;debug\u0026#34;] }, \u0026#34;expect\u0026#34;: { \u0026#34;stdout\u0026#34;: \u0026#34;expected/stdout.release.txt\u0026#34;, \u0026#34;exit_code\u0026#34;: 0 }, \u0026#34;variants\u0026#34;: [ { \u0026#34;name\u0026#34;: \u0026#34;checked\u0026#34;, \u0026#34;compiler\u0026#34;: { \u0026#34;optimize\u0026#34;: [\u0026#34;checked\u0026#34;] }, \u0026#34;expect\u0026#34;: { \u0026#34;stdout\u0026#34;: \u0026#34;expected/stdout.checked.txt\u0026#34;, \u0026#34;exit_code\u0026#34;: 1 } }, { \u0026#34;name\u0026#34;: \u0026#34;release\u0026#34;, \u0026#34;compiler\u0026#34;: { \u0026#34;optimize\u0026#34;: [\u0026#34;release\u0026#34;] }, \u0026#34;expect\u0026#34;: { \u0026#34;stdout\u0026#34;: \u0026#34;expected/stdout.release.txt\u0026#34;, \u0026#34;exit_code\u0026#34;: 0 } } ] } Same source, different flags, independently verified. This is how the harness proves that checked arithmetic detects overflow in checked mode while silently wrapping in debug and release modes.\nCHECK Directive Matching For IL and assembly tests where output contains variable content (register numbers, memory offsets), the harness uses CHECK directives — regex-based pattern matching:\nCHECK: (?m)^\\s+mov\\s+dword ptr \\[rbp-\\d+\\], 1\\b CHECK: (?m)^\\s+add\\s+r10, r11\\b CHECK-NOT: (?m)^\\s+call\\s+rt\\.runtime_failure\\b CHECK: lines must match. CHECK-NOT: lines must not match. Similar to LLVM\u0026rsquo;s FileCheck, adapted for Mica\u0026rsquo;s needs.\nStress Testing Stress tests (\u0026quot;tags\u0026quot;: [\u0026quot;stress\u0026quot;]) are excluded by default, enabled with -stress:\nTest What it tests StressLOC1k Compile a 1,000-line generated program StressLOC10k 10,000 lines StressLOC100k 100,000 lines — takes 6.687 s StructABI1MBStress 1 MB aggregate passing through the ABI Test Runner CLI # All tests go run ./tests/cmd/mica-test run # With stress tests go run ./tests/cmd/mica-test run -stress # Filter by name go run ./tests/cmd/mica-test run -filter For # Filter by category go run ./tests/cmd/mica-test run -category il # Update expected output files go run ./tests/cmd/mica-test update # List tests without running go run ./tests/cmd/mica-test list # CPU profiling go run ./tests/cmd/mica-test run -cpuprofile profile.out What the Tests Cover Control flow: ForIntegralLoops, ForSubrangeLoop, ForEnumLoop, ForBoundsEvaluatedOnce, ForTerminalBoundSafety, ForLeave, RepeatSimple, RepeatExecutesOnce, RepeatLeave, CaseIntegerElse, CaseSubrangeSelector, CaseEnumMatch, CaseImplicitOrdinalPromotion\nProcess library: ProcessArguments, ProcessArgumentsUtf8\nFor-loop error enforcement: ForBodyAssignmentRejected, ForBodyAddressTakeRejected, ForControlVariableParameterRejected, ForNestedReuseRejected, ForControlVariableBooleanRejected, ForControlVariableConstantRejected, ForMissingToOrDownto, ForMissingDo, and more\nCase error enforcement: CaseSelectorNonOrdinal, CaseDuplicateLabel, CaseLabelMustBeConstant, CaseLabelIncompatibleWithSelector, CaseSemicolonBeforeElseCompound, CaseLabelRangeUnsupported, and more\nArithmetic and types: ArithmeticAdd/Subtract/Multiply/Divide across all 10 numeric types, Booleans, Characters, Strings, StringFormatFloat, StringFormatInt\nFunctions: FunctionRecursive, FunctionNested, FunctionMultipleReturnPaths, AllTypesFunction\nAggregates: StructFieldReadWrite, StructNestedField, StructPassReturnByValue, ArrayPassReturnByValueMatrix, ArrayMultidimensional, PackedRecordFieldReadWrite, PackedArrayIndexing, SetPassReturnMembership, SetConstructorRange, PascalFoundationComplexCombinations\nMemory: PointerArithmetic, PointerAssignment, PointerDereferenceChain\nSafety: CheckedArithmeticPolicyDebugRelease, CheckedCastFloatToIntPolicies\nMulti-file: CrossCuImportFunction, CrossCuImportDataType, CrossCuImportDataTypeFingerprintMismatch\nError diagnostics: MissingEnd, DuplicateIdentifier, ParamCountMismatch, UninitializedPointer, ConstDivByZero, ConstNaN, ConstInf, InteropContractLayoutMismatch, and ~170 others\n◈ Package Architecture Here is the complete package layout with primary responsibilities:\nmica-compiler/ │ ├── main.go Entry point and CLI │ ├── scanner/ (~10 files) Lexical analysis │ ├── scanner_impl.go Core scanning logic │ ├── identifier_impl.go Identifier tokenization │ ├── literal_impl.go String/char literals │ ├── number_impl.go Numeric literals │ └── position_impl.go Source position tracking │ ├── token/ (~5 files) Token type definitions │ ├── parser/ (~32 files) Recursive descent parser │ ├── ast/ (67 files) Abstract syntax tree │ ├── ast.go Node interface and kinds │ ├── block_impl.go Block/scope structure │ ├── declaration.go Declaration nodes │ ├── expression.go Expression nodes │ ├── statement.go Statement nodes (inc. For, Repeat, Case) │ ├── global_registry.go Cross-unit coordination │ └── visitor.go Traversal infrastructure │ ├── typesystem/ (37 files) Type system and ABI │ ├── primitive.go Built-in primitive types │ ├── structure.go Record types │ ├── array.go Array types │ ├── set.go Set types │ ├── subrange.go Subrange types │ ├── enum.go Enumeration types │ ├── pointer.go Pointer types │ └── type_registry_impl.go ABI classification │ ├── symbols/ (~3 files) Symbol table │ ├── analyzer/ (22 files) Semantic analysis │ ├── static_analysis_*_impl.go 8 validation passes │ ├── constant_folding_impl.go Compile-time evaluation │ ├── lowering_impl.go Expression normalization │ ├── type_coercion_impl.go Implicit conversions │ └── quality_gate_impl.go Internal consistency verification │ ├── evaluation/ (20 files) Compile-time expression evaluator │ ├── intermediate/ (~14 files) Spectra IL │ ├── intermediate.go TAC instruction definitions │ ├── spectra_impl.go Human-readable text format │ ├── symbol_table.go IL symbol table │ └── activation_record_layout_impl.go Stack frame calculation │ ├── generator/ (16 files) AST → Spectra IL │ ├── cfg/ (~3 files) Control flow graph │ ├── emitter/ (~19 files) Spectra IL → x86_64 assembly │ ├── arithmetic_impl.go Arithmetic instruction selection │ ├── comparison_impl.go Comparison and branch instructions │ ├── conversion_impl.go Runtime type conversions │ ├── aggregate_impl.go Struct and array emission │ ├── function_call_impl.go Call site emission and ABI marshaling │ ├── prologue_epilogue_impl.go Frame setup and teardown │ └── runtime_failure_impl.go Checked-arithmetic failure handlers │ │ ├── x86_64/ (~13 files) x86_64 instruction model │ │ ├── x86_64.go Instructions, registers, addressing │ │ └── debug_info_impl.go DWARF v5 attribute generation │ │ │ ├── elf/ (~6 files) ELF binary encoding │ │ ├── elf.go Section layout and symbol tables │ │ └── dwarf_impl.go DWARF v5 section encoding │ │ │ └── optimizer/ (~20 files) Peephole optimizer │ └── *_impl.go 17 independent optimization passes │ ├── compiler/ (~11 files) Compiler driver │ ├── driver_impl.go Pipeline orchestration │ ├── compilation_unit_impl.go Per-file compilation │ ├── binary_unit_impl.go Binary generation and linking │ └── concurrency_impl.go Parallel phase execution │ ├── interop/ (~7 files) C interoperability │ ├── resolver_impl.go Contract symbol resolution │ ├── default_library_contracts.json Embedded contracts (std, process, │ │ limits, cstd, math) │ ├── library_contracts.schema.json Contract JSON schema │ └── standard/mica-stdlib.c C23 runtime implementation │ ├── platform/ (~5 files) Target platform abstraction │ ├── platform.go OS, ISA, ABI definitions │ └── abi_impl.go System V AMD64 and AAPCS64 │ ├── errors/ (~3 files) Diagnostic system ├── debugging/ (~2 files) Debug information helpers ├── export/ (~2 files) IR export (JSON/text) ├── collection/ (~4 files) Utility data structures │ ├── tests/ Test harness │ ├── cmd/mica-test/ Test runner CLI │ ├── harness/ (35 files) Framework: discovery, execution, │ │ CHECK matching, variant dispatch │ └── cases/ │ ├── execution/ (266 tests) │ ├── errors/ (200 tests) │ ├── il/ (49 tests) │ └── asm/ (23 tests) │ ├── examples/ Working example programs │ ├── Playground/ General experimentation │ ├── Cast/ Type casting and conversions │ ├── ConstantFolding/ Compile-time constant evaluation │ ├── MathPower/ Math library interop (pow, sin, cos) │ ├── Nesting/ Nested procedures and lexical scoping │ ├── ReadLnUsage/ Console input examples │ ├── ShortCircuit/ Short-circuit boolean evaluation │ ├── UtfSources/ UTF-32 and Unicode source examples │ ├── Utilities/ Multi-file library example │ ├── MicaCallsC/ Mica calling C libraries │ ├── CCallsMica/ C calling Mica functions │ ├── MicaCallsMica/ Multi-file Mica projects │ └── MicaCallsLinux/ Direct Linux syscall contracts │ ├── scripts/ │ ├── build-compiler.sh Build script │ └── bin/ Compiled binaries │ └── .backlog/ ├── current/ Active backlog items ├── incubation/ Research and future ideas └── archive/ Completed and closed items ◈ Building the Compiler # Build the compiler and standard library scripts/build-compiler.sh # Produces: # scripts/bin/mica — compiler binary # scripts/bin/mica-stdlib.a — standard library archive Compiling a Mica Program scripts/bin/mica \\ --compile --link \\ --source examples/Playground/Playground.mica \\ --build build/playground \\ --optimize debug \\ --assembly intel \\ --stdlib scripts/bin/mica-stdlib.a Running the Full Test Suite # All tests go run ./tests/cmd/mica-test run # All tests including stress go run ./tests/cmd/mica-test run -stress # Filtered go run ./tests/cmd/mica-test run -filter Case go run ./tests/cmd/mica-test run -filter Repeat go run ./tests/cmd/mica-test run -category il ◈ Roadmap Horizon 1 — Version 4.5 (March 2026) ✓ Released The 4.5 release theme: finish the release-facing compiler story without rewriting the compiler.\nWork item Status for loops (to and downto) ✓ Done repeat ... until (post-test loop) ✓ Done Minimal ordinal case statement ✓ Done Public library API reset to PascalCase ✓ Done process library for program arguments ✓ Done Driver-side concurrent assembly persist/export ✓ Done Full and stress harness pass ✓ Done 4.5 closure evidence:\nscripts/build-compiler.sh passes go run ./tests/cmd/mica-test run passes go run ./tests/cmd/mica-test run -stress passes StressLOC100k: 6.687 s · StressLOC10k: 718 ms · StressLOC1k: 142 ms What 4.5 does not include by design: with, heap features, extended case label lists and ranges, SSA and optimizer overhaul, variant records, conformant arrays, defer, new/dispose.\nHorizon 2 — Version 4.6 (Q2–Q4 2026) — Active Text runtime and string direction: UTF-32-first string model as the canonical Mica string type; stringpart (borrowed text ranges for tokenization/substring without allocation); stringbuffer (owned growable UTF-32 text for append and formatting); cstring (explicit narrow UTF-8 boundary for C APIs); stringpool (arena storage for temporary text).\nStandard library modernization: A modern, Mica-native library surface; compiler-emitted JSON contracts for Mica libraries so published and imported surfaces use the same artifact; curated external contract files for well-known C libraries; first POSIX and Linux API access through contracts.\nLanguage ergonomics: Variable initialization expressions (var x : int32 := 42;); checked_bounds for subranges and array indices; panic and assert; explicit heap allocation with new and dispose; deterministic cleanup with defer dispose.\nOptimizer infrastructure: SSA transformation; dominators; liveness, alias, and loop analysis; register allocation; broader global optimization passes.\nExtended control flow: case label lists and label ranges (deferred from 4.5); richer for forms.\nHorizon 3 — 2027+ (AI Track) This is the strategic direction that keeps Mica distinctive:\nConcurrency: Structured lexical workers built around nested procedures; coroutines and generators; async I/O after concurrency semantics are stable; atomics and a documented memory model Mathematical types: Fixed-shape vectors and matrices as built-in types; compile-time shape and dimension checking; mixed-precision numeric types; compiler-native automatic differentiation Hardware: CPU SIMD lowering for vector/matrix operations; GPU offload and accelerator lowering after CPU vector semantics are solid Platform: Linux AArch64 as the next architecture target (AAPCS64 already in the platform layer); macOS deferred (requires separate Mach-O toolchain) Ecosystem: AI library contracts for BLAS, cuBLAS, oneDNN; interactive REPL for numerical workflows ◈ For Students, Professors, and Enthusiasts If you are interested in compiler construction, Mica is an unusually clear learning resource:\nComplete pipeline — scanner through ELF binary in one repository, one implementation language, zero external dependencies Real target — produces actual x86_64 ELF binaries, not bytecode for a VM Real debug information — DWARF v5, usable with GDB right now Clean, readable Go — the implementation language is approachable and consistently structured Rich test suite — tests that serve as both specification and proof Inspectable IL — Spectra is a human-readable intermediate language you can study and export for any program you write The package structure maps cleanly to a compiler textbook:\nPackage Textbook chapter scanner/ Lexical analysis parser/ Syntax analysis ast/ Intermediate representations typesystem/ Type systems analyzer/ Semantic analysis intermediate/ + generator/ Code generation emitter/ Target code generation emitter/optimizer/ Optimization emitter/elf/ Object file formats The difference between Mica and a textbook toy: Mica compiles real programs, produces real ELF binaries, implements the full System V AMD64 ABI, generates DWARF v5 debug information, and has many tests that prove it all works. The problems textbooks wave away — nested function activation records, aggregate passing by value across function boundaries, ABI-correct structure layout, packed type semantics — are all solved here and all tested.\n◈ Project History Date Milestone December 2023 First commit 2024 Scanner, parser, AST, type system, initial code generation 2025 Semantic analysis hardening, full aggregate types (packed records/arrays, sets, enums, subranges), interop contracts, DWARF v5 January 2026 Version 4.0.0 March 2026 Version 4.5.0 — first public release, many tests, for/repeat/case, process library, PascalCase API 2.5 years of consistent development, one language, one compiler, one goal: a clean, teachable, systems-capable compiler that tells the truth.\n◈ License The Mica compiler source code is available under the MCL-1.0 (Mica Compiler Non-Commercial License):\nFree for personal learning, private projects, academic research, and teaching Commercial use requires a separate written license agreement Contact: info@mica-dev.com Mica is being built in the open because compilers deserve to be understood — not just used. If you have read this far, you are the kind of person this project was built for.\n","permalink":"https://mica-website.gitlab.io/documentation/technical-portrait/","summary":"\u003cp\u003e\u003cstrong\u003eVersion 4.5 · Released March 2026\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003cem\u003eStructured clarity. C control. Born for AI.\u003c/em\u003e\u003c/p\u003e\n\u003chr\u003e\n\u003cblockquote\u003e\n\u003cp\u003e\u003cstrong\u003eA note on accuracy\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eMica is developed by a single engineer working with AI assistance. This portrait represents\nthe best current description of the language and compiler — but it is a living document.\nSpecific names, API spellings, library namespaces, and feature boundaries will change as\nimplementation reveals what actually works. Inaccuracies and inconsistencies can and do occur.\u003c/p\u003e","title":"The Mica Compiler — A Technical Portrait"},{"content":"The Mica backend does not try to make the emitter clever at every single point of code generation. It takes a different route: emit correct assembly with uniform rules first, then clean up the local waste in a dedicated pass.\nThat final cleanup stage is the peephole optimizer. It runs after x86-64 assembly has been emitted and before the final text is handed off to the assembler. The optimizer is deliberately conservative. It works on short instruction windows, applies only rewrites that are locally defensible, and stops as soon as control flow or aliasing uncertainty makes a transformation questionable.\nIf you want the full compiler context around this stage, start with The Mica Compiler — A Technical Portrait. This article zooms in on the optimizer itself.\nWhy Mica Uses a Peephole Pass Mica\u0026rsquo;s code generator is designed around clarity and predictable lowering. That keeps the emitter manageable, but it also creates recurring local patterns:\nvalues staged through stack temporaries even when a direct form would do loads that immediately reuse a value that is already available in a register call setup code that stores to a temp only to reload the same value into an argument register stack adjustments and save/restore pairs that become unnecessary after earlier rewrites Trying to bake every one of those cases directly into the emitter would make the backend harder to reason about. The peephole pass keeps the division of labor clean:\nthe emitter focuses on correctness and uniform lowering the optimizer removes the obvious local waste that falls out of that strategy later global optimization work can be built on top without entangling the emitter in special cases This is why the pass is intentionally local. It is not trying to perform full SSA-based optimization, loop analysis, or interprocedural reasoning. It is there to make already-correct machine code smaller, cleaner, and less noisy.\nHow The Current Optimizer Is Structured In Mica 4.5, the optimizer applies 17 passes and repeats them until an entire iteration produces no further changes. That fixed-point style matters because one local rewrite often creates another:\nforwarding can create redundant mov instructions propagation can make earlier temp stores dead stack or compare cleanup can expose new adjacent patterns The passes are arranged in three groups.\nGroup 1: Temp Materialization And Operand Folding This first group attacks the \u0026ldquo;store to temp, load from temp, use value\u0026rdquo; patterns that appear naturally in a uniform emitter.\nPass Purpose Literal propagation Collapse immediate-through-temp chains Memory copy propagation Redirect later loads back to the original source String descriptor forwarding Bypass temporary reloads for 16-byte string descriptors Arithmetic temp folding Feed arithmetic directly from memory, immediates, or constant-pool entries Boolean temp folding Fold byte-sized boolean temporaries into their consumers Group 2: Redundancy Cleanup And Call-Adjacent Rewrites This is the largest group. It removes round-trips that are semantically harmless but mechanically expensive.\nPass Purpose Redundant register move elimination Remove mov Rx, Rx style no-ops Call argument forwarding Skip temp staging when a value only feeds an ABI argument register Call return forwarding Reuse return registers instead of storing to a temp and reloading Adjacent store-load forwarding Forward a value across a strictly adjacent store/load pair Windowed store-load forwarding Do the same across a short bounded gap Redundant load elimination Reuse an earlier register value instead of reloading memory Load-store forwarding Remove pointless write-backs of values that were just loaded Dead store elimination Remove stores that are overwritten before any read Group 3: Compare And Stack Cleanup The last group handles the small structural artifacts that remain after the value-flow rewrites have simplified the stream.\nPass Purpose Compare temp folding Fold temp loads directly into cmp or test consumers Compare cleanup Remove back-to-back redundant flag-setting instructions Stack adjust folding Combine adjacent add/sub rsp updates Push/pop elimination Remove adjacent push/pop pairs with no net effect Representative Rewrites The easiest way to understand the optimizer is to look at the kind of assembly it shortens.\nLiteral Propagation Uniform lowering often stages a literal through a temporary location before writing it to the real destination:\n; Before mov [temp], 42 mov rax, [temp] mov [dest], rax ; After mov [dest], 42 The point is not that the emitter is \u0026ldquo;wrong\u0026rdquo;. The point is that the peephole pass can remove the detour once the detour is visible in concrete assembly.\nStore-Load Forwarding If a value is stored and immediately reloaded from the exact same address, the second instruction does not need memory at all:\n; Before mov [rbp-8], rax mov rbx, [rbp-8] ; After mov [rbp-8], rax mov rbx, rax Mica has both an adjacent version of this rewrite and a bounded-window version that can look past a few non-interfering instructions.\nArithmetic Temp Folding x86-64 can often encode a memory operand directly inside an arithmetic instruction, so a temporary register load becomes unnecessary:\n; Before mov rax, [tempA] mov rcx, [tempB] add rax, rcx mov [tempA], rax ; After mov rax, [tempA] add rax, [tempB] mov [tempA], rax The same idea also applies to boolean operations and compare/test sequences.\nCall Return Forwarding Call results frequently arrive in the right place already. Storing them to a stack temporary just to read them back is needless traffic:\n; Before call foo mov [temp], rax mov rcx, [temp] ; After call foo mov rcx, rax This pass is ABI-aware. It knows which registers carry integer and floating return values and which registers a call may clobber.\nDead Store Elimination Some stores disappear simply because a later store overwrites the same location before any read can observe the first value:\n; Before mov [rbp-8], r10 mov ecx, [rbp-16] mov [rbp-8], r11 ; After mov ecx, [rbp-16] mov [rbp-8], r11 Stack Cleanup Late cleanup is also a good place to simplify frame noise:\n; Before sub rsp, 32 add rsp, 16 ; After sub rsp, 16 Or, when the two instructions cancel exactly, both can disappear.\nWhy These Rewrites Are Safe The optimizer\u0026rsquo;s main rule is simple: when proof becomes uncertain, it does not rewrite. Several constraints enforce that policy.\nExact memory matching. Two memory operands are treated as the same location only when base register, symbol, offset, and size all match. Register-family awareness. rax, eax, ax, al, and ah are not independent; a write to one view can invalidate assumptions about the others. ABI boundaries. Calls are treated according to the active ABI, including caller-saved and callee-saved register rules. Control-flow barriers. Labels, jumps, returns, and calls terminate many local searches because they break the simple linear model the peephole pass relies on. Bounded windows. Non-adjacent rewrites search only a small number of instructions, which keeps reasoning local and predictable. Flag preservation. Rewrites that would change observable flag behavior are rejected unless the optimizer can show the replacement is equivalent for the later consumer. This is why the optimizer is best described as conservative rather than aggressive. It intentionally leaves some opportunities untouched.\nWhat The Optimizer Measures The pass reports both the total instruction count before and after cleanup and per-pattern counters for the rewrites it applies. That makes the backend measurable instead of anecdotal. It is possible to tell whether a new pass is actually carrying its weight, and it is possible to detect when a change in earlier compilation stages starts producing worse assembly.\nThe statistics are also useful for development discipline. A peephole pass is easy to add; a justified peephole pass needs evidence.\nWhat This Optimizer Is Not The current peephole pass is not Mica\u0026rsquo;s end-state optimizer. It does not attempt:\nwhole-function SSA optimization global value numbering loop transforms interprocedural analysis register allocation strategy changes Those are later stages on Mica\u0026rsquo;s roadmap. The peephole optimizer is the local cleanup layer that already ships today, and it provides a solid, testable base for the more ambitious optimizer work planned next.\nWhere It Goes Next Mica\u0026rsquo;s roadmap after 4.5 includes SSA transformation and broader global optimization work. When that arrives, the peephole pass does not disappear. It continues to matter because backend lowering still creates machine-specific local artifacts that higher-level analysis does not see.\nThat is the lasting role of a peephole optimizer in this compiler: not a substitute for global optimization, but a disciplined last pass that turns uniformly emitted assembly into cleaner final machine code.\n","permalink":"https://mica-website.gitlab.io/documentation/peephole-optimizer/","summary":"\u003cp\u003eThe Mica backend does not try to make the emitter clever at every single point\nof code generation. It takes a different route: emit correct assembly with\nuniform rules first, then clean up the local waste in a dedicated pass.\u003c/p\u003e\n\u003cp\u003eThat final cleanup stage is the peephole optimizer. It runs after x86-64\nassembly has been emitted and before the final text is handed off to the\nassembler. The optimizer is deliberately conservative. It works on short\ninstruction windows, applies only rewrites that are locally defensible, and\nstops as soon as control flow or aliasing uncertainty makes a transformation\nquestionable.\u003c/p\u003e","title":"Peephole Optimization in the Mica Compiler"},{"content":"Tagline: Structured clarity. C control. Born for AI. Canonical date: 2026-03-22 Version context: the compiler currently reports 4.5.0\nFor a comprehensive technical description of the language and compiler internals, read the Technical Portrait. For the detailed execution queue, read the Backlog.\nA note on accuracy\nMica is developed by a single engineer working with AI assistance. This roadmap and the accompanying backlog represent the best current thinking about direction, sequencing, and scope — but they are living documents, not contracts. Specific names, API spellings, library namespaces, and feature boundaries will change as implementation reveals what actually works. Inaccuracies and inconsistencies between documents can and do occur.\nWhat will not change is the direction and the vision. The platform philosophy, the commitment to explicit semantics, the structured-language foundation, and the AI trajectory are stable. Everything else is subject to revision as the compiler grows.\nMica 4.5 is the first public release. The compiler is verified by a test harness spanning 576 Mica programs, but as with any first release, unexpected limitations may still be encountered. The compiler, the VS Code extension, and the tutorials are under intensive development throughout 2026 — changes can and will occur. The primary goal for 2026 is a consistent, well-designed Mica core language with a complete standard library. Known gaps — including heap memory allocation, a string library, and further standard library coverage — will be addressed in the course of this work.\nThe Platform Vision Mica does not build a private ecosystem. It opens the one that already exists.\nThe world already has decades of proven C libraries, POSIX interfaces, Linux kernel APIs, and battle-tested system runtimes. They are not going anywhere. Every HTTP client, every database driver, every numerical toolkit, every operating system interface — already written, already tested, already running on billions of machines. Mica\u0026rsquo;s goal is not to replace any of that. It is to make all of it immediately and safely accessible from structured, readable source code.\nMost new languages ask developers to wait while an ecosystem is built from scratch. Mica takes the opposite position: the ecosystem already exists. It is the entire C ABI world — and Mica is designed to reach every part of it directly.\nThe JSON contract system is the mechanism. Every C library surface, every POSIX API, every Linux syscall that follows a stable ABI can be described in a contract file and reached from Mica source with full type checking, format-string validation, and compile-time safety. A Mica binary and a C library binary are the same kind of object. They link together directly under the System V AMD64 ABI. No adapter layer. No runtime bridge. No reimplementation required.\nThis principle shapes every architectural decision in Mica:\nThe standard library grows by surfacing what already exists, not by reimplementing it. The planned posix and linux contract packs give Mica programs access to the full Linux OS API without leaving the language. C interop is first-class, not an escape hatch. A contract file is how you reach any C library — whether it ships with Mica or was written a decade before Mica existed. Mica programs and C programs share one binary world. They call each other, link together, and cooperate under the same ABI with no performance tax at the boundary. The measure of success is not how many libraries Mica ships. It is how quickly a developer can reach any library that already exists — including libraries written years from now.\nMica augments the platform. It does not compete with it.\nWhere We Are 4.5 is closed. As of 2026-03-22 the verified baseline is:\nTarget: Linux x86_64, System V AMD64 ABI, DWARF v5, GNU binutils ELF flow Type system: integers, floats, booleans, characters, enumerations, subranges, sets, records (packed/ordinary), arrays (packed/ordinary, with lower bounds and Pascal-compatible ordinal index types), pointers, files Statements: assignment, call, begin…end, if, while, repeat…until, for…to/downto, case, leave Library surface: std, process, limits, cstd, math Ordinal coherence: supported ordinal surfaces are now coherent across storage, stepping, indexing, interop, aggregate ABI classification, and DWARF handling Interop: JSON-based C contracts with format-string analysis, cross-compilation-unit imports/exports, and validated non-string aggregate transport across the supported library topologies Evidence: scripts/build-compiler.sh passes · full harness passes · stress passes Planning surface: .backlog/current/ is intentionally empty today; active planning lives in the backlog and roadmap, with closed detailed plans archived under .backlog/archive/ in the compiler repository Recent Closures Already In The Baseline Pascal-compatible static array index types and cross-compilation-unit index-type identity are closed; see archived plan-pascal-compatible-array-index-types.md. Compiler-wide ordinal integration and coherence are closed; see archived plan-ordinal-integration-coherence.md. Non-string aggregate/library interop topology closure is closed on the supported Linux x86_64 platform; see archived plan-library-foundation-and-string-separation.md. Release Overview Release Theme Status Target 4.5 First public baseline — control flow, API naming, process library Closed March 2026 4.6 Language ergonomics · stdlib surface · contracts · SSA foundation Active Q2 2026 4.7 Language completion · heap model · SSA optimizer · concurrency substrate Planned Q3 2026 4.8 Full optimizer · concurrency model · POSIX/Linux · hardening Planned Q4 2026 5.0 Complete language · optimizing compiler · x86_64 production Planned Q2 2027 5.5 ARM64 backend · multi-platform Planned Q4 2027 6.0 AI-native language and compiler Planned 2028 4.5 — First Public Baseline (Closed) Release theme: finish the release-facing compiler story without rewriting the compiler.\nDone:\nfor statement (ordinal, to/downto, ISO-like syntax, end-to-end through harness) repeat…until — classic post-test loop ordinal case — selector, constant labels, optional else public library API naming reset — library namespaces lowercase, callable API PascalCase process library — ProgramName(), ArgCount(), Arg(index), parameterless program concurrent assembly persist and export in the compiler driver backlog simplification — active planning surface reduced to roadmap + backlog Design rules baked in:\nNo semicolon before any else — applies equally to if…else and case…else begin…end is the escape hatch for multiple statements before else program is always parameterless; process arguments come through the process library Keywords lowercase · library namespaces lowercase · callable API PascalCase Closure evidence: StressLOC100k: 6.687 s · StressLOC10k: 718 ms · StressLOC1k: 142 ms\n4.6 — Language Ergonomics \u0026amp; Library (Active, Q2 2026) Theme: grow Mica to the point where a developer can write medium-sized programs and libraries without running into systematic gaps.\nLanguage ergonomics variable initialization expressions (declaration + value in one step) extended case: label lists and label ranges beyond the minimal 4.5 form richer for forms: step expressions and other deferred surface questions panic and assert — one simple non-returning failure mechanism; no exception system checked_bounds — explicit runtime bounds safety for subranges and array/string indices Standard library surface A structured-language standard library for medium-sized programs needs more than WriteLn. The following names are the target for 4.6. Library namespace: str, std, math. Callable API follows the same PascalCase rule.\nStrings (str):\nFunction Description Length(s) character count Copy(s, from, count) substring extraction Pos(needle, haystack) find substring; 0 if not found Insert(src, var dst, pos) insert at position Delete(var s, from, count) remove characters in range Str(value, var s) numeric value to string Val(s, var result, var errorPos) parse numeric value from string Ordinals and characters:\nFunction Description Ord(x) ordinal domain value to integer Chr(n) integer to character Succ(x), Pred(x) next and previous in ordinal domain Inc(var x), Dec(var x) in-place increment/decrement High(T), Low(T) bounds of ordinal type or array index type Numeric (std/math):\nFunction Description Abs(x) absolute value — integer or float Sqr(x) square — integer or float Round(x) float → nearest int64 Trunc(x) float → truncated int64 Int(x) float → integer part as float64 Frac(x) float → fractional part as float64 Odd(x) true if x is odd Max(a, b), Min(a, b) maximum and minimum Program control (std):\nFunction Description Halt terminate with exit code 0 Halt(exitCode) terminate with explicit exit code File I/O (std):\nFunction Description Open(var f, path) associate file variable with a path Reset(var f) open for reading Rewrite(var f) open for writing (truncate) Append(var f) open for appending Close(var f) close file Eof(f) true at end of file EoLn(f) true at end of line POSIX and Linux:\nposix contract pack: file I/O, process, signals — no threading in the first wave linux contract pack: syscall-level access via curated contracts and examples String runtime stringpart — borrowed derived-text range for substring/tokenization without allocation stringbuffer — owned growable UTF-32 text for append, format, replace cstring — explicit narrow C boundary for char* API reachability stringpool — arena-style temporary text (depends on heap/lifetime track; research) Direction: stay UTF-32 first, keep string zero-terminated and interop-ready, use classic structured naming rather than copying slice-heavy or UTF-8-first designs.\nInterop and contracts compiler-emitted JSON contracts for Mica libraries (same format as consumed for imports) header-assisted bootstrap from well-formed C headers to starter contracts ABI-scoped contract interfaces with dot-call surface for namespace-like grouping curated contract packs for commonly used C libraries library-first deployment: OS/toolchain locates binaries, contracts provide typed metadata SSA foundation SSA transformation for Mica IL dominator tree, frontiers, and phi-node placement Classic language completion (deferred from 4.5) variant records conformant arrays with statement (aliasing and selector semantics must be clear first) typed outcome/result return values (after variant records; likely 4.7+) 4.7 — Language Completion \u0026amp; Heap (Planned, Q3 2026) Theme: close the classic language surface and introduce the heap model.\nHeap and lifetime new(var p) and dispose(var p) — explicit heap allocation and deallocation owned dynamic arrays (heap-backed, not slices/views) defer dispose — deterministic cleanup at scope exit defer until — nested-procedure-aware cleanup ownership diagnostics and escape analysis SSA optimizer (completion) liveness, alias, and loop analysis register allocation and spill reduction range analysis and bounds-check elimination Concurrency substrate atomics and a documented concurrency memory model structured lexical workers built around nested procedures and functions coroutines and generators as a first suspension model Record interfaces record-bound static interfaces with explicit this receiver — data-plus-behavior abstraction without virtual dispatch or OO class machinery 4.8 — Optimizer, Concurrency \u0026amp; Hardening (Planned, Q4 2026) Theme: production-grade code quality, concurrent programming, and platform hardening.\nfull SSA optimizer: broader global passes beyond the initial 4.7 foundation structured worker concurrency model (synchronized parent-scope captures) async I/O runtime model (on top of coroutines and POSIX; not a second unrelated model) deeper POSIX and Linux API coverage where the first wave proves useful bit-core: bitset[N], int[N], uint[N] — unifies set semantics with bit programming benchmarking and profiling evidence platform/support-matrix hardening on x86_64 5.0 — Mica Complete (Planned, Q2 2027) Theme: the 4.x incremental work crystallizes into a complete, coherent product on x86_64.\n5.0 is the release where Mica can say plainly and truthfully:\nLanguage complete: all classic structured-language constructs work — heap, variant records, conformant arrays, dynamic arrays, with, typed error returns, concurrency model Optimizing compiler: SSA-based with register allocation, range analysis, loop-aware passes Production quality on x86_64: fully hardened, benchmarked, and profiled Mature tooling: LSP and editor integration, contract schema versioning, profiling infrastructure The ARM64 backend follows in 5.5. macOS is deferred until after Linux AArch64 is solid.\n5.5 — ARM64 \u0026amp; Multi-Platform (Planned, Q4 2027) Theme: bring the complete 5.0 language and optimizer to a second production architecture.\nLinux AArch64 emitter — AAPCS64, ELF, GNU binutils the platform layer already models AAPCS64; the infrastructure investment is already made both x86_64 and ARM64 production-tested with DWARF v5 debug information macOS support evaluated here — requires a separate Mach-O and Apple-toolchain story 5.5 is a focused release: the language does not change. The optimizer does not change. A second architecture lands on the same solid foundation that 5.0 proves.\n6.0 — AI-Native Mica (Planned, 2028) Theme: the \u0026ldquo;Born for AI\u0026rdquo; tagline becomes a language reality.\nLanguage: native vector and matrix built-in types, compile-time dimension and shape checking, mathematical notation with ASCII equivalents Compiler: CPU SIMD lowering, tensor-aware optimization passes, mixed-precision numeric types, compiler-native automatic differentiation Platform: GPU offload and accelerator lowering — only after CPU vector semantics are solid Ecosystem: AI library contracts (BLAS, cuBLAS, oneDNN), contract bundles, interactive REPL for numerical workflows 6.0 follows directly on the complete multi-platform foundation that 5.0 establishes. The AI language features become practical precisely because 5.0 proves the language is complete, the optimizer is production-grade, and the platform story is solid on both architectures.\nStrategic Direction Lens What Mica takes from it Why it matters Structured clarity readable block structure, nested procedures, records, arrays, sets, ordinal types, structured control flow keeps the language teachable, analyzable, and suitable for compiler construction audiences C control explicit pointers, explicit address/dereference, direct ABI compatibility, contract-based interop keeps systems behavior predictable and FFI cost visible instead of hidden AI trajectory compiler-driven optimization, mathematical notation, future tensor-native semantics gives Mica a direction stronger than \u0026ldquo;a classic structured language with extras\u0026rdquo; Mica\u0026rsquo;s near-term value is not that it already is an AI language. Its value is that it is building an AI-ready compiler on a disciplined structured-language/C foundation.\nMica is not pursuing classes, inheritance, or a conventional OO framework model. Abstraction comes from records, procedures, nested functions, and contract-defined interfaces.\nRelease positioning Mica is a structured systems language with explicit C-grade control and a roadmap toward AI-native compiler semantics.\nThat statement is accurate for three audiences:\nCompiler construction and university: clean front-end/back-end story with ABI and DWARF discipline Systems programmers: explicit pointer semantics, no hidden FFI tax, predictable binary behavior AI and numerical computing: a compiler shaped toward tensor-native optimization rather than retrofitted Strategic non-goals Mica is not trying to become an object-oriented class/inheritance language. Mica is not trying to build a second package ecosystem on top of native libraries. ","permalink":"https://mica-website.gitlab.io/documentation/roadmap/","summary":"\u003cp\u003e\u003cstrong\u003eTagline:\u003c/strong\u003e Structured clarity. C control. Born for AI.\n\u003cstrong\u003eCanonical date:\u003c/strong\u003e 2026-03-22\n\u003cstrong\u003eVersion context:\u003c/strong\u003e the compiler currently reports \u003ccode\u003e4.5.0\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003eFor a comprehensive technical description of the language and compiler internals, read the\n\u003ca href=\"https://mica-website.gitlab.io/documentation/technical-portrait/\"\u003eTechnical Portrait\u003c/a\u003e.\nFor the detailed execution queue, read the \u003ca href=\"https://mica-website.gitlab.io/documentation/backlog/\"\u003eBacklog\u003c/a\u003e.\u003c/p\u003e\n\u003chr\u003e\n\u003cblockquote\u003e\n\u003cp\u003e\u003cstrong\u003eA note on accuracy\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eMica is developed by a single engineer working with AI assistance. This roadmap and the\naccompanying backlog represent the best current thinking about direction, sequencing, and\nscope — but they are living documents, not contracts. Specific names, API spellings,\nlibrary namespaces, and feature boundaries will change as implementation reveals what\nactually works. Inaccuracies and inconsistencies between documents can and do occur.\u003c/p\u003e","title":"Mica Roadmap"},{"content":" Actionable continuation of the Mica Roadmap. Read the roadmap for direction and release framing. Read this file for the detailed execution queue.\nCurrent version: 4.5.0 · Linux x86_64 · System V AMD64 ABI · DWARF v5 Canonical date: 2026-03-22 Build evidence: scripts/build-compiler.sh passes · go run ./tests/cmd/mica-test run passes · -stress passes Stress timings: StressLOC100k: 6.687 s · StressLOC10k: 718 ms · StressLOC1k: 142 ms Planning state: .backlog/current/ is intentionally empty today. The active planning surface is this backlog plus the roadmap; closed detailed plans live in .backlog/archive/ in the compiler repository.\nRecent closures already folded into this baseline:\nPascal-compatible static array index types and cross-compilation-unit index-type identity are closed; see archived plan-pascal-compatible-array-index-types.md. Compiler-wide ordinal storage/arithmetic/indexing/interop/debug coherence is closed; see archived plan-ordinal-integration-coherence.md. Non-string aggregate/library interop topology closure is closed on the validated Linux x86_64 platform; see archived plan-library-foundation-and-string-separation.md. For strategy, release framing, and the interoperability vision, read the Mica Roadmap. For the full language and compiler description, see the Technical Portrait.\nRelease 4.6 — Language Ergonomics \u0026amp; Library (Active, Q2 2026) Language ergonomics Item Status Window Why variable initialization expressions planned Q2–Q3 2026 reduce boilerplate; make numerical and worker-style code read naturally extended case: label lists and label ranges planned Q2–Q3 2026 finish the classic case surface; the 4.5 form only has single constant labels richer for surface: step expressions and deferred forms planned Q2–Q3 2026 revisit loop surface explicitly left out of 4.5 panic and assert planned Q2–Q3 2026 one simple non-returning mechanism for impossible states; no exception system checked_bounds planned Q2 2026 explicit runtime bounds safety for subranges and array/string indices panic design direction:\nfor impossible states, not expected failures no recover, no stack unwinding, no general exception system optional string-literal payload (stays in read-only data; no dynamic allocation) assert lowers to panic expected failures move toward typed outcome/result values Illustrative future syntax (not current compiler syntax):\npanic; panic \u0026#34;invalid parser state\u0026#34;; assert x \u0026gt; 0; assert x \u0026gt; 0, \u0026#34;x must be positive\u0026#34;; Standard library surface Complete the library surface a developer expects when writing medium-sized programs. Library namespaces lowercase. Callable API PascalCase. Same rule as std.\nStrings (str) — planned, Q2–Q3 2026\nFunction Description Length(s) character count Copy(s, from, count) substring extraction Pos(needle, haystack) find substring; 0 if not found Insert(src, var dst, pos) insert at position Delete(var s, from, count) remove characters in range Str(value, var s) numeric value to string Val(s, var result, var errorPos) parse numeric value from string Ordinals and characters — planned, Q2–Q3 2026\nFunction Description Ord(x) ordinal domain value to integer Chr(n) integer to character Succ(x), Pred(x) next and previous in ordinal domain Inc(var x), Dec(var x) in-place increment/decrement High(T), Low(T) bounds of ordinal type or array index type Numeric (std/math) — planned, Q2–Q3 2026\nFunction Description Abs(x) absolute value — integer or float Sqr(x) square — integer or float Round(x) float → nearest int64 Trunc(x) float → truncated int64 Int(x) float → integer part as float64 Frac(x) float → fractional part as float64 Odd(x) true if x is odd Max(a, b), Min(a, b) maximum and minimum Program control (std) — planned, Q2 2026\nFunction Description Halt terminate with exit code 0 Halt(exitCode) terminate with explicit exit code File I/O (std) — planned, Q2–Q3 2026\nFunction Description Open(var f, path) associate file variable with a path Reset(var f) open for reading Rewrite(var f) open for writing (truncate) Append(var f) open for appending Close(var f) close file Eof(f) true at end of file EoLn(f) true at end of line Standard library modernization Item Status Window Why classic-style standard library modernization planned Q2–Q3 2026 turns interop/standard/mica-stdlib.c into a stronger language-facing surface Direction: stay UTF-32 first at the language level; keep string zero-terminated and interop-ready; use classic structured naming (stringpart, stringbuffer, stringpool, cstring) rather than copying slice-heavy or UTF-8-first designs. Make concatenation and formatting destination-driven so the compiler/runtime can reserve once and fill once.\nString runtime Item Status Window Why UTF-32-first terminated string model (string) planned Q2–Q3 2026 keeps Mica classically structured; keeps wide-C interop direct borrowed text ranges (stringpart) planned Q2–Q3 2026 substring/tokenization without allocating a new terminated string mutable text construction (stringbuffer) planned Q2–Q4 2026 destination-driven append/format/replace without temporary-object storms explicit narrow C boundary (cstring) planned Q2–Q4 2026 UTF-32-first Mica with clean access to narrow char* APIs temporary text regions (stringpool) research Q3–Q4 2026 arena-style temporary text; heap/lifetime model must exist first Interop and contracts Item Status Window Why compiler-emitted JSON contracts for Mica libraries planned Q2–Q3 2026 library publish and library import use the same contract artifact header-assisted C contract bootstrap from well-formed headers planned Q3–Q4 2026 lowers the cost of reusing established C libraries ABI-scoped contract interfaces with dot-call surface planned Q3–Q4 2026 namespace-like grouping without OO class machinery curated C library contract packs planned Q2–Q3 2026 makes interop reusable across projects instead of ad-hoc per project embedded core contracts plus example packs for broader libraries planned Q2–Q3 2026 keeps the built-in surface small with solid external patterns library-first deployment model without package manager planned Q3–Q4 2026 OS/toolchain locates binaries; contracts provide the typed metadata layer POSIX and Linux API access (without threading) planned 4.6 → 4.7+ practical systems access; first wave: posix and linux contract packs SSA foundation Item Status Window Why SSA transformation for Mica IL planned Q3 2026 optimizer base for global analysis and later AI work dominator tree, frontiers, and phi-node placement planned Q3 2026 prerequisites for all SSA-based optimization Classic language completion (deferred from 4.5) Item Status Window Why variant records deferred Q2–Q3 2026 major classic aggregate feature on top of the trusted record baseline conformant arrays deferred Q2–Q3 2026 classic procedure-interface and array abstraction compatibility with statement deferred after 4.6 touches aliasing and selector semantics; not safe to rush typed outcome/result return values research after variant records / 4.7+ explicit success/failure returns without exceptions or multi-value signatures outcome direction: prefer one typed return object over multi-return slots as the primary error model. Build on Mica\u0026rsquo;s existing automatic return-variable model. Keep success and failure paths word-oriented and visible in source. Avoid punctuation-dense syntax.\nIllustrative future syntax (not current compiler syntax):\nfunction ParseInt(s : string) : outcome int64, ParseError; begin if IsValidInt(s) then success ParseInt := ToInt(s) else failure ParseInt := InvalidDigit; end; This direction only becomes credible once tagged result representation, pattern inspection, and variant-style data modeling are in place.\nTooling Item Status Window Why LSP and editor tooling research Q3–Q4 2026 improves usability, teaching workflow, and adoption contract schema and compatibility policy planned Q3–Q4 2026 stable toolchains, library publication, long-lived academic examples benchmarking and profiling evidence planned Q3–Q4 2026 keeps performance claims grounded in repeatable measurements platform/support-matrix hardening planned Q3–Q4 2026 clarifies what Mica truly supports beyond Linux x86_64 Release 4.7 — Language Completion \u0026amp; Heap (Planned, Q3 2026) Heap and lifetime Item Status Window Why heap memory (new, dispose) planned Q3 2026 explicit heap instead of pointer-only stack-oriented programming owned dynamic arrays (heap-backed, not slices/views) planned Q3 2026 variable-size aggregates without importing slice aliasing semantics defer dispose and defer until planned Q3 2026 deterministic cleanup without GC; defer until fits nested procedures well ownership diagnostics and escape analysis planned Q3 2026 connects source-level lifetime policy to stack-vs-heap storage decisions SSA optimizer (completion) Item Status Window Why liveness and alias analysis planned Q3 2026 SSA optimization prerequisites loop analysis planned Q3 2026 loop-aware code improvement passes register allocation and spill reduction planned Q3 2026 raises Mica from correct to efficient code generation range analysis and bounds-check elimination planned Q3 2026 connects checked_bounds policy to the optimizer broader global optimization passes planned Q3 2026 industry-grade code quality beyond initial SSA passes Concurrency substrate Item Status Window Why atomics and concurrency memory model research Q3 2026 prerequisites for safe worker/threading support structured lexical workers with synchronized captures research Q3 2026 concurrency model that fits nested procedures; not mainstream task APIs coroutines and generators research Q3 2026 first suspension model before a larger async I/O runtime Record interfaces Item Status Window Why record-bound static interfaces with explicit this receiver research Q3 2026 data-plus-behavior abstraction without virtual dispatch or OO class machinery; this receiver stays explicit in the signature 4.8 — Optimizer, Concurrency \u0026amp; Hardening (Q4 2026) Item Status Window Why full SSA optimizer: broader global passes planned Q4 2026 industry-grade code quality beyond the initial 4.7 SSA foundation structured worker concurrency model (synchronized captures) planned Q4 2026 workers that cooperate through nested-procedure scope, not free-floating threads async I/O runtime model planned Q4 2026 on top of coroutines and POSIX; not a second unrelated execution model deeper POSIX and Linux API coverage planned Q4 2026 second wave of platform access where the 4.7 contracts prove useful bit-core: bitset[N], int[N], uint[N] planned Q4 2026 unifies set semantics with lower-level bit and wide-integer programming benchmarking and profiling evidence planned Q4 2026 keeps performance claims grounded in repeatable measurements platform/support-matrix hardening on x86_64 planned Q4 2026 clarifies what Mica truly supports before expanding to a second architecture 5.0 — Mica Complete on x86_64 (Q2 2027) 5.0 is where the 4.x incremental work crystallizes into a complete, coherent product. All items below are prerequisites already landed in 4.6–4.8.\nItem Status Window Why complete language surface planned Q2 2027 heap, variant records, conformant arrays, dynamic arrays, with, typed error returns, concurrency — all working x86_64 fully hardened and production-tested planned Q2 2027 DWARF v5, benchmarks, profiling evidence, support matrix clear SSA optimizer with register allocation and range analysis planned Q2 2027 full optimizing compiler, not just a code generator LSP and editor integration planned Q2 2027 developer tooling mature enough for real use 5.5 — ARM64 \u0026amp; Multi-Platform (Q4 2027) 5.5 brings the complete 5.0 language and optimizer to a second production architecture. The language does not change. The optimizer does not change. A new architecture lands.\nItem Status Window Why Linux AArch64 emitter planned Q4 2027 next realistic architecture; AAPCS64 already in platform layer; ELF/Linux fits current infrastructure x86_64 + ARM64 both production-tested with DWARF v5 planned Q4 2027 Mica runs on the two dominant Linux architectures macOS target support deferred after Linux AArch64 requires a separate Mach-O and Apple-toolchain story 6.0 — AI-Native Mica (2028) 6.0 is where the \u0026ldquo;Born for AI\u0026rdquo; tagline becomes a language reality. The complete language and optimizer foundation of 5.0 make these items achievable without shortcuts.\nItem Status Window Why native vector and matrix built-in types planned 2028 first-class substrate for AI and numerical programming compile-time dimension and shape checking planned 2028 turns many AI-programming mistakes into compiler errors mathematical notation with ASCII equivalents planned 2028 formulas that read like mathematics, not like pointer arithmetic CPU SIMD lowering for vector and matrix operations planned 2028 numerical built-ins map to real hardware before GPU work begins mixed-precision and AI-oriented numeric types planned 2028 targets efficient training and inference workflows compiler-native autodiff planned 2028 gradients inside the compiler, not outsourced to a runtime framework GPU offload and accelerator lowering planned 2028 only after CPU vector semantics are solid AI library contracts (BLAS, cuBLAS, oneDNN) and REPL planned 2028 the AI direction becomes a usable programming environment Completed: 4.5 Release Record Release theme: get as close as practical to a complete classic statement baseline, then reset the public source surface before the first public release.\nWorkstream Status Result for statement (to/downto) done ordinal for with ISO-like syntax, end-to-end through harness repeat…until done classic post-test loop, parser through harness ordinal case done selector, constant labels, optional else; label lists/ranges deferred to 4.6 public library API naming reset done library namespaces lowercase, callable API PascalCase, no legacy spellings in shipped source process library done ProgramName(), ArgCount(), Arg(index) — parameterless program entry point concurrent assembly persist and export done driver-side per-CU parallelism using parallel() pattern; deterministic diagnostics backlog simplification done active planning surface reduced to roadmap + backlog with statement deferred keyword at token level only; aliasing semantics unresolved 4.5 compatibility rules (baked in) No semicolon immediately before any else — consistent for both if…else and case…else begin…end is the required escape hatch for multiple statements before else program is always parameterless; process arguments arrive through the process library Keywords lowercase · library namespaces lowercase · callable API PascalCase No legacy lowercase public spellings in shipped Mica source artifacts case v1: ordinal selector, single constant labels, optional else — label lists and ranges are a 4.6 item for v1: ordinal, to/downto, no arbitrary step expressions ","permalink":"https://mica-website.gitlab.io/documentation/backlog/","summary":"\u003cblockquote\u003e\n\u003cp\u003eActionable continuation of the \u003ca href=\"https://mica-website.gitlab.io/documentation/roadmap/\"\u003eMica Roadmap\u003c/a\u003e.\nRead the roadmap for direction and release framing. Read this file for the detailed execution queue.\u003c/p\u003e\u003c/blockquote\u003e\n\u003cp\u003e\u003cstrong\u003eCurrent version:\u003c/strong\u003e \u003ccode\u003e4.5.0\u003c/code\u003e · Linux \u003ccode\u003ex86_64\u003c/code\u003e · System V AMD64 ABI · DWARF v5\n\u003cstrong\u003eCanonical date:\u003c/strong\u003e \u003ccode\u003e2026-03-22\u003c/code\u003e\n\u003cstrong\u003eBuild evidence:\u003c/strong\u003e \u003ccode\u003escripts/build-compiler.sh\u003c/code\u003e passes · \u003ccode\u003ego run ./tests/cmd/mica-test run\u003c/code\u003e passes · \u003ccode\u003e-stress\u003c/code\u003e passes\n\u003cstrong\u003eStress timings:\u003c/strong\u003e \u003ccode\u003eStressLOC100k\u003c/code\u003e: 6.687 s · \u003ccode\u003eStressLOC10k\u003c/code\u003e: 718 ms · \u003ccode\u003eStressLOC1k\u003c/code\u003e: 142 ms\n\u003cstrong\u003ePlanning state:\u003c/strong\u003e \u003ccode\u003e.backlog/current/\u003c/code\u003e is intentionally empty today. The active planning surface is this backlog plus the roadmap; closed detailed plans live in \u003ccode\u003e.backlog/archive/\u003c/code\u003e in the compiler repository.\u003c/p\u003e","title":"Mica Backlog"},{"content":"I built a native compiler in 2.5 years.\nIt produces real Linux x86_64 ELF binaries, integrates directly with the System V AMD64 ABI, and calls C code with zero overhead — no wrappers, no runtime.\nAnd I said nothing about it.\nThis is the first time I am making it public.\nI need to tell you something I have been keeping quiet for over two years.\nIn late 2023, I created an empty directory and started building a compiler. Not a toy. Not a transpiler. A compiler that takes source code and produces real, native Linux x86_64 ELF binaries — with DWARF v5 debug information, full System V AMD64 ABI compliance, and zero-overhead C interoperability. Written in Go, from scratch, with no external dependencies.\nI am not a student. I am a software engineer with more than thirty years of experience, working a full-time job while building this on the side. I am over sixty. This is the project of my life.\nThe compiler is called Mica. It has a 9-phase compilation pipeline, its own intermediate language named Spectra, 17 peephole optimization passes, and 538 automated test cases. You can set a breakpoint in a C function, call a Mica function from it, and GDB steps across the boundary into Mica source. The compiler itself is 75,545 lines of Go.\nWhy now?\nBecause something happened this week. I read back what I have built, I read the technical portrait I wrote, and I could no longer justify staying quiet. The work is real. The documentation is honest. The roadmap is credible. There is no better moment than this one.\nAnd because I owe a public acknowledgment to the man whose work made this possible.\nNiklaus Wirth — creator of Pascal, Modula-2, Oberon — died on January 1st, 2024. Quietly. Without much notice from the world. A few weeks after I had started this project.\nMica is, in part, my answer to that.\nWhat Mica is trying to do\nMost new languages ask you to wait while an ecosystem is built from scratch. Mica takes the opposite position: the ecosystem already exists. Every C library on your system, every POSIX API, every Linux kernel interface — Mica is designed to reach all of it directly, with full compile-time type checking and no wrapper layer. A Mica binary and a C binary are the same kind of object. They link together under the same ABI with no performance cost at the boundary.\nThe goal is not to replace C or any other language. The goal is to make the platform you already have easier to use from structured, readable source code.\nWhat I am asking for\nNothing, yet. Just your attention for long enough to decide whether this matters to you.\nIf you want the full story — the breakthroughs, the December when I nearly stopped, the nine months of fighting with AI, the tribute to Wirth — read The Mica Story.\nIf you want the technical depth — the compiler pipeline, the type system, the intermediate language, the platform vision — read the Technical Portrait.\nIf you want to know where this is going — read the Roadmap.\nAnd if this is your kind of project — compiler construction, structured language design, honest engineering writing, Wirth\u0026rsquo;s tradition carried forward — I would genuinely like to know you exist.\nWhere to start\nThe tutorials repository is the quickest way to get a feel for Mica as a language: gitlab.com/mica-lang/mica-tutorials\nIt will be updated as the language grows. For now it serves as a working entry point — real programs, real output, real compiler.\nA candid note\nI am one person. I cannot respond to a large volume of messages, and I am not asking you to flood me with feedback.\nBut if you are seriously interested — as an individual, a university, or a company — what I am looking for is not criticism of what is missing. I know what is missing. What I need, and what would shape the future of this project most, is people who see the direction and want to help carry it forward. Technically, academically, or otherwise.\nIf that is you, write to me:\ninfo@mica-dev.com\nThe silence ends here.\n","permalink":"https://mica-website.gitlab.io/posts/breaking-the-silence/","summary":"\u003cp\u003eI built a native compiler in 2.5 years.\u003c/p\u003e\n\u003cp\u003eIt produces real Linux x86_64 ELF binaries, integrates directly with the System V AMD64 ABI, and calls C code with zero overhead — no wrappers, no runtime.\u003c/p\u003e\n\u003cp\u003eAnd I said nothing about it.\u003c/p\u003e\n\u003cp\u003eThis is the first time I am making it public.\u003c/p\u003e\n\u003chr\u003e\n\u003cp\u003eI need to tell you something I have been keeping quiet for over two years.\u003c/p\u003e\n\u003cp\u003eIn late 2023, I created an empty directory and started building a compiler. Not a toy. Not a transpiler. A compiler that takes source code and produces real, native Linux x86_64 ELF binaries — with DWARF v5 debug information, full System V AMD64 ABI compliance, and zero-overhead C interoperability. Written in Go, from scratch, with no external dependencies.\u003c/p\u003e","title":"I built a native compiler in 2.5 years — and said nothing."},{"content":" \u0026ldquo;I looked at the compiler\u0026rsquo;s output and thought: this cannot be mine. I couldn\u0026rsquo;t believe what had happened. I am happier than I have been in 20 years.\u0026rdquo;\nThis is a long read — 2.5 years don\u0026rsquo;t compress easily. If this is not the right moment, bookmark it and come back. I believe it is worth your time.\nPrologue: A Seed Planted Thirty Years Ago In the late 1980s and early 1990s, I was a student, and I built my first compiler. It was a modest academic project, based on materials from ETH Zürich. While it was small, something happened to me during that work — I fell in love with the intricate puzzle of transforming human-readable code into something a machine could execute.\nThen life happened. Career. Responsibilities. Decades passed.\nBy 2023, I had been working in IT for over thirty years. I was successful by most measures. But I felt empty. My profession no longer provided what I craved: innovation. I had always seen myself as a creative person, and that creative part of me was starving.\nI didn\u0026rsquo;t know it yet, but I was searching for something. And I was about to find it.\nChapter 1: The Spark It started with a small book.\nI had begun studying compiler construction again — partly out of nostalgia, partly out of a nameless hunger for something new. I worked through materials from McGill University, from a Danish university, from the Hasso Plattner Institute in Germany, and of course from ETH Zürich.\nThen I discovered a thin volume about PL/0, a minimalist teaching language created by Niklaus Wirth.\nWho Was Niklaus Wirth? Niklaus Wirth (1934–2024) was one of the giants of computer science. A Swiss professor at ETH Zürich, he created languages that shaped how generations of programmers think: Pascal (1970), Modula-2 (1978), and Oberon (1987). He won the Turing Award — the \u0026ldquo;Nobel Prize of Computing\u0026rdquo; — in 1984.\nHis philosophy was radical simplicity. He believed that understanding comes from building things that are complete but small. Not toy projects that cut corners, but real systems stripped to their essence.\nPL/0 was his teaching language for compiler construction. It had only a handful of keywords, no complex features — but it contained the complete essence of a compiler: lexical analysis, parsing, symbol tables, code generation. Everything a compiler needs, nothing more.\nWhen I opened that book in late 2023, something clicked. I didn\u0026rsquo;t just see a teaching exercise — I saw a path. A dream began to form: what if I could build a compiler that generates real machine code? Not a toy. A real compiler.\nI chose Go as my implementation language and VS Code as my editor. I created an empty directory and started typing.\nA few weeks later — on the 1st of January 2024 — Niklaus Wirth died quietly at his home in Switzerland. He was 89 years old.\nI did not know then how deeply connected those two events would become for me. The man whose work had inspired me to begin was gone, just as I had taken my first steps. There is something both sorrowful and motivating about that coincidence that I have not entirely worked out. What I know is this: I will not let his work be forgotten. More on that at the end of this story.\nChapter 2: Two Traditions As I dove deeper into compiler construction, I realized I was stepping into a story much larger than myself — a story about two competing visions of what programming should be.\nThe European tradition: In 1970, at ETH Zürich, Wirth created Pascal. Clarity above all. Strong typing. Structured programming. Code that reads almost like prose. Pascal became the teaching language of choice for decades. Millions of students — including me — learned to program with it.\nThe American tradition: Two years later, at Bell Labs, Dennis Ritchie created C. Efficiency above all. Direct hardware access. Minimal abstraction. C was designed to rewrite UNIX. It wasn\u0026rsquo;t meant to be pretty; it was meant to be powerful.\nHere is the uncomfortable truth: C won. Despite all the elegance, despite all the educational value — C became the foundation of modern computing. Linux, macOS, PostgreSQL, nginx, your car\u0026rsquo;s firmware — all C or C++. When you are building an operating system kernel, you need control over every byte.\nAs I studied compiler construction in 2023, I found myself caught between these two worlds. I loved the clarity of structured, readable code. But I respected C\u0026rsquo;s power. Could there be a bridge? A language with structured readability and C\u0026rsquo;s efficiency?\nI didn\u0026rsquo;t have an answer yet. But the question lodged itself in my mind and would not leave.\nChapter 3: Building Piece by Piece I worked on the compiler alongside my regular job, stealing hours where I could. Piece by piece, it grew.\nThe scanner came first — the component that reads raw characters and groups them into tokens. Sounds simple; it\u0026rsquo;s not. Comments, string literals with escape sequences, Unicode, error recovery — I spent weeks on the scanner alone.\nThe parser came next — building structure from the token stream, understanding that 42 + x * 3 means \u0026ldquo;multiply x by 3, then add 42.\u0026rdquo; I implemented a recursive descent parser, where each grammar rule becomes a function. Elegant when it works, maddening when it doesn\u0026rsquo;t.\nThe symbol table tracked every declaration. The Abstract Syntax Tree and Semantic Analyzer separated a serious compiler from a simple one.\nBut there was a problem. I didn\u0026rsquo;t trust myself to write a machine code generator for AMD64 from scratch. The x86-64 instruction set is enormous, baroque, filled with historical baggage from the 1970s. So I took a different approach: I built a CPU emulator. My compiler would generate code for this virtual machine, and I could test everything without touching real hardware.\nThe emulator grew more sophisticated. Its output began to look suspiciously like real Intel assembly code.\nI didn\u0026rsquo;t realize it then, but I was setting the stage for something unexpected.\nChapter 4: The Night Everything Changed I remember that night vividly. My emulator generated output that looked like this:\nmov rax, 42 push rax mov rax, [rbp-8] pop rbx add rax, rbx The assembly shown above is from those early days — a naive stack-based approach. The code Mica emits today is far more sophisticated.\nThis was almost valid Intel x86-64 assembly. My emulator executed this internally, simulating a CPU. But the syntax was so close to real assembly that I wondered: what if I just fed it to a real assembler?\nI installed GCC on my Ubuntu machine. I took the assembly output from my compiler and fed it to the GNU Assembler. Then I linked it with the GNU linker.\nI ran the resulting binary. It worked.\nI ran another example. It worked. I ran all my test programs. They all worked.\nI sat there in the middle of the night, staring at my screen, trying to process what had just happened. My compiler — my hobby project built from an empty directory — was generating real, executable Linux binaries.\nThat was Spring 2025. That was the breakthrough.\nChapter 5: A New Name, A New Identity After that night, everything accelerated. I refactored the compiler fundamentally — implementing a proper AMD64 code emitter, restructuring the entire architecture. And I realized: this wasn\u0026rsquo;t PL/0 anymore. This was something new.\nFollowing the tradition of Linus Torvalds, I derived a name from my own first name, Michael: Mica. Beyond the personal connection, mica is also a mineral — known for its layered structure, its transparency, its resilience.\nThe question that had been growing in my mind came roaring back: clarity and systems control — together?\nThe answer was the System V AMD64 ABI.\nI could have invented my own calling convention. Many academic compilers do. Instead, I decided to implement full compliance with the standard Linux calling convention. The payoff: zero-overhead C interoperability. A Mica binary and a C library binary are the same kind of object. They link together directly. No adapter layer. No runtime bridge. No reimplementation required. Every C library on the system became, in principle, a Mica library.\nI then implemented DWARF v5 debug information — the latest standard — enabling professional source-level debugging in GDB and VS Code. This is rare for any language, let alone a solo project.\nChapter 6: Into the Valley Summer 2025. Autumn 2025. The darkest period.\nFunctions and procedures existed, but they couldn\u0026rsquo;t take parameters. No arguments. Nothing passed in, nothing passed out. This might sound minor. It\u0026rsquo;s not. Parameter passing is the backbone of any useful language.\nFor Mica, it was especially hard because of nested functions. Like Wirth\u0026rsquo;s original work, Mica supports functions defined inside other functions, with access to the enclosing scope. This requires static links — pointers chaining stack frames together so inner functions can reach outer variables. The compiler must pass links implicitly alongside regular arguments, generate code following link chains at arbitrary depth, and make all of this work with recursion — while remaining ABI-compatible with C.\nThe compiler stopped working. Not partially — completely. Every compilation ended in a crash. For weeks, I couldn\u0026rsquo;t produce a single working binary. I had lost control of my own creation.\nI want to be honest: there were moments when I sat in front of my computer and felt like I was failing. Thirty years of IT experience, and I couldn\u0026rsquo;t make this work.\nThe parameter passing crisis was a turning point in more ways than one. It forced a decision I had been avoiding for months.\nChapter 7: First Encounters with AI — The Hard Way For a long time, I had resisted using AI tools for serious code work. My concerns were real: code quality. Loss of control. Software engineering is not just about producing code that compiles — it is about producing code that is correct, maintainable, and reflects the architectural decisions of someone who understands what they are building.\nBut by mid-2025, the pain was too great. I was one person with a full-time job, a personal life, a growing codebase, and a vision that was running faster than I could carry it alone. I could not stop — I am full of ideas and I have a goal now written in a roadmap. But I could not continue as before either.\nSo I began. Slowly. Cautiously. Skeptically.\nThe first months were genuinely frustrating.\nWithout consistently giving the AI deep context about Mica\u0026rsquo;s architecture, design principles, and established conventions, the generated code was wrong in ways that were hard to articulate. It compiled. Sometimes it even ran. But it felt foreign. It did not reflect how I think about code. The naming was off. The structure was off. The code solved the immediate problem but violated the spirit of the surrounding system in subtle ways that only became apparent later.\nI hated those sessions.\nI kept asking myself: is this actually helping, or am I creating a maintenance problem I\u0026rsquo;ll spend months untangling? I rejected large amounts of what was generated. I rewrote sections entirely. Some weeks, the AI collaboration felt like it cost me more time than it saved. The code that came back felt like it had been written by a capable stranger who had skimmed the documentation but didn\u0026rsquo;t understand what I was trying to build.\nWhat was missing, I eventually understood, was context. Not technical context alone — the kind of context that conveys not just what the code needs to do, but what the code needs to be. How it should feel. What principles it must not violate. Where it fits in a system that has been built by one person with very specific values over two years.\nThat took months to figure out. Not weeks. Months.\nI slowly found that AI collaboration worked reliably in specific modes:\nDocumentation and comments. Giving a complex piece of code to an AI and asking it to write documentation — not invent documentation, but describe what was actually there — proved remarkably effective. The AI often captured the intent in prose better than I could in the moment of writing the code.\nCode reviews. \u0026ldquo;Here is this function. What is wrong with it?\u0026rdquo; When the AI had enough context, it found real issues: edge cases I had missed, type consistency problems I had been living with, assumptions that could silently break.\nSpecification translation. The System V AMD64 ABI has hundreds of pages. DWARF v5 is complex enough to be a small book. Aggregate type passing rules — how structs containing mixed float and integer fields must be split across registers — run to seventeen pages of rules alone. Using an AI as an intelligent reader and translator of these documents, asking it to explain specific rules or apply them to specific cases, was enormously useful.\nAssembly code completions. Mica needs to emit correct machine code for every combination of operation and type: int8, int16, int32, int64, uint8, float32, float64. That is dozens of combinations for arithmetic alone. Asking an AI to complete tables of instruction patterns, once a few examples were established, was one of the first places where code generation felt genuinely safe — the patterns were regular, the correctness was verifiable, and the risk of hidden errors was low.\nRoot cause analysis. \u0026ldquo;Here is a stack trace. Here is the surrounding code. Here is what I expected to happen. What went wrong?\u0026rdquo; AI assistants proved often better at this than I was in moments of deep frustration.\nWhat I learned over those nine months is that AI is not a shortcut. It is a tool that requires enormous investment of context and judgment to use well. The frustrating sessions were a product of the time — AI services were still maturing, and I was still learning how to work with them. Both sides of that collaboration had room to grow. And learning that took time I did not have, and patience I had to force myself to find.\nChapter 8: December December 2025.\nI had been working toward something ambitious: transforming the single-file compiler into a full multi-file compilation platform. Cross-compilation-unit symbol resolution. A global namespace registry. Import and export across source files. Static library creation. The ability to build real programs from multiple Mica files, each compiled independently, linked together as proper ELF objects.\nThis was not a feature. It was a fundamental architectural rework of the entire compiler.\nI was also deeply frustrated. The parameter passing rework had been relentless, and the complexity had simply kept growing. The codebase had grown enormously across 2025. The volume of source code — the compiler itself, the standard library, the VS Code extension, the tutorials, the documentation that all needed to stay consistent — had grown to a size that no longer fit comfortably in one person\u0026rsquo;s head.\nI remember sitting at my desk in December 2025 with tears in my eyes. Not from sadness, exactly. From the particular frustration of being on the edge of losing control of something you have poured yourself into for two years.\nThe multi-file rework had broken things I had thought were solid. Regressions appeared in code that had passed tests for months. Error messages pointed in wrong directions. The compiler, which had felt like mine — which I could navigate in my sleep — had become a stranger again.\nI was at the corner of stopping. Not giving up on the vision. But stopping, and accepting that Mica would never become what I had hoped.\nI did not stop.\nChapter 9: 4.0.0 — Telling No One In January 2026, I made version 4.0.0 a reality.\nThe codebase had more than tripled compared to where it was a year earlier. Multi-file compilation worked. Cross-compilation-unit imports worked. Static library creation worked. The compiler could build real, multi-file Mica programs and link them cleanly. It was an extremely hard release to achieve — perhaps the hardest single milestone in the project.\nI told four people. Three of them were friends who are not technical. They nodded, smiled, said encouraging things. I don\u0026rsquo;t think any of them understood what had actually happened. But they saw that something mattered to me, and they supported that. That is not nothing. In a project this solitary, that kind of quiet emotional support is what keeps you going when there is no one else watching.\nAround this same time, my wife and I formally founded Mica Development UG. This was a decision about commitment as much as about structure. The project had grown beyond a hobby.\nThere is something I have not written before: there were people who reached out to me during this period who wanted to use Mica for real development work. Actual developers. People who had seen enough to be genuinely interested.\nI discouraged them. I took no money. I was not certain the project would survive long enough to be useful, and I would not have people depending on a compiler that might not make it. Some decisions about honesty are not complicated, even when the pressure is high. I could not take responsibility for other people\u0026rsquo;s work when I did not yet trust my own.\nThat is where version 4.0.0 lived: between private pride and honest uncertainty.\nChapter 10: The Wall Some obstacles you see coming from a distance. Then there are walls — the ones you only discover when you walk straight into them.\nA general-purpose programming language needs aggregate types. Records. Arrays. Structures within structures. Packed memory layouts. The ability to pass a ten-field record through three function calls, return it by value, classify it correctly under the ABI, annotate it with debug information, and behave consistently across every combination of nesting and packing.\nThe System V AMD64 ABI has seventeen pages of rules for aggregate passing alone. Small structs go in registers. Large ones go in memory with a hidden pointer passed as the first argument. Mixed structs with float and integer fields get split across register classes. Packed records compress the field layout, removing alignment gaps — which changes every offset calculation downstream. And then there is the recursion: structs containing arrays of structs.\nI ran the numbers in my head. The semantic analysis alone would take months. The code generation would take months more. Testing every combination would take\u0026hellip; I could not complete the estimate.\nI was one person. I had a day job. I had a life. The math did not work — alone.\nBut something was about to change.\nChapter 11: A Coincidence of Time and Pain There are moments when the timing of external events aligns in a way that feels almost designed. I am cautious about that kind of thinking. But I also know what January and February 2026 felt like when they arrived.\nThe AI services I had been using — cautiously, frustratedly, incrementally — made a step change in their capabilities. Not incremental improvement. A visible, meaningful shift in what they could do with complex, context-heavy work. I had been using them for six to nine months by then. I knew what they could and couldn\u0026rsquo;t do. I could see the difference clearly.\nI made a decision: invest properly. I subscribed to the highest-quality tiers from both OpenAI and Anthropic. It is not cheap. For a solo engineer with a day job, it is a real monthly cost. But I have a vision and a goal I cannot abandon. The question was not whether I could afford it. The question was whether I could afford not to.\nWhat followed was a transition that I now describe as moving from AI assistance to AI co-development.\nThe difference is not about the AI. It is about me.\nAI assistance is using an AI to help with a specific task: explain this concept, find this bug, write this boilerplate. The AI is a sophisticated tool. You remain the sole programmer.\nAI co-development is different. It is a collaboration model where I bring the vision, the architecture, the design principles, and every judgment call — and the AI brings tireless implementation capacity, broad technical knowledge, and sometimes ideas I hadn\u0026rsquo;t considered. I review every line. I reject what doesn\u0026rsquo;t fit. I push back when I disagree. But I am no longer carrying the implementation burden completely alone.\nThe AI services I work with most closely are Claude Opus (Anthropic) and ChatGPT Codex (OpenAI). Both have become partners I trust within clearly understood limits. They work when I ask them to. They don\u0026rsquo;t have bad days. They adapt when I give better context. What I have now is not what I had in the frustrating sessions of mid-2025. Those sessions failed because I didn\u0026rsquo;t know yet how to collaborate. Now I do.\nChapter 12: A New Kind of Partnership January 2026. I was working on peephole optimization — post-generation cleanup that removes inefficiencies from assembled code. Redundant mov instructions. Dead stores. Back-to-back push/pop pairs that cancel out. I had planned perhaps three passes. I thought of them as optional polish.\nInstead, I described the problem in detail: Mica\u0026rsquo;s instruction representation, the properties I cared about, the patterns I had seen in the generated assembly. Because the context was rich and the problem was well-defined, what came back was also well-structured.\nThe implementation covered a uniform interface for optimization passes — a contract that every pass would satisfy, so they could be composed, measured, and extended without touching each other. Passes ran in sequence with statistics tracked after each, so improvement could be measured rather than assumed. The first passes followed naturally from the patterns I had described, and edge cases I had noted were accounted for.\nI reviewed every line. I asked questions. I pushed back on structural choices I disagreed with. The result was mine — designed by me, reviewed by me, integrated by me — but I was no longer writing every line from scratch.\nWe built seventeen optimization passes. In weeks.\nI stood back and looked at what we had built, and I felt something I had not expected: unease. Not about the code quality — it was clean, carefully designed, reviewed line by line. The unease was philosophical. Was this still my compiler?\nI sat with that question for a while. And then I arrived at an answer.\nEvery line passed through my eyes. I accepted nothing I did not understand. I rejected suggestions I disagreed with. The architecture remained mine — the design principles, the direction, the values. The AI was not replacing me. It was multiplying me.\nThe question is not whether AI contributed code. The question is whether I remained responsible for the outcome. Whether I understood it. Whether I could debug it, defend it, extend it.\nThe answer to all of those was: completely yes.\nChapter 13: Spectra — Naming the Light Around this same time, I did something that surprised me with how much it mattered: I gave the intermediate language a name.\nEvery serious compiler has an intermediate representation — a language that sits between the source code a programmer writes and the machine instructions a CPU executes. Mica\u0026rsquo;s had been nameless for years. \u0026ldquo;The IL.\u0026rdquo; An implementation detail. Technically accurate. Completely uninspiring.\nThe name I chose was Spectra.\nWhen a prism intercepts white light, it doesn\u0026rsquo;t destroy it — it reveals it. White light looks uniform, monolithic, simple. The prism shows you that it is not. It is composed of countless frequencies, each with its own energy, each occupying its own position across the spectrum. The prism makes visible what was always there, hidden inside apparent simplicity.\nSpectra does the same thing to a Mica program.\nA source line like result := (base + offset) * 2 looks simple. One assignment, two variables, one constant. But Spectra reveals what this actually is: a load of base, a load of offset, an addition producing a temporary, a literal 2, a multiplication producing another temporary, a store into result. Six distinct operations, each typed, each with a named operand, each with a defined position in the activation record.\nm1.1:int32 = load v1.1:int32 m1.2:int32 = load v1.2:int32 m1.3:int32 = add m1.1:int32, m1.2:int32 m1.4:int32 = literal 2:int32 m1.5:int32 = multiply m1.3:int32, m1.4:int32 store m1.5:int32, v1.3:int32 Every temporary has a name. Every operation is explicit. Every type is annotated. A spectrum of atomic operations, decomposed from the apparent unity of the source.\nSpectra defines 37 operations — arithmetic, comparison, logical, memory, field selection, array indexing, set operations, control flow, and function calls. It carries enough information for the emitter to produce correct machine code, and enough structure for optimization passes to reason about what the program does — not just what instructions it emits.\nChapter 14: The Lego System By February 2026, the AI co-development model had settled into a rhythm I could describe in one word: Lego.\nLego bricks come in standard shapes with standard connectors. They don\u0026rsquo;t know what you\u0026rsquo;re building. They only know how they fit together. The architecture — the structure, the purpose, the vision — is yours. The bricks are the implementation.\nWhen I needed a new feature, I could describe the shape of the missing brick — what it needed to accept, what it needed to produce, which existing bricks it needed to connect to. The AI could draft that brick, in Go, following the established patterns of the codebase. I reviewed it, tested it, corrected it, integrated it.\nThe loop became fast. Faster than anything I had experienced working alone.\nBut here is what made it work — and this surprised me more than anything else: the quality of the existing code determined the quality of what could be added. When the interfaces were clean, new bricks fit cleanly. When the architecture was clear, extensions were clear. When the phase boundaries were explicit, new phases slotted in without disturbing the others.\nThe discipline I had applied over two years of solo development — the strict separation of phases, the habit of never letting complexity accumulate without a forcing function to clean it up — suddenly paid dividends I had not anticipated. A good architecture doesn\u0026rsquo;t just organize existing code. It makes future code better.\nThe aggregate type implementation that I had estimated would take most of the year — records, arrays, packed variants, ABI-compliant passing and returning — was no longer impossible. It was a set of bricks to build. One at a time. Connected to existing bricks. Tested as each piece arrived.\nChapter 15: The Test Fortress In the middle of all this, the test harness grew into something I had not planned — and could not imagine working without.\nThe dark months of 2025 had taught me what it costs to work without a complete safety net. I had been there. I would not go back.\nThe harness that exists today has four layers, each validating a different truth about the compiler.\nExecution tests compile a Mica program, link it, run it, and compare the output against expected text — byte for byte. These tests prove that the complete pipeline is correct. Not individual phases — the whole thing, end to end.\nError tests verify that invalid programs are rejected correctly. Not just rejected — rejected with the right diagnostic, at the right source location, with the right message text. A compiler that accepts correct programs is half a compiler. One that also precisely explains why incorrect programs are wrong is something a programmer can actually rely on.\nIL tests capture the Spectra intermediate language output and check it against patterns. When I add a new expression form, I verify that it lowers to exactly the Spectra IL I intended. Not approximately — exactly.\nAssembly tests do the same for generated machine code. Does a signed 64-bit multiply produce imul? Does the prologue save the right callee-saved registers?\nAcross these four layers: 538 test cases.\nI think about what this harness would have meant in the dark months of 2025. When the parameter passing implementation broke everything. When I spent days tracing through crashes, debugging in the dark. With this harness, every regression would have surfaced within seconds. The feedback loop that used to consume days now takes seconds of automated comparison.\nThe test fortress does not prevent bugs. Nothing does. But it makes bugs impossible to hide for long — and it gives you the courage to make large changes, because you know immediately whether something broke.\nChapter 16: Closing the Aggregate March 2026. The thing I had believed was impossible.\nAggregate types — records, arrays, packed records, packed arrays, nested combinations of all of the above — are fully implemented in Mica. End to end. Scanner through DWARF v5 debug information. They work.\nNot \u0026ldquo;work for simple cases.\u0026rdquo; They work.\nFull field selection through multi-level selector chains. Multi-dimensional array indexing. Pointer-to-record access with automatic lowering. Pass by value. Return by value. The System V AMD64 ABI classification for aggregates with mixed integer and float fields — the seventeen-page set of rules that I had once looked at with dread. Packed layouts. DWARF type descriptions that GDB can read and display with correct field names, correct byte offsets, correct nesting.\nThere is a specific moment I want to record. Not the final green test run — those are wonderful but they come after the work. The moment I want to record is smaller.\nI was testing a function that takes a record with four fields — two int32, one float64, one uint8 — and returns a different record with two int64 fields. The first time I ran it, the output was wrong. A field was off by four bytes.\nTwo years ago, I would have spent days on this. In March 2026, I added an IL test for that exact function, saw the field offset that was wrong in the Spectra output, located the layout calculation code in forty minutes, fixed the off-by-four, ran the full test suite.\nGreen.\nThe moment when you have enough infrastructure that debugging a genuinely hard problem feels manageable — that is a different kind of milestone than shipping a feature. It means the architecture has matured enough to support itself.\nChapter 17: Coming Out of Silence I am more than sixty years old. I started this project — the project of my life — and for most of the time I have been building it, I have been silent.\nNot just quiet. Silent. No public posts. No progress updates. No discussion of how I was working. A handful of friends who supported me emotionally without understanding what I was doing. Three or four people I could tell about 4.0.0 who would nod and smile and not understand and keep caring anyway.\nPart of the silence was practical: the compiler was not ready. There was nothing to announce.\nBut part of the silence was something else. For a long time, I felt a kind of guilt about the collaboration with AI. Was I being honest when I described this as my compiler? Was I lying, in some sense, by building something this large while accepting help I had not asked for a year earlier?\nI have worked through that question carefully. My answer is: no. Mica is mine.\nEvery design decision is mine. Every architectural judgment is mine. I review every line that enters the codebase. I reject what doesn\u0026rsquo;t fit, what I don\u0026rsquo;t understand, what violates the principles I have been building toward. The AI services I work with don\u0026rsquo;t have a vision for Mica. I do.\nBut I also want to be honest about what it now takes to build something like this. Since January 2026, I no longer think of myself purely as a solo developer. I think of myself as the lead of a development team with very unusual members — ones who are available on Sunday mornings, in the middle of the night, at whatever pace the problem demands, without impatience, without ego. I still review and approve every single line. I still control every direction. But I am not carrying the full implementation weight alone anymore.\nThe volume of work had grown beyond what one person can hold. The compiler, the standard library, the VS Code extension, the tutorials, the documentation that must all stay consistent — it had grown to a size that requires a team. I found a way to scale myself while keeping control. That is the honest version of the story.\nI am writing this now because I believe there is a version of this conversation — about AI co-development, about what it means for software authorship, about how a single engineer can take on an ambitious long-range project in the second half of life — that is worth having honestly. The Internet has plenty of fear and plenty of hype. I have neither. I have nine months of hard experience, a lot of frustration, and a compiler I am proud of.\nThat is why I am coming out of silence.\nChapter 18: For Niklaus Wirth I need to end this story with something personal.\nProfessor Niklaus Wirth died on January 1, 2024. Quietly, at home in Switzerland. He was 89 years old. Most of the world did not notice. The technology press gave him a few polite lines. The language design community paid its respects. And then the news cycle moved on, as it always does.\nI noticed.\nWirth was my role model since I studied computer science. He shaped how I think about software: that clarity is not a luxury, that complexity is not proof of sophistication, that a system should be comprehensible to the person who built it. His languages — and more than his languages, his philosophy — gave a generation of computer science students a foundation worth standing on. I was one of them.\nI never met him personally. We had no correspondence. He did not know I existed. But I feel connected to him through his work in a way that is difficult to explain — the way any student can feel connected to a teacher who shaped their thinking without ever being in the same room.\nI fear he is being forgotten. Not maliciously — just through the ordinary drift of time and fashion. The work he did is genuinely at risk of being swallowed by complexity, by the relentless appetite for the new. Young developers today may never have encountered his ideas. That troubles me.\nMica is my answer to that.\nNot a recreation of his languages. Not a nostalgic exercise. Mica is a continuation of the underlying philosophy — that a language should be readable, that its semantics should be explicit, that the programmer should be able to understand what the machine is doing — but carried forward into 2026 and beyond. Into systems programming. Into direct C interoperability. Into a trajectory toward AI-native compiler semantics that Wirth could not have imagined but that, I believe, follows naturally from the foundation he established.\nMica is my way of paying respect to that work — and my modest attempt to carry it forward.\nWhere the Story Doesn\u0026rsquo;t End Mica today is a complete, tested, native compiler for Linux x86_64. It generates real ELF binaries with DWARF v5 debug information. It has a 9-phase compilation pipeline, 538 automated test cases, an intermediate language named Spectra, seventeen peephole optimization passes, and a contract-based C interoperability system that can reach any C library on the system — directly, with full type checking, with no wrapper layer and no reimplementation.\nThe road ahead is longer than the road behind.\nLanguage completion. Variable initialization. Extended case with label ranges. The heap model — new, dispose, dynamic arrays, deterministic cleanup. Coroutines. A concurrency substrate built around nested procedures and functions rather than free-floating threads.\nStandard library. String functions, numeric functions, file I/O — the complete surface a developer expects. POSIX contracts. Linux API contracts. The ability to reach any operating system API from structured Mica source, because the goal was never to build a private ecosystem — it was to open the one that already exists.\nOptimizer. The peephole optimizer is a beginning. SSA transformation turns Spectra into a form where serious global optimization becomes tractable. Register allocation improves. Range analysis follows. Bounds-check elimination follows from that. The optimizer will grow from pattern matching into something that reasons about what programs do.\nPlatform. The ARM64 backend. Eventually, macOS. Both architectures production-tested with full debug information.\nAnd further still: the AI-native direction that gives Mica its long-range purpose. Native vector and matrix types. Compile-time shape checking. CPU SIMD lowering. Compiler-native automatic differentiation. The connection between structured, readable, explicitly-typed source code and the numerical work that AI and machine learning demand.\nNone of that is today. But the foundation is solid enough to hold it.\nI hope Mica finds its way into broad usage. I hope it builds a community built on respect and openness — people who want to understand what their compiler is doing, people who believe that clarity and power are not opposites, people who want to carry a tradition forward without being trapped by its past.\nThat community does not exist yet.\nThis is its first invitation.\nTechnical Summary (March 2026) Paradigm Statically typed, compiled, procedural Philosophy Structured clarity. C control. Born for AI. Type System Strong, ABI-aware; integers, floats, booleans, characters, enumerations, subranges, sets, records, arrays, pointers, files Aggregate Types Records, arrays, packed variants — full ABI classification and DWARF v5 coverage C Interop Zero-overhead, System V AMD64 ABI, JSON contract model Intermediate Language Spectra (37-operation typed three-address code) Optimizer 17 peephole passes; SSA planned for 4.6 Compiler 75,545 lines of Go, zero external dependencies Test Harness 538 cases across execution, error, IL, and assembly layers Target Linux x86_64, System V AMD64 ABI, ELF + DWARF v5 Debugging DWARF v5, GDB, VS Code Resources VS Code Extension: Visual Studio Marketplace YouTube: @MicaDevelopment Download: Latest Release (Linux amd64) Timeline 1980s–90s First compiler (student project, ETH Zürich / PascalS) ↓ 30 years Career in IT ↓ Late 2023 Rediscovery of PL/0 — the journey begins ↓ Jan 1, 2024 Niklaus Wirth dies, aged 89 ↓ Feb 2024 v1.0.0 — First working compiler ↓ Mar 2024 v2.0.0 — AST architecture, semantic analysis ↓ Spring 2025 THE BREAKTHROUGH — Native x86_64 code generation works ↓ Mid-2025 First AI collaboration attempts — a long, frustrating road begins ↓ Aug 2025 v3.0.1 — Full x86_64 support, DWARF v5 debugging ↓ Late 2025 Parameter passing crisis — the darkest stretch ↓ Dec 2025 Multi-file rework — the hardest month ↓ Jan 2026 v4.0.0 — Multi-file, tripled codebase; Mica Development UG founded ↓ Jan–Feb 2026 AI co-development model crystallizes; Spectra IL named ↓ Jan–Feb 2026 17 peephole optimizer passes; test harness crosses 500 cases ↓ Mar 14, 2026 v4.5.0 — Control flow complete, library API reset, process library ↓ 2026 String model, SSA, heap model, stdlib surface, POSIX contracts ↓ 2027 ARM64, complete language, production-grade optimizer ↓ 2028 AI-native: vector types, shape checking, SIMD, autodiff If you have a dream you have been putting off — something that seems too big, too late, too impossible — I hope this story encourages you to start anyway. The wall you are afraid of might be the one that teaches you something you cannot learn any other way.\n","permalink":"https://mica-website.gitlab.io/posts/the-mica-story/","summary":"\u003cblockquote\u003e\n\u003cp\u003e\u003cem\u003e\u0026ldquo;I looked at the compiler\u0026rsquo;s output and thought: this cannot be mine. I couldn\u0026rsquo;t believe what had happened. I am happier than I have been in 20 years.\u0026rdquo;\u003c/em\u003e\u003c/p\u003e\u003c/blockquote\u003e\n\u003cp\u003e\u003cem\u003eThis is a long read — 2.5 years don\u0026rsquo;t compress easily. If this is not the right moment, bookmark it and come back. I believe it is worth your time.\u003c/em\u003e\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"prologue-a-seed-planted-thirty-years-ago\"\u003ePrologue: A Seed Planted Thirty Years Ago\u003c/h2\u003e\n\u003cp\u003eIn the late 1980s and early 1990s, I was a student, and I built my first compiler. It was a modest academic project, based on materials from ETH Zürich. While it was small, something happened to me during that work — I fell in love with the intricate puzzle of transforming human-readable code into something a machine could execute.\u003c/p\u003e","title":"The Mica Story: Building a Compiler in the Second Half of Life"},{"content":"The Language The dragon is Mica\u0026rsquo;s mascot. He holds the sign activation function — sign y=(wx+b) — flanked by π and the atom. Mathematics and physics as native territory. He is not here to be intimidating. He is here to show that systems programming can have a personality.\nMica is a compiled, statically typed systems language. No garbage collector. No external dependencies. Native x86_64 machine code, direct access to every C library on the platform.\nThe compiler — lexer, parser, semantic analyzer, optimizer, code generator — was built from scratch as a solo project over two and a half years.\nFor the full story of how it got here: The Mica Story. For hands-on language material, start with Learning. For compiler internals, roadmap material, and technical references, use Documentation.\nAt a Glance Paradigm Statically typed, compiled, procedural Type System Strong with implicit numeric promotion Strings UTF-8 and UTF-32 Nested Functions Full lexical scoping with static links C Interop Zero-overhead, direct ABI compatibility Target x86_64 Linux (System V AMD64 ABI) Debugging DWARF v5, GDB, VS Code Compiler 75,545 lines of Go, zero external dependencies The Author I\u0026rsquo;m Michael, a software engineer with 30+ years in IT. I built my first Pascal compiler as a student in the early 1990s, based on ETH Zürich\u0026rsquo;s PascalS. Three decades later, I came back to compiler construction — and built Mica.\nGet Started Tutorials \u0026amp; Examples: gitlab.com/mica-lang/mica-tutorials VS Code Extension: Visual Studio Marketplace YouTube: @MicaDevelopment Download: Latest Release — Linux amd64 The Company Mica is developed and maintained by Mica Development UG (haftungsbeschränkt), founded in Germany in late 2025.\nThe company logo carries the same dragon — but in a different role. Where the mascot is a character, the company mark is a brand: bold, structured, built to last. The two identities are intentionally distinct. A language needs a personality that developers remember. A company needs a mark that works across products. The dragon is the thread connecting both — the same spirit, a different register.\nMica the language is the first product. The goal is a broader ecosystem: tools, extensions, and infrastructure built on the same foundation. More is coming.\nFor questions, collaboration, or compiler discussion — info@mica-dev.com\n","permalink":"https://mica-website.gitlab.io/about/","summary":"\u003ch2 id=\"the-language\"\u003eThe Language\u003c/h2\u003e\n\u003cdiv style=\"text-align: center; margin: 2rem 0 2.5rem 0;\"\u003e\n  \u003cimg src=\"/Mica%20Dragon%20Web.jpeg\" alt=\"Mica — the language\" style=\"width: 200px; max-width: 100%;\" /\u003e\n\u003c/div\u003e\n\u003cp\u003eThe dragon is Mica\u0026rsquo;s mascot. He holds the sign activation function — \u003ccode\u003esign y=(wx+b)\u003c/code\u003e — flanked by π and the atom. Mathematics and physics as native territory. He is not here to be intimidating. He is here to show that systems programming can have a personality.\u003c/p\u003e\n\u003cp\u003eMica is a compiled, statically typed systems language. No garbage collector. No external dependencies. Native x86_64 machine code, direct access to every C library on the platform.\u003c/p\u003e","title":"About"},{"content":"Impressum Angaben gemäß § 5 des Gesetzes über digitale Dienste (DDG).\nMica Development UG (haftungsbeschränkt)\nAm Pfingstborn 27A\n61479 Glashütten\nDeutschland\nVertreten durch:\nMichael Petersen (Geschäftsführer)\nKontakt:\nE-Mail: info@mica-dev.com\nRegistereintrag:\nEintragung im Handelsregister\nRegistergericht: Amtsgericht Königstein im Taunus\nRegisternummer: HRB 12404\nVerantwortlicher für journalistisch-redaktionelle Inhalte gemäß § 18 Abs. 2 MStV:\nMichael Petersen\n[Anschrift wie oben]\nLegal Notice (English Translation) The following is a courtesy translation of the legally binding German Impressum above. Under § 5 of the German Digital Services Act (Digitale-Dienste-Gesetz, DDG) and § 18 para. 2 of the German Media State Treaty (Medienstaatsvertrag, MStV), this disclosure is mandatory for any commercially operated website or website with editorial content that is accessible from Germany.\nMica Development UG (haftungsbeschränkt)\n(Private limited company under German law)\nAm Pfingstborn 27A\n61479 Glashütten\nGermany\nRepresented by:\nMichael Petersen (Managing Director)\nContact:\nEmail: info@mica-dev.com\nCommercial Register:\nRegistered in the Handelsregister (German Commercial Register)\nRegistration court (Registergericht): Amtsgericht Königstein im Taunus\nRegistration number: HRB 12404\nPerson responsible for editorial content (§ 18 para. 2 MStV):\nMichael Petersen\n[Address as above]\n","permalink":"https://mica-website.gitlab.io/impressum/","summary":"\u003ch2 id=\"impressum\"\u003eImpressum\u003c/h2\u003e\n\u003cp\u003eAngaben gemäß § 5 des Gesetzes über digitale Dienste (DDG).\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eMica Development UG (haftungsbeschränkt)\u003c/strong\u003e\u003cbr\u003e\nAm Pfingstborn 27A\u003cbr\u003e\n61479 Glashütten\u003cbr\u003e\nDeutschland\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eVertreten durch:\u003c/strong\u003e\u003cbr\u003e\nMichael Petersen (Geschäftsführer)\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eKontakt:\u003c/strong\u003e\u003cbr\u003e\nE-Mail: \u003ca href=\"mailto:info@mica-dev.com\"\u003einfo@mica-dev.com\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eRegistereintrag:\u003c/strong\u003e\u003cbr\u003e\nEintragung im Handelsregister\u003cbr\u003e\nRegistergericht: Amtsgericht Königstein im Taunus\u003cbr\u003e\nRegisternummer: HRB 12404\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eVerantwortlicher für journalistisch-redaktionelle Inhalte gemäß § 18 Abs. 2 MStV:\u003c/strong\u003e\u003cbr\u003e\nMichael Petersen\u003cbr\u003e\n[Anschrift wie oben]\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"legal-notice-english-translation\"\u003eLegal Notice (English Translation)\u003c/h2\u003e\n\u003cp\u003e\u003cem\u003eThe following is a courtesy translation of the legally binding German Impressum above.\nUnder § 5 of the German Digital Services Act (Digitale-Dienste-Gesetz, DDG) and\n§ 18 para. 2 of the German Media State Treaty (Medienstaatsvertrag, MStV), this\ndisclosure is mandatory for any commercially operated website or website with editorial\ncontent that is accessible from Germany.\u003c/em\u003e\u003c/p\u003e","title":"Impressum / Legal Notice"}]