Conditions & Loops

OcaltQL has no ELSE keyword. Fallback logic uses OR. Chained conditions use OR IF. Compound conditions use AND and OR inline between full condition phrases. Loops use WHILE and LOOP.

IF

The condition follows IF. The body is wrapped in OPEN and CLOSE. If the condition is false, execution falls to the OR block if one is present.

Basic IF
IF ?a IS EQUAL TO ?b
OPEN
  EMIT "Equal"
CLOSE
IF with OR Fallback
IF ?a IS GREATER THAN 10
OPEN
  EMIT "Big"
CLOSE
OR
OPEN
  EMIT "Small"
CLOSE
OR IF Chain
IF ?a IS EQUAL TO 1
OPEN
  EMIT "One"
CLOSE
OR IF ?a IS EQUAL TO 2
OPEN
  EMIT "Two"
CLOSE
OR IF ?a IS EQUAL TO 3
OPEN
  EMIT "Three"
CLOSE
OR
OPEN
  EMIT "Other"
CLOSE

Comparison Operators

All comparison operators are multi-word natural language phrases. IS and ARE are interchangeable — ARE is used conventionally with arrays and objects.

Full Operator Reference
IF ?a IS EQUAL TO ?b
AFTER IF ?a IS IDENTICAL TO ?b
AFTER IF ?a IS GREATER THAN 10
AFTER IF ?a IS LESS THAN 10
AFTER IF ?a IS GREATER THAN OR EQUAL TO 10
AFTER IF ?a IS LESS THAN OR EQUAL TO 10
AFTER IF ?a IS NOT EQUAL TO ?b
AFTER IF ?a IS NOT IDENTICAL TO ?b
AFTER IF ?text CONTAINS "hello"
AFTER IF ?var IS SET
AFTER IF ?var IS EMPTY
AFTER IF ?var IS NOT EMPTY
AFTER IF ?var IS NULL
AFTER IF ?var IS NOT NULL

Compound Conditions

AND and OR connect full condition phrases inline inside an IF or WHILE. These are not chain keywords here — they are logical operators between conditions. Chaining is virtually unlimited.

Context matters. AND and OR between two full condition phrases inside an IF are logical operators. AND and OR between two statements outside a condition are chain keywords. The parser distinguishes by position.
Precedence and short-circuiting. Compound conditions follow the same precedence as PHP's && / ||AND binds tighter than OR. IF ?a IS ... AND ?b IS ... OR ?c IS ... evaluates as (?a IS ... AND ?b IS ...) OR (?c IS ...). Evaluation is left to right and short-circuits — an AND chain stops at the first false condition, an OR chain stops at the first true one; conditions after that point are not evaluated.
AND — Both Must Be True
IF ?a IS GREATER THAN 10 AND ?b IS EQUAL TO ?somevalue
OPEN
  EMIT "Both true"
CLOSE
OR — Either Must Be True
IF ?a IS GREATER THAN 10 OR ?b IS EQUAL TO ?somevalue
OPEN
  EMIT "At least one true"
CLOSE
Mixed AND / OR — Example 1
IF ?a IS IDENTICAL TO "this" AND ?a IS NOT EQUAL TO ?x OR ?b IS GREATER THAN 44
(* Groups as: (?a IS IDENTICAL TO "this" AND ?a IS NOT EQUAL TO ?x) OR ?b IS GREATER THAN 44 *)
OPEN
  EMIT "Complex condition met"
CLOSE
Mixed AND / OR — Example 2
IF ?a IS GREATER THAN OR EQUAL TO 10 AND ?b IS LESS THAN OR EQUAL TO 20
(* The "OR" inside "GREATER THAN OR EQUAL TO" and "LESS THAN OR EQUAL TO" is part of the
   operator phrase itself, not a logical connector. This is a single AND:
   (?a >= 10) AND (?b <= 20) *)
OPEN
  EMIT "In range"
CLOSE
Mixed AND / OR — Example 3
IF ?x IS GREATER THAN 0 AND ?x IS LESS THAN 100 OR ?y IS EQUAL TO "special" AND ?z IS SET OR ?flag IS EMPTY
(* Groups as: (?x > 0 AND ?x < 100) OR (?y IS EQUAL TO "special" AND ?z IS SET) OR (?flag IS EMPTY) *)
OPEN
  EMIT "Very complex condition"
CLOSE

Array & Object Conditions — ARE and SOME

IF ?arr ARE checks that every item in the array or object matches the condition. IF SOME ?arr ARE checks that at least one item matches. Both work with objects as well — checking property values.

ARE — All Items Match
IF ?arr ARE EQUAL TO "target"
OPEN
  EMIT "All match"
CLOSE
SOME — At Least One Matches
IF SOME ?arr ARE EQUAL TO "target"
OPEN
  EMIT "Found at least one"
