Two questions hide under “does the language support Unicode?”, and most languages answer them in one tangle. What may the source contain? And how are strings stored at run time? Mica answers them separately, and both answers fit in a sentence. The source: anything — the language does not reserve the alphabet. The storage: a build-time choice between utf-32 and utf-8 that never changes what a program means.
The example is UtfSources; it pairs with Text, which owns the string value itself.
Identifiers in any script
var
Straße, Вулиця, Δρόμος, ストリート, 长变量名 : int32;
procedure 절차의긴이름();
begin
WriteLn(" a procedure named 절차의긴이름 answered %d", 42);
end;Identifiers in five scripts
Straße = 1, Вулиця = 2, Δρόμος = 3
ストリート + 长变量名 * Δρόμος = 19
Routine names too
a procedure named 절차의긴이름 answered 42A non-ASCII identifier is a name like any other — it declares, assigns, participates in expressions, names a procedure, and nothing about it is a special case to the compiler, the debugger, or the language server. A team in Kyiv or Kyoto writes its domain vocabulary in its own script, and the teaching examples on this site stay honest about what that costs: nothing.
Strings count runes, whatever the build
Strings count runes, not bytes
こんにちは世界!🎌 — 9 runes
مرحبا بالعالم!🌍 — 15 runes
🚀 Mica 世界 — 9 runes
The walk takes rune-sized steps
'🚀 Mica 世界' walked in 9 steps, first 🚀, last 界Length answers what a reader would count on the screen. The rocket is
four bytes under utf-8 and one rune everywhere; the byte number would
change with the encoding, and that is exactly why the length of a Mica
string is not defined as one. The for ch in s walk takes the same nine
steps under either build — under utf-8 it advances a byte cursor by each
rune’s width in one pass, and none of that machinery reaches the program.
The choice, and the one place it shows
The encoding is a property of the build, never of a value:
make -C examples/UtfSources run # utf-32, the default
make -C examples/UtfSources MICA_ENCODING=utf-8 # the same program?Almost. Every rune count, every walk, every comparison in this example is identical under both — but the second build refuses:
analyzer error 5184: format string validation error: string format
specifier at position 1 must use '%s' for UTF-8 encoding (found '%ls')A format specifier names the storage its argument arrives in — %ls for
utf-32 code units, %s for utf-8 bytes — and the compiler holds the format
string to the build’s truth rather than letting a mismatched specifier
garble a line at run time. That is the whole visible surface of the
encoding choice: one letter in format strings, checked before the program
exists.
When does utf-8 earn its flag? At the boundary. A program that mostly hands text to C libraries, files, or sockets saves the conversion by storing utf-8 natively — the C boundary examples build that way. A program that mostly indexes and slices its own text takes the default: utf-32’s fixed-width runes make positional access constant time.
What this does not do
- The encoding is never per-value. There is no utf-8 string next to a utf-32 string in one program, no tagged storage, no implicit transcoding between values — one build, one storage, by design.
- A
mica.projectcan pin it. The build flag and the project file are two spellings of the same fact; the editor’s diagnostics follow the project file, so what you see while typing is what the build does. - Identifiers are not normalized. Two visually identical names composed of different code points are different names — write a codebase in one input method’s output, as you already do in one natural language.
Try it
git clone https://gitlab.com/mica-lang/mica-container.git
make -C mica-container/examples/UtfSources run
make -C mica-container/examples/UtfSources clean
make -C mica-container/examples/UtfSources MICA_ENCODING=utf-8The third command meets refusal 5184 four times — once per %ls whose
argument would arrive as utf-8 bytes. Change those four specifiers to %s
and the program builds and prints the same runes; those one-letter edits
are the entire porting cost between the encodings.
Next
The strings group is told: the value, builder and window in Text, the source and the encoding here. The series continues with programs in the large — units, libraries, and generics.