Most of what the Mica compiler guarantees depends on seeing the whole program’s behaviour. An indirect call is opaque: the analyzer cannot know its effects and the optimizer cannot reason across it. One such construct in the language would not weaken a guarantee slightly — it would remove the ability to make it at all.
So several constructs are refused by the compiler rather than discouraged in a style guide: reaching for one meets a parse error, never a silent acceptance.
The refusals are not all the same shape
This distinction matters when reading Mica code, and it is easy to overstate:
- Absent from the grammar.
gotoandlabelare not keywords. They are not reserved either: both are legal variable names, and a program declaring them compiles and links. They are refused only as statements — written where a statement belongs,gotoparses as a bare identifier. - Reserved, and accepted nowhere.
withis a word the compiler knows. No rule accepts it, which also makes it unusable as an identifier — declaring a variable calledwithis itself an error. This is a stronger refusal thangoto’s, not a weaker one. - Refused in one position only.
procedureis a reserved word and the ordinary way to declare a routine —procedure Name();, parentheses required. Procedure declarations run right through the merge-gated corpus. What is refused is the procedural type: you cannot name a signature and store a routine in a variable.
Only the last is the function-pointer refusal — worth stating exactly, because “Mica has no procedures” would be wrong in a way that matters.
| Refused | Principle it would break | The replacement |
|---|---|---|
goto and labels | structured control flow | leave / next, including leave <loop> when <condition> |
with record do | names mean what they say | explicit selectors — p.x |
| procedural types (function pointers) | analyzability | capability-constrained generics, unit finalizers, signalfd/timerfd, the task tree |
pointer pointer T | one visible level of indirection | records with pointer fields |
| variant records | this is the silent-corruption class | tagged alternatives via explicit types |
Each of them but goto presents as a parse error naming the offending word —
expected identifier or wildcard '*', found procedure for a procedural type, the
same message with found pointer for a second level of indirection. goto is the
exception, for the reason above: with no such word in the grammar, the parser can
only report expected becomes, found identifier.
Variant records
Variant records are the clearest case, and the only one refused on safety grounds
rather than language identity. A case arm inside a record — the untagged union
— is rejected where the record body expects to end. Write one arm, read another,
get garbage with no diagnostic: that is precisely the silent-corruption failure
mode the whole project exists to eliminate.
The genuine need a variant record serves — a value that is one of several shapes — is not met today. It waits on user-definable capabilities, where the discriminant would be one the compiler enforces rather than one the programmer promises to check.
Every callback need has a known answer
The usual objection to refusing function pointers is that callbacks are necessary. They are — but each concrete need has a structural form the compiler can see:
- Sorting by a comparison — a generic constrained by the
orderedcapability, monomorphized at the call site. - Cleanup on scope exit —
defer, and unit finalizers. - Reacting to signals and timers —
signalfdandtimerfd, which are file descriptors, not callbacks. - Concurrent work — the task tree, where the compiler knows the whole shape.
Each one is analysable in a way an indirect call through a variable is not.
Named loop exits
The replacement for goto covers the case people actually reach for it — a
bounded scan that stops the moment a guard fires:
scan : for i := 1 to 100 do
begin
leave scan when i > 5;
count := count + 1;
end;A named loop is left by name, from any nesting depth, without a label to jump to.
The guard is evaluated on each arrival. The same when suffix guards next, and
guards the bare leave that returns from a procedure early.