Nesting & Termination
OPEN and CLOSE define blocks in OcaltQL. They are used by IF, WHILE, LOOP, SWITCH, and NEW OPERATION. Blocks can nest to any depth. Variable scope is shared across control-flow blocks — variables set inside an IF, WHILE, LOOP, or SWITCH are available outside it. A NEW OPERATION body is the one exception — it runs in its own isolated frame, covered below.
Inline References
Square brackets [ and ] mark an inline reference — an expression that resolves to a value at the point where a value is expected. Anything that would normally require an intermediate variable and a separate AFTER step can be written inline instead. Inline references are nestable: the innermost resolves first, then outward.
EMIT [CALCULATE 1 + 1]
(* Output: 2 *)
NEW OPERATION square WITH ?n
OPEN
RETURN [CALCULATE ?n * ?n]
CLOSE
AFTER EMIT [CALCULATE [RUN square WITH 4] + [RUN square WITH 3]]
(* [RUN square WITH 4] resolves to 16 *)
(* [RUN square WITH 3] resolves to 9 *)
(* Output: 25 *)
OPEN and CLOSE
Every block-level construct in OcaltQL uses OPEN and CLOSE as its delimiters. There are no curly braces. There are no indentation rules. OPEN begins the block and CLOSE ends it.
IF ?a IS GREATER THAN 10
OPEN
EMIT "big"
CLOSE
NUMBER 0 SET ?i
AFTER WHILE ?i IS LESS THAN 5
OPEN
EMIT ?i
AFTER CALCULATE ?i + 1 SET ?i
CLOSE
LOOP 1 TO 5 SET ?i
OPEN
EMIT ?i
CLOSE
NEW OPERATION myfunc WITH ?x
OPEN
CALCULATE ?x * 2 SET ?result
AFTER RETURN ?result
CLOSE
Nested Blocks
Blocks nest to any depth. Any block-level construct can appear inside any other, with the exception that NEW OPERATION cannot contain another NEW OPERATION.
LOOP 1 TO 10 SET ?i
OPEN
IF ?i IS GREATER THAN 5
OPEN
EMIT "big: " & ?i
CLOSE
OR
OPEN
EMIT "small: " & ?i
CLOSE
CLOSE
IF ?flag IS SET
OPEN
LOOP 1 TO 3 SET ?j
OPEN
EMIT ?j
CLOSE
CLOSE
Variable Scope
OcaltQL does not have block-level variable isolation for control-flow blocks. Variables set inside an IF, WHILE, LOOP, or SWITCH are available outside it. Variables from the outer scope are accessible inside any of these blocks. Scope is flat across the entire script execution — with one exception: a NEW OPERATION body runs in its own isolated frame. Parameters and any variable set inside the operation are local to that call and disappear when it ends; only a RETURN value escapes. To write a value from inside an operation back out to the wider execution, use !GLOBAL('key') — see Header & Globals and Operations & Return.
NEW OPERATION set_local
OPEN
STRING "only visible in here" SET ?local
CLOSE
AFTER RUN set_local
AFTER EMIT ?local
(* Output: null — ?local was set inside the operation's own frame and does not escape it *)
IF true
OPEN
STRING "inside" SET ?inner
CLOSE
AFTER EMIT ?inner
(* Output: "inside" — variable set inside a block is accessible outside it *)
STRING "outer" SET ?out
AFTER IF true
OPEN
EMIT ?out
CLOSE
(* Output: "outer" *)
SWITCH
SWITCH matches a variable against CASE values. Each CASE falls through to the next unless terminated with BREAK. DEFAULT is the fallback when no case matches.
SWITCH ?status
OPEN
CASE "pending"
EMIT "Order is pending"
BREAK
CASE "shipped"
EMIT "Order is shipped"
BREAK
CASE "delivered"
EMIT "Order is delivered"
BREAK
DEFAULT
EMIT "Unknown status"
BREAK
CLOSE
SWITCH ?grade
OPEN
CASE "A"
CASE "B"
EMIT "Passing"
BREAK
CASE "C"
EMIT "Barely passing"
BREAK
CASE "D"
CASE "F"
EMIT "Failing"
BREAK
DEFAULT
EMIT "Invalid"
BREAK
CLOSE
(* "A" and "B" both fall through to "Passing" *)
(* "D" and "F" both fall through to "Failing" *)
NEW OPERATION get_color WITH ?status
OPEN
SWITCH ?status
OPEN
CASE "pending"
RETURN "yellow"
BREAK
CASE "shipped"
RETURN "blue"
BREAK
CASE "delivered"
RETURN "green"
BREAK
DEFAULT
RETURN "gray"
BREAK
CLOSE
CLOSE
AFTER RUN get_color WITH "shipped" SET ?color
AFTER EMIT ?color
(* Output: blue *)
SWITCH on Multivariables
When SWITCH operates on a multivariable, each branch of the multivariable is evaluated independently against the cases in parallel. The result of each branch follows the same multivariable rules — the output is itself a multivariable if SET is used inside the cases.
FETCH "https://api1.com/data" SET ?response AND FETCH "https://api2.com/data" SET ?response
AFTER WAIT FOR ?response
AFTER SWITCH ?response
OPEN
CASE "success"
STRING "won" SET ?result
BREAK
CASE "failed"
STRING "lost" SET ?result
BREAK
DEFAULT
STRING "unknown" SET ?result
BREAK
CLOSE
AFTER COLLAPSE ?result SET ?all
AFTER FOREACH ?all SET ?item
OPEN
EMIT ?item
CLOSE
Termination
OcaltQL has four termination controls. Each operates at a different level of the execution stack.
NEW OPERATION early WITH ?a
OPEN
IF ?a IS EQUAL TO 0
OPEN
RETURN "zero"
(* Ends operation here *)
CLOSE
AFTER EMIT "non-zero"
CLOSE
RUN early WITH 0 SET ?r
AFTER EMIT ?r
(* Output: zero *)
NEW OPERATION early WITH ?a
OPEN
IF ?a IS EQUAL TO 0
OPEN
RETURN "zero"
CLOSE
AFTER EMIT "non-zero"
CLOSE
AFTER RUN early WITH 5
(* Output: non-zero *)
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 — exits before 5 *)
LOOP 1 TO 5 SET ?i
OPEN
IF ?i IS EQUAL TO 3
OPEN
CONTINUE
CLOSE
AFTER EMIT ?i
CLOSE
(* Output: 1 2 4 5 — skips 3 *)
EMIT "step 1"
AFTER EXIT
AFTER EMIT "never reached"
(* Script ends at EXIT *)
EXIT 404
(* Sets HTTP response status to 404 and ends script *)
RETURN — ends the current operation or script, optionally with a value.BREAK — exits the current loop or SWITCH case.CONTINUE — skips to the next loop iteration.EXIT — terminates the entire script, optionally with an HTTP status code.