Language Policy

Operators & Expressions

Canonical grammar, semantics, constraints, and deferred boundaries for Operators & Expressions.

Topaz fixes precedence, associativity, numeric domains, comparison eligibility, short-circuiting, and fault behavior so formatting or backend choice cannot change an expression.

Policy

Precedence runs from postfix calls/index/member/optional access/result propagation, through right-associative **, unary + - !, multiplicative and additive operators, ranges, comparisons and in, &&, ||, ??, SPEC-level composition >>, then left-associative pipeline |>. Assignment forms are statements and do not join this table.

Specified behavior

int is signed 64-bit two’s-complement: division truncates toward zero, remainder follows the dividend sign, overflow faults, and integer exponentiation rejects negative exponents. float is IEEE-754 binary64, including infinity and NaN behavior. Numeric binary operands stay in one domain; there is no implicit int/float conversion. && and || short-circuit left to right, and + concatenates only two strings or two same-domain numbers.

Constraints and loud decline

Equality is available only for comparable types; functions, resources, templates, Map, and Set are not comparable. Nominal equality preserves enum/record/newtype identity before inspecting payloads. Integer division by zero, dynamic overflow, and a dynamic negative integer exponent fault; their const-expression equivalents are static errors. ++, --, **=, bitwise ~, and general use of by are rejected.

Deferred boundary

Implicit numeric coercion, floating remainder as an operator, general bitwise operators, operator overloading, and user-defined operators are outside the language. >> is specified but excluded by the public-docs profile, so canonical examples use named functions or |>.

Worked example

TOPAZ
function score(base: int, bonus: int) -> int {
    let doubled = base * 2
    if bonus > 0 { doubled + bonus } else { doubled }
}

let result = score(20, 2)
print("{result}")