Operators
Operator Precedence (low to high)
Section titled “Operator Precedence (low to high)”pipe— Pipelinecoal— Nullish coalescingor— Logical ORand— Logical ANDbor— Bitwise ORbxor— Bitwise XORband— Bitwise ANDeq/neq/not eq/instanceof— Equality / Type checklt/gt/le(lt eq) /ge(gt eq) — Comparisonshl/shr/ushr— Bitwise shiftadd/sub— Addition / Subtractionmul/div/mod— Multiplication / Division / Modulopow— Exponentiation- Unary:
not/neg/bnot/typeof/void/await/delete/new/add\(prefix++) /sub\(prefix--) - Postfix:
.access /\.optional chaining /[args]call /[\expr]computed access /ascast /\add(postfix++) /\sub(postfix--) - Primary: literals, identifiers, brackets
Pipeline
Section titled “Pipeline”data pipe filterdata pipe filter pipe mapdata pipe transform[extra-arg]data pipe .method[arg]Compiles to:
filter(data)map(filter(data))transform(data, extra_arg)data.method(arg)Assignment
Section titled “Assignment”const x be 42let y be 10y be 20Compound Assignment
Section titled “Compound Assignment”Compound assignment operators combine an arithmetic operation with assignment:
x add be 1 -- x += 1x sub be 1 -- x -= 1x mul be 2 -- x *= 2x div be 2 -- x /= 2x mod be 3 -- x %= 3x pow be 2 -- x **= 2Bitwise compound assignments:
x band be 255 -- x &= 255x bor be 1 -- x |= 1x bxor be mask -- x ^= maskx shl be 2 -- x <<= 2x shr be 1 -- x >>= 1x ushr be 1 -- x >>>= 1Logical compound assignments:
x and be true -- x &&= truex or be false -- x ||= falsex coal be 0 -- x ??= 0Works with property and computed access:
obj.count add be 1 -- obj.count += 1arr[\i] mul be 2 -- arr[i] *= 2Arithmetic
Section titled “Arithmetic”a add b -- a + ba sub b -- a - ba mul b -- a * ba div b -- a / ba mod b -- a % ba pow b -- a ** bneg x -- -xBitwise
Section titled “Bitwise”a band b -- a & b (bitwise AND)a bor b -- a | b (bitwise OR)a bxor b -- a ^ b (bitwise XOR)bnot x -- ~x (bitwise NOT)a shl b -- a << b (left shift)a shr b -- a >> b (right shift)a ushr b -- a >>> b (unsigned right shift)Comparison
Section titled “Comparison”When the right side of eq is a type name (e.g., string, number, null, or a capitalized class name), it becomes a type check. Otherwise, it becomes a strict equality comparison (===).
For not-equal, use neq or not eq. For less-than-or-equal, both le and lt eq work. For greater-than-or-equal, both ge and gt eq work.
a eq b -- a === ba neq b -- a !== ba not eq b -- a !== b (alternative)a lt b -- a < ba gt b -- a > ba le b -- a <= ba lt eq b -- a <= b (alternative)a ge b -- a >= ba gt eq b -- a >= b (alternative)a eq string -- typeof a === "string" (type check)Array Ranges
Section titled “Array Ranges”Generate arrays from numeric ranges using .. (inclusive) and ... (exclusive):
const a be [0..5] -- [0, 1, 2, 3, 4, 5]const b be [0...5] -- [0, 1, 2, 3, 4]const c be [1..10] -- [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]const d be [1...10] -- [1, 2, 3, 4, 5, 6, 7, 8, 9]Slicing
Section titled “Slicing”Extract a portion of an array using \ prefix with .. (inclusive) or ... (exclusive) inside bracket access:
const numbers be [0, 1, 2, 3, 4, 5, 6]const middle be numbers[\2..5] -- [2, 3, 4, 5]const partial be numbers[\2...5] -- [2, 3, 4]Splicing
Section titled “Splicing”Replace a portion of an array by assigning to a slice:
numbers[\2..4] be [///a///; ///b///; ///c///]-- numbers is now [0, 1, "a", "b", "c", 5, 6]Computed Access
Section titled “Computed Access”Use \ inside brackets to access array elements or object properties by expression:
const val be arr[\i] -- arr[i]const item be obj[\key] -- obj[key]arr[\0] be ///new/// -- arr[0] = "new"The \ prefix distinguishes computed access from function calls: f[x] is a call, arr[\x] is property access.
Optional Chaining
Section titled “Optional Chaining”Use \. for optional chaining (JS ?.):
const name be user\.name -- user?.nameconst val be obj\.method[1; 2] -- obj?.method(1, 2)const deep be a\.b\.c -- a?.b?.cCompiles to:
const name = user?.name;const val = obj?.method(1, 2);const deep = a?.b?.c;Destructuring
Section titled “Destructuring”Extract values from arrays into variables:
const weather be [///Sunny///; ///Rainy///]const [today; tomorrow] be weather
-- Swap variables[today; tomorrow] be [tomorrow; today]Object destructuring
Section titled “Object destructuring”Use object[...] to destructure properties from an object:
const config be [host be ///localhost///, port be 8080]const object[host; port] be configCompiles to:
const config = { host: "localhost", port: 8080 };const { host, port } = config;Logical
Section titled “Logical”a and b -- a && ba or b -- a || bnot x -- !xNullish Coalescing
Section titled “Nullish Coalescing”The coal operator returns the right-hand side when the left-hand side is null or undefined:
a coal b -- a ?? ba coal b coal c -- a ?? b ?? cCompiles to:
a ?? b;a ?? b ?? c;This is different from or: or treats all falsy values (false, 0, "", null, undefined) as false, while coal only treats null and undefined as “empty”. Use coal when you want to preserve values like 0, false, or "".
const port be config.port coal 3000 -- uses 3000 only if port is null/undefinedconst name be user.name coal ///guest/// -- uses "guest" only if name is null/undefinedType Checks
Section titled “Type Checks”eq performs a type check when followed by a type name.
x eq string -- typeof x === "string"x eq null -- x === nullx eq MyClass -- x instanceof MyClassx instanceof Y -- x instanceof Ytypeof x -- typeof xvoid x -- void xIncrement / Decrement
Section titled “Increment / Decrement”Purus supports postfix and prefix increment/decrement using \ combined with add or sub:
| Purus | JS | Description |
|---|---|---|
x\add | x++ | Postfix increment |
x\sub | x-- | Postfix decrement |
add\x | ++x | Prefix increment |
sub\x | --x | Prefix decrement |
let i be 0i\add -- i++ (returns 0, then i becomes 1)add\i -- ++i (i becomes 2, returns 2)i\sub -- i-- (returns 2, then i becomes 1)sub\i -- --i (i becomes 0, returns 0)Compiles to:
let i = 0;i++; // returns 0, i becomes 1++i; // i becomes 2, returns 2i--; // returns 2, i becomes 1--i; // i becomes 0, returns 0