THE JOA LANGUAGE

Operators

Use arithmetic, comparisons, logical operators, membership tests, keyword matching, and operator precedence in Joa.

Arithmetic

Operator Operation Example Result
+ Addition 3 + 2 5
- Subtraction 10 - 4 6
* Multiplication 3 * 4 12
/ Division 7 / 2 3
% Modulo 10 % 3 1
** Exponentiation 2 ** 10 1024.0

Integer arithmetic preserves the Integer type when both operands are integers. Any float operand promotes the result to Float.

Division between two integers truncates toward zero: 7 / 2 is 3. Use a float operand for fractional division: 7.0 / 2 is 3.5. The interpreter performs arithmetic through floating-point conversion, so very large integers can lose precision even though Integer values are stored as signed 64-bit numbers.

** (power) always returns Float, even for integer operands.

Division and modulo by zero raise a Runtime Error.

Power Operator Associativity

** is right-associative: 2 ** 3 ** 2 is evaluated as 2 ** (3 ** 2) = 2 ** 9 = 512.0.

print(4 ** 2)       // 16.0
print(2 ** 3 ** 2)  // 512.0  (right-associative)

String Concatenation

+ concatenates when either operand is a String. The other operand is automatically converted to its string representation.

let msg = "Port: " + 8080     // "Port: 8080"
let info = str(99) + "% load" // "99% load"

Comparison

Operator Meaning
== Equal
!= Not equal
< Less than
<= Less than or equal
> Greater than
>= Greater than or equal

Numeric comparisons accept both Integer and Float. Equality compares numeric values across those two types and supports null, String, Bool, and IP. Different nonnumeric types compare unequal. Lists, maps, subnets, functions, and agents have no structural or identity equality in the current interpreter: == returns false for those values, even when comparing a value with itself. List membership and contains() use these same equality rules.

Ordering comparisons (<, <=, >, >=) also work on String values (lexicographic order).

Logical

Operator Meaning Short-circuits
and Logical AND Yes — stops at first false
or Logical OR Yes — stops at first true
not Logical NOT N/A
if active and load < 90 {
    print("All good")
}

if error or timeout {
    print("Something went wrong")
}

if not connected {
    print("Offline")
}

Membership — in / not in

Tests whether a value is contained in a list, a key exists in a map, a substring exists in a string, or an IP address is within a subnet.

// List membership
if "admin" in roles {
    print("Access granted")
}

// Map key membership
let config = {host: "localhost", port: 8080}
if "host" in config {
    print("host is set")
}

// Substring check
if "error" in log_line {
    print("Error found in log")
}

// IP-in-subnet (native)
if client_ip in 192.168.1.0/24 {
    print("Local client")
}

// Negated membership
if client_ip not in trusted_range {
    quarantine(client_ip)
}

Keyword Match — ~

Both operands must be strings. The runtime lowercases both strings, splits the right operand on whitespace, and counts how many right-hand words occur as substrings in the left operand. It returns true when the count is at least max(1, floor(word_count / 2)). Punctuation is not removed; repeated words are counted separately. An empty right operand returns false.

print("password attack" ~ "password security threat") // true
print("leaked credentials" ~ "password security threat") // false

This is a keyword heuristic. It does not understand intent or call an AI model.

Operator Precedence

From highest to lowest:

Level Operators
1 - (unary negation)
2 ** (right-associative)
3 * / %
4 + -
5 == != < <= > >= ~ in not in
6 not
7 and
8 or

Use parentheses to override precedence:

let result = (a + b) * c