CLOSE
Compound Array Conditions — Example 1
IF SOME ?arr ARE GREATER THAN 10 AND SOME ?arr ARE LESS THAN 100
OPEN
  EMIT "Has values in range"
CLOSE
Compound Array Conditions — Example 2
IF ?arr ARE EQUAL TO "ok" OR ?obj ARE EMPTY
OPEN
  EMIT "Either all ok or object empty"
CLOSE
Compound Array Conditions — Example 3
IF SOME ?obj ARE EQUAL TO "admin"
OPEN
  EMIT "At least one admin role"
CLOSE
Compound Array Conditions — Example 4
IF SOME ?arr ARE EQUAL TO "error" AND ?status IS EQUAL TO "active" OR SOME ?obj ARE NULL
OPEN
  EMIT "Complex match"
CLOSE
WHILE SOME
WHILE SOME ?arr ARE GREATER THAN 0
OPEN
  EMIT "Still has positives"
CLOSE

!THIS — Runtime Context

!THIS() accesses the current execution context from inside a nest. It is only valid inside an OPEN...CLOSE block.

!THIS('state')
IF ?a IS GREATER THAN 10
OPEN
  EMIT !THIS('state')
  (* Output: true — we are inside the nest because the condition was true *)
CLOSE
!THIS('some') — Matching Keys
IF SOME ?arr ARE EQUAL TO "target"
OPEN
  EMIT !THIS('some')(0)       (* first matching index *)
  AFTER COUNT !THIS('some') SET ?total
  AFTER EMIT ?total            (* how many matched *)
CLOSE
!THIS('some') — Additive with AND SOME
(* Keys from both conditions combined, may have duplicates *)
IF SOME ?arr ARE GREATER THAN 10 AND SOME ?arr ARE LESS THAN 100
OPEN
  EMIT !THIS('some')
CLOSE
!THIS('some') — Additive with OR SOME
(* All keys that matched either condition *)
IF SOME ?arr ARE EQUAL TO "error" OR SOME ?arr ARE EQUAL TO "warn"
OPEN
  EMIT !THIS('some')
CLOSE
!THIS('some') — Empty on No Match
IF SOME ?arr ARE EQUAL TO "zulu"
OPEN
  EMIT "Found"
CLOSE
OR
OPEN
  EMIT !THIS('some')   (* empty array — no matches *)
CLOSE
!THIS('some') with Object
IF SOME ?obj ARE EQUAL TO "admin"
OPEN
  EMIT "Admin keys: " & [JOIN !THIS('some') WITH ", "]
CLOSE

WHILE

WHILE repeats the body for as long as the condition remains true. The condition is evaluated before each iteration. Compound conditions work identically to IF.

Basic WHILE
NUMBER 0 SET ?i
AFTER WHILE ?i IS LESS THAN 5
OPEN
  EMIT ?i
  AFTER CALCULATE ?i + 1 SET ?i
CLOSE
WHILE with Compound Condition
NUMBER 0 SET ?i
AFTER NUMBER 10 SET ?limit
AFTER WHILE ?i IS LESS THAN ?limit AND ?i IS NOT EQUAL TO 3
OPEN
  EMIT ?i
  AFTER CALCULATE ?i + 1 SET ?i
CLOSE

LOOP

LOOP iterates over a numeric range. SET ?i is the loop variable, available inside the body. An optional STEP controls the increment. Negative steps count downward.

Basic LOOP
LOOP 1 TO 5 SET ?i
OPEN
  EMIT ?i
CLOSE
LOOP with STEP
LOOP 0 TO 10 STEP 2 SET ?i
OPEN
  EMIT ?i
CLOSE
Descending LOOP
LOOP 10 TO 1 STEP -1 SET ?i
OPEN
  EMIT ?i
CLOSE

BREAK and CONTINUE

BREAK exits the current loop immediately. CONTINUE skips the remainder of the current iteration and moves to the next. Both are only valid inside a loop body.

BREAK — Exit Early
LOOP 1 TO 10 SET ?i
OPEN
  IF ?i IS EQUAL TO 5
  OPEN
    BREAK
  CLOSE
  AFTER EMIT ?i
CLOSE
(* Output: 1 2 3 4 — stops before 5 *)
CONTINUE — Skip Iteration
LOOP 1 TO 10 SET ?i
OPEN
  IF ?i IS EQUAL TO 5
  OPEN
    CONTINUE
  CLOSE
  AFTER EMIT ?i
CLOSE
(* Output: 1 2 3 4 6 7 8 9 10 — skips 5 *)
There is no ELSE in OcaltQL. Use OR as the fallback block and OR IF for chained conditions. The runtime constructs the equivalent Rust if / else if / else at execution level.