Language reference
A complete guide to code-lang syntax and semantics. All examples can be run in the REPL or saved to a .cl file.
Comments
# single-line comment
/* multi-line
comment */Variables
let declares a mutable variable. const declares a constant — reassignment is a runtime error.
let age = 25;
const PI = 3.14159;
age = 26; # ok
PI = 3; # error: cannot reassign constantTypes
| Type | Literal example | Notes |
|---|---|---|
| Integer | 42, -7 | 64-bit signed |
| Float | 3.14, -0.5 | 64-bit IEEE 754 |
| String | "hello" | UTF-8, double-quoted |
| Char | 'a' | Single character, single-quoted |
| Boolean | true, false | |
| Null | null | Absence of value |
| Array | [1, "x", true] | Mixed types allowed |
| Hash | { "k": 1 } | Any type as key or value |
| Function | fn(x) { x * 2 } | First-class value |
| Struct | Point { x: 1 } | Typed object with defaults |
Operators
| Category | Operators |
|---|---|
| Arithmetic | + - * / % · ** power · // floor division |
| Comparison | == != < > <= >= |
| Logical | && || ! — short-circuit evaluation |
| Compound assign | += -= *= /= %= |
| Increment / decrement | ++ -- prefix and postfix |
| String concat | + — works between strings |
2 ** 8; # 256
17 // 5; # 3 (floor division)
10 % 3; # 1
let n = 5;
n++; # n is now 6
n += 10; # n is now 16Control flow
if / elseif / else
let score = 85;
if (score >= 90) {
"A"
} elseif (score >= 80) {
"B"
} else {
"C"
};while
let i = 0;
while (i < 5) {
i += 1;
};for
for (let i = 0; i < 5; i++) {
if (i == 2) { continue; };
if (i == 4) { break; };
};break and continue work in both while and for.
Functions
Functions are values. Assign them with let or const. Return early with return — the last expression in a block is also returned implicitly.
let add = fn(a, b) {
return a + b;
};
let square = fn(x) { x * x }; # implicit return
add(3, 4); # 7
square(9); # 81Closures
Functions close over the enclosing scope and capture variables by reference.
let make_adder = fn(n) {
return fn(x) { x + n };
};
let add5 = make_adder(5);
add5(10); # 15
add5(20); # 25Recursion
let fib = fn(n) {
if (n <= 1) { return n; };
return fib(n - 1) + fib(n - 2);
};
fib(10); # 55Higher-order functions
map, filter, and reduce are not in the stdlib yet because they need evaluator access to call function values. Use for loops in the meantime.let apply = fn(f, x) { f(x) };
apply(fn(n) { n * 2 }, 7); # 14Arrays
let nums = [1, 2, 3, 4, 5];
nums[0]; # 1
nums[2] = 99; # mutate in place
nums[-1]; # last element (if supported)
let mixed = [1, "hello", true, [2, 3]];See the arrays module for slice, sort, zip, flatten, and 15 more operations.
Hashes
let person = { "name": "Alice", "age": 30 };
person["name"]; # Alice
person.name; # same — dot access works too
person["role"] = "admin"; # add or update keyKeys can be any type. See the hash module for keys, values, merge, and more.
Structs
Structs define a named type with default field values. Instantiate with TypeName { fields } — any field not provided gets its default.
struct User {
name: "Guest",
role: "user",
active: true,
}
let admin = User { name: "Walon", role: "admin" };
let guest = User {};
admin.name; # Walon
guest.name; # Guest
guest.active; # trueModules
Import stdlib
import "math";
import "strings";
math.sqrt(16); # 4.0
math.clamp(150, 0, 100); # 100
strings.split("a,b,c", ","); # ["a", "b", "c"]
strings.to_upper("hello"); # HELLOImport a .cl file
Import any .cl file by its path (without the extension). Everything declared at the top level in that file becomes a field on the resulting module object.
# utils.cl
const VERSION = "1.0";
let double = fn(x) { x * 2 };
# main.cl
import "utils";
utils.double(5); # 10
utils.VERSION; # 1.0See all 12 built-in modules in the standard library reference.