Quilon Language Reference
Version: 0.9.2 — “Hegemon” (stable basics — the core is solid and verified end-to-end, but the language is not yet feature-complete; see Known limitations).
Quilon is a statically-typed, symbol-based language (no control-flow keywords) that compiles to native code via LLVM. Every example in this reference has a passing end-to-end test. Each examples/*.qn program is self-asserting: it verifies its own results in-language with assert(value, matcher) and exits 0 (a failing assertion aborts with exit 101), under both the JIT (quilon run) and native AOT.
Design principles
Section titled “Design principles”Quilon’s identity, and the rules that guide its design:
- No keywords. Every construct is punctuation, not words — nothing was removed from the language; the words were. Branching is
?/|, the entry point is^, import/export are<</>>, mutability is:=, sum-type alternatives are/. Not one word is reserved:if,while,forand the rest are ordinary identifiers you may bind. - Symbols mirror notation that already exists. A symbol reuses a notation the world already has rather than inventing one:
/separates sum-type alternatives the way you already write “red / green / blue”. - The playful choice wins. On a genuine toss-up, the more delightful option is picked —
^for the entry point,$for Unit. Syntax is allowed a sense of humor. - Deliberate simplicity. The smallest system that works: no generics (ad-hoc overloading is the only polymorphism), no
while, no interfaces, a singleNumtype. Features are omitted on purpose. - Fail loud, never silent. Invalid inputs and meaningless operations must fail — never silently no-op, clamp, or return a magic sentinel. A statically-determinable problem is a compile error; anything else is a runtime error on stderr with a non-zero exit, saying where it happened. (Hence
Text.indexOf → Ok(Num)/NotOkrather than a-1sentinel, andText.replace’s count/empty-argument checks failing rather than clamping.) - No magic. No hidden coercions, no implicit dispatch. Overloads are exact-typed; operators mean what they say.
- Immutable by default.
=binds immutably,:=binds mutably — for variables, for record bindings, and for methods: a method declaredname := …may mutate its receiver, and one declaredname = …is checked to make sure it does not. - Errors are values. Fallible operations return
Ok/NotOk(a normal sum type) — no exceptions, no sentinels. - Library APIs hide internals. A library never makes the caller do its own conversion/desugaring (
print(x), neverprint(show(x))).
Symbols
Section titled “Symbols”| Symbol | Meaning | Example |
|---|---|---|
= | Immutable binding | x = 42 |
:= | Mutable bind / reassign / in-place field write | counter := 0, obj.field := v |
:: | Type annotation | x :: Num |
=> | Function body / match arm | f = (x :: Num) => x + 1 |
-> | Return type; also a function type | f = (x :: Num) -> Num => x · (Num) -> Bool |
+ - * / % | Arithmetic (-x negates) | a + b · x % 2 |
== != < <= > >= | Comparison → Bool · ==/!= over Num/Text/Bool, ordering over Num/Text | a == b · x <= 3 |
&& || ! | Logical and / or / not (short-circuit) | a && !b |
< > | Block delimiters · also </> comparison (rule) | < a b a + b > · a < b · a > b |
^ | Entry point (main) | ^ = () -> Num => 0 |
$ | Unit type and its sole value | f = () -> $ => $ |
<< | Import a module | << core.io |
>> | Export an item from a module | >> add = (a :: Num, b :: Num) => a + b |
|> | Pipe (first-argument injection) | x |> f(a) ≡ f(x, a) |
<- (infix) | Inclusive range → []Num | 1 <- 4 ≡ [1,2,3,4] · 4 <- 1 ≡ [4,3,2,1] |
<- (prefix) | Spread inside a [ ] / { } literal (rule) | [<-xs, 4] · {<-p, x = 9} · Vec {<-p, x = 9} |
? | _ | Pattern match | v ? | 0 => "zero" | _ => "other" |
/ | Division or sum-type variant separator | a / b · Color = Red / Green |
[| |] | Map / Set pipe fence (=> = “maps to”) | [|"a" => 1|] (map) · [|1, 2|] (set) |
+- -+ | Set intersection (one symmetric operator) | a +- b ≡ a -+ b |
` (in a string) | Interpolation hole · “ = one literal backtick | "hi `user.name`" |
` (as a name) | The overloadable render operator — a type’s Text rendering | ` = () -> Text => "..." |
? : | Ternary | x < 0 ? -x : x |
@ (name prefix) | A leaf IO primitive (corelib-only; user code calls, never declares) | @sleep(1) |
~ | Comment (to end of line) | ~ a note |
There are no keywords: if/return etc. are all expressed with symbols, and there
are no loop constructs at all — iteration is via array methods and recursion.
No word is reserved either, so if = 5 or a function named while is perfectly legal.
Contents
Section titled “Contents”- Types: overview (
Num,Bool,$) · Text · records · sum types - Collections: arrays, maps, and sets
- Variables · Mutation
- Functions: basics · closures and tail recursion · overloading · call-site locations
- Expressions: operators and blocks · pipe · iteration · ranges and spread · pattern matching
- Modules: imports and exports · entry point
- Corelib: the standard library, module by module
- Concurrency · its runtime
- Memory
- Tooling: compiling & running · error messages
- Status: feature matrix · known limitations · compiler architecture