Symbols
!! · ## · ( ) · ** · . · // · /// · :: · => · [ ] · _ · · { }
!!
The WOMT operator — “Wait! One more thing!” After a keyword’s arguments, it starts its modifiers. A modifier is a function that returns a map, and I use the map’s keys to fill the keyword’s parameters by name. The keyword has to ALLOW each modifier.
Example
DRAW LINE path, red !! thickness(3) dashed
Chains statements on one line: I pass the value of each stage to the next as _. Every stage after the first has to use _ — otherwise that value would be lost. The one exception is a stage that is nothing but a function written in place: I call that with the value.
Examples
doubled = score_of("ada") ## _ * 2
count = load("level1") ## level => LEN(level.rooms)
( )
After a name, calls a function or reads from an array or a map. Around one value, groups it. Around two or more numbers, makes a coordinate.
Example
PRINT double(4), scores(0), (1 + 2) * 3, (10, 20)
**
At the start of an argument, spreads one value into several arguments. I lay out an array, a coordinate or a vector in order; a map fills parameters by name.
Example
DRAW **corners
grid(**pos) = 1
spawn(**{kind: "slime", hp: 5})
.
Reads or writes a field of an object or a map, calls a method, or reaches into a namespace. On a coordinate, .x, .y, .z and .w are its numbers; on a vector, .start and .stop are its ends. A reserved word is fine as a field name too: thing.type.
Example
hero.hp = hero.hp - 1
PRINT pos.x, Geometry.midpoint(a, b)
//
A comment: a note for people. I skip the rest of the line.
Example
lives = 3 // three tries
///
A documentation comment. It belongs to the FUNCTION, TYPE, field, NAMESPACE or any kind of BIND on the next line, and it’s what I show for it on pages like this one.
Above a function, lines starting with ! mean something special to me. !code: message declares an error the function can return, and !tip: under it adds advice. !returns: describes the result, !example: shows a use, !deprecated: has me warn anyone who still uses the function. !param name: says what one parameter is for. !category:, !status:, !since:, !see: and !label: say where the function belongs in the documentation and change nothing about what it does. !value turns the function into a value: you read it by its name alone, like a variable, and I call it each time you do. Two more are for host functions: !accepts-errors lets one be given error values, and !accepts-futures lets one be given futures that haven’t been resolved.
Example
/// Loads a saved game.
/// !save-missing: I can't find a save called `{name}`!
/// !tip: Saves live in the `saves` folder.
/// !returns: the saved game as a map
FUNCTION load_game(name)
::
In a function’s declaration, joins a type’s name to a method’s name.
Example
FUNCTION Player::Heal(amount)
=>
Makes a function out of one expression, right where it’s used. The names in front are its parameters and what follows is what it gives back: everything up to the next comma or closing bracket. It gets a copy of the locals around it, like any function written in place. When it needs more than one line, write FUNCTION(parameters) and END FUNCTION instead.
name => expression
(first, second) => expression
Examples
double = n => n * 2
alive = filter(squad, unit => unit.hp > 0)
total = fold(scores, 0, (sum, score) => sum + score)
[ ]
Makes an array. I count arrays from 0, and I’ll stop you if you read or write past the end.
Example
scores = [10, 20, 30]
scores(0) = 15
_
Inside a ## chain, the value of the stage before.
Example
load("level1") ## PRINT _
Text that can run over as many lines as you like. I take it exactly as you wrote it: a backslash is just a backslash, and two backticks together are how you write one. Start the text on the line after the opening backtick and I treat it as a block — I drop that first line break and the indentation all its lines share, so you can keep it lined up with your code.
Examples
query = `
SELECT name
FROM players
`
path = `C:\games\saves`
Makes a map. A bare word as a key is the key’s name, not a variable; a key worked out from an expression goes in parentheses. I keep keys written as bare words in lowercase. Ask for a key the map doesn’t have and you get NULL. Even one of my reserved words works as a bare key, so {type: "enemy"} is fine.
Example
player = {name: "ada", hp: 100}
PRINT player.name, player("hp")