!~ATH (pronounced "until death") is an esoteric programming language where all control flow is predicated on waiting for things to die. Inspired by the fictional ~ATH language from Homestuck. Everything is about death. Loops wait for entities to die. Computation happens in death callbacks. The language is deliberately inconvenient.
Entities are mortal things that can be waited upon. Each entity is either
alive or dead. Create entities with import:
import timer T(1s); // dies after 1 second import timer T2(500ms); // dies after 500 milliseconds
import process P("cmd"); // dies when process exits [NOT IN BROWSER]
import connection C("host", 80); // dies when connection closes [NOT IN BROWSER]
import watcher W("file.txt"); // dies when file is deleted [NOT IN BROWSER]
THIS is an implicit entity representing the program itself.
Kill entities manually with .DIE(). The program ends when
THIS.DIE(); is called.
The fundamental control structure. Waits for an entity to die, then runs the EXECUTE clause:
import timer T(1s);
~ATH(T) {
} EXECUTE(UTTER("Timer died!"));
THIS.DIE();
Combine entities with && (both must die), ||
(either dies), or ! (dies immediately when created):
~ATH(T1 && T2) { } EXECUTE(...); // wait for both
~ATH(T1 || T2) { } EXECUTE(...); // wait for either
~ATH(!T) { } EXECUTE(...); // runs immediately
Split execution into concurrent branches:
bifurcate THIS[LEFT, RIGHT];
~ATH(LEFT) {
// code for left branch
} EXECUTE(VOID);
~ATH(RIGHT) {
// code for right branch
} EXECUTE(VOID);
[LEFT, RIGHT].DIE();
BIRTH x WITH 5; // mutable variable ENTOMB PI WITH 3.14159; // constant (immutable) x = x + 1; // reassignment
42, -7 // INTEGER
3.14, -0.5 // FLOAT
"hello\nworld" // STRING (escapes: \\ \" \n \t)
ALIVE, DEAD // BOOLEAN (truthy/falsy)
VOID // absence of value
[1, 2, 3] // ARRAY
{name: "Karkat", age: 6} // MAP
+ - * / % // arithmetic (/ is integer div for ints) == != < > <= >= // comparison AND OR NOT // logical (short-circuit) arr[0] map["key"] map.key // indexing
SHOULD condition {
// if truthy
} LEST {
// else
}
No loops in the expression language. Use ~ATH with timers for iteration:
RITE countdown(n) {
SHOULD n > 0 {
UTTER(n);
import timer T(1s);
~ATH(T) { } EXECUTE(countdown(n - 1));
}
}
countdown(5);
THIS.DIE();
RITE add(a, b) {
BEQUEATH a + b; // return value
}
BIRTH sum WITH add(2, 3);
ATTEMPT {
BIRTH x WITH PARSE_INT("bad");
} SALVAGE error {
UTTER("Error: " + error);
}
CONDEMN "Something went wrong"; // throw error
I/O:
UTTER("Hello", x); // print (space-separated, newline appended)
BIRTH line WITH HEED(); // read line from input
SCRY("file.txt") // read file [NOT IN BROWSER]
INSCRIBE("file.txt", s) // write file [NOT IN BROWSER]
Type operations:
TYPEOF(x) // "INTEGER", "FLOAT", "STRING", etc.
LENGTH(arr), LENGTH(str) // length of array or string
PARSE_INT("42") // string to integer
PARSE_FLOAT("3.14") // string to float
STRING(42) // value to string
INT(3.7) // float to integer (truncates)
FLOAT(42) // integer to float
Array operations:
APPEND(arr, val) // add to end (returns new array) PREPEND(arr, val) // add to start SLICE(arr, start, end) // subsequence FIRST(arr), LAST(arr) // first/last element CONCAT(arr1, arr2) // concatenate arrays
Map operations:
KEYS(map), VALUES(map) // get keys/values as arrays HAS(map, key) // check if key exists SET(map, key, val) // set key (returns new map) DELETE(map, key) // remove key
String operations:
SPLIT("a,b,c", ",") // split to array
JOIN(arr, ",") // join array to string
SUBSTRING(s, start, end) // extract substring
UPPERCASE(s), LOWERCASE(s), TRIM(s)
REPLACE(s, old, new) // replace all occurrences
Utility:
RANDOM() // random float 0 to 1 RANDOM_INT(min, max) // random integer in range TIME() // Unix timestamp in ms