KAL expressions & built-ins
Types, literals, the full operator set with precedence, comparison semantics and every built-in function.
Types#
KAL values are STRING, NUMBER, BOOLEAN, NULL, ARRAY or MAP (TYPE(v) returns exactly these spellings). Missing data reads as null β an out-of-range array index, an absent map key or an unset context field all yield null rather than an error.
Literals#
DECLARE count = 42; // NUMBER (integers and decimals)
DECLARE label = "hello"; // STRING - escapes: \n \r \t \" \' \\ \uXXXX
DECLARE flag = true; // BOOLEAN
DECLARE nothing = null; // NULL
DECLARE tags = ["news", "fun"]; // ARRAY
DECLARE scores = {"alice": 3}; // MAP
Escapes in strings: \n, \r, \t, \", \', \\ and \uXXXX. Literal line breaks inside a string are rejected.
Operators#
| Category | Operators | Notes |
|---|---|---|
| Arithmetic | + - * / % | / by zero is a runtime error; % by zero too |
| Concatenation | + | If either side is a string, + joins as strings |
| Comparison | < <= > >= | Numbers only |
| Equality | == != | Deep equality β maps and arrays compare by content |
| Identity | IS | Strict β two separately-built maps are never IS each other |
| Membership | IN / CONTAINS | Arrays (value), strings (substring), maps (key) |
| Prefix/suffix | STARTS_WITH / ENDS_WITH | Strings only |
| Logic | AND OR NOT (also && ` | |
| Assignment | = += -= *= /= %= | With SET |
Precedence, lowest to highest: OR β AND β comparisons & IN/CONTAINS β < <= > >= β + - β * / %. Parentheses override everything.
Member access, indexing, iteration sources#
user_info.name // MAP property
user_info.stats.messages // nested maps
scores["alice"] // MAP by key
tags[0] // ARRAY by index (out of range -> null)
LENGTH(tags) // ARRAY or MAP or STRING size
Built-in functions#
| Function | Signature | Returns |
|---|---|---|
LENGTH(v) | string / array / map | NUMBER |
LOWER(s) UPPER(s) TRIM(s) | string | STRING |
SUBSTRING(s, start[, len]) | string, numbers | STRING |
REPLACE(s, search, repl) | strings | STRING |
SPLIT(s, delim) | strings | ARRAY |
JOIN(arr, delim) | array, string | STRING |
MIN(a, b) MAX(a, b) | numbers | NUMBER |
ROUND(n[, decimals]) | number | NUMBER |
FLOOR(n) CEIL(n) ABS(n) | number | NUMBER |
RANDOM([min, max]) | numbers (inclusive) | NUMBER |
NOW() | β | NUMBER (epoch ms) |
DATE(v) TIME(v) | epoch number or string | STRING |
DURATION(ms) | number | STRING (human-readable) |
SECONDS_AGO(n) MINUTES_AGO(n) HOURS_AGO(n) DAYS_AGO(n) | epoch | NUMBER |
TYPE(v) | any | STRING |
EXISTS(v) NOT_EXISTS(v) | any | BOOLEAN |
EMPTY(v) NOT_EMPTY(v) | string / array / map | BOOLEAN |
LAST_ACTION() | β | MAP (previous action's result) |
UI_BUTTON UI_SELECT_MENU UI_OPTION UI_ACTION_ROW UI_CLONE_WITH | component builders | MAP β see Components |
A worked example#
KAL VERSION 2.0;
AUTOMATION text_tools {
WHEN COMMAND analyze (word AS STRING) {
DECLARE ts = NOW();
DECLARE stamp = DATE(ts);
DECLARE clean = TRIM(LOWER(word));
DECLARE parts = SPLIT(clean, " ");
DECLARE joined = JOIN(parts, "-");
DECLARE verdict = "unknown";
IF clean STARTS_WITH "kh" THEN {
SET verdict = "kharat-prefixed";
} END IF;
REPLY "[" + stamp + "] " + joined + " (" + ("" + LENGTH(parts)) + " parts, " + verdict + ")";
}
}
Truthiness#
IF, WHILE, AND/OR treat exactly these as false: null, false, 0, "" and NaN. Everything else β including empty arrays and empty maps β is true.