v0.22.0—Bounded nullability checks and practical .NET migration guidance.See what's new

Documentation

Control Flow

Calor provides loops and conditionals with explicit structure.


Loops

For Loop Syntax

Calor
§L{id:var:from:to:step}
  // body
PartDescription
idUnique loop identifier
varLoop variable name
fromStarting value (inclusive)
toEnding value (inclusive)
stepIncrement per iteration

Examples

Count 1 to 10:

Calor
§L{for1:i:1:10:1}
  §P i

Count down:

Calor
§L{for1:i:10:1:-1}
  §P i

Count by 2s:

Calor
§L{for1:i:0:100:2}
  §P i

Using variable bounds:

Calor
§L{for1:i:1:n:1}
  §P i

Using expressions:

Calor
§L{for1:i:0:(- n 1):1}
  §P i

While Loop Syntax

Calor
§WH{id} condition
  // body
PartDescription
idUnique loop identifier
conditionBoolean expression evaluated before each iteration

While Loop Examples

Simple countdown:

Calor
§B{i} 10
§WH{while1} (> i 0)
  §P i
  §ASSIGN i (- i 1)

Read until done:

Calor
§B{running} true
§WH{while1} running
  §B{input} §C{Console.ReadLine} §/C
  §IF{if1} (== input "quit")
    §ASSIGN running false

Do-While Loop Syntax

Calor
§DO{id}
  // body (executes at least once)
PartDescription
idUnique loop identifier
conditionBoolean expression evaluated after each iteration

The condition is placed at the end to match the semantics: the body always executes at least once, then the condition is checked.

Do-While Loop Examples

Execute at least once:

Calor
§B{i} 0
§DO{do1}
  §P i
  §ASSIGN i (+ i 1)

Menu loop (always show menu first):

Calor
§B{choice} 0
§DO{do1}
  §P "1. Option A"
  §P "2. Option B"
  §P "3. Exit"
  §B{choice} §C{ReadChoice} §/C

Retry until success:

Calor
§B{success} false
§DO{do1}
  §B{success} §C{TryOperation} §/C

Dictionary Iteration

Use §EACHKV to iterate over key-value pairs in a dictionary.

Syntax

Calor
§EACHKV{id:keyVar:valueVar} dictName
  // body uses keyVar and valueVar
PartDescription
idUnique loop identifier
keyVarVariable name for the current key
valueVarVariable name for the current value
dictNameName of the dictionary to iterate

Examples

Print all entries:

Calor
§DICT{ages:str:i32}
  §KV "alice" 30
  §KV "bob" 25

§EACHKV{e1:name:age} ages
  §P name
  §P age

Sum all values:

Calor
§B{total} 0
§EACHKV{e1:k:v} scores
  §ASSIGN total (+ total v)

Conditional processing:

Calor
§EACHKV{e1:key:val} data
  §IF{if1} (> val 100)
    §P key

Comparison with §FOREACH

Loop TypeUse Case
§L{id:var:from:to:step}Numeric ranges
§FOREACH{id:var} collectionLists, arrays, sets
§EACHKV{id:k:v} dictDictionaries (key-value pairs)

Conditionals

Single Line (Arrow Syntax)

For simple single-action branches:

Calor
§IF{id} condition → action
§EI condition → action
§EL → action

Multi-Line (Block Syntax)

For complex branches:

Calor
§IF{id} condition
  // multiple statements
§EI condition
  // multiple statements
§EL
  // multiple statements

Parts

PartDescription
§IF condIf statement (block body indents below)
conditionBoolean expression
→Arrow separator (single-line inline form)
§EIElse-if (optional, can repeat) at same column as §IF
§ELElse (optional, at most one) at same column as §IF
§IF{id} condExplicit ID form (optional, for tooling references)

Conditional Examples

Simple If

Calor
§IF{if1} (> x 0) → §P "positive"

If-Else

Calor
§IF{if1} (> x 0)
  §P "positive"
§EL
  §P "not positive"

If-ElseIf-Else

Calor
§IF{if1} (> x 0)
  §P "positive"
§EI (< x 0)
  §P "negative"
§EL
  §P "zero"

Single Line with Multiple Branches

Calor
§IF{if1} (== (% i 15) 0) → §P "FizzBuzz"
§EI (== (% i 3) 0) → §P "Fizz"
§EI (== (% i 5) 0) → §P "Buzz"
§EL → §P i

Nested Conditionals

Calor
§IF{if1} (> x 0)
  §IF{if2} (< x 100)
    §P "between 0 and 100"
  §EL
    §P "100 or greater"

FizzBuzz Complete Example

Calor
§M{m001:FizzBuzz}
  §F{f001:Main:pub}
    §O{void}
    §E{cw}
    §L{for1:i:1:100:1}
      §IF{if1} (== (% i 15) 0) → §P "FizzBuzz"
      §EI (== (% i 3) 0) → §P "Fizz"
      §EI (== (% i 5) 0) → §P "Buzz"
      §EL → §P i

Loop with Conditional

Calor
§M{m001:Example}
  §F{f001:PrintEvens:pub}
    §I{i32:n}
    §O{void}
    §E{cw}
    §Q (> n 0)
    §L{for1:i:1:n:1}
      §IF{if1} (== (% i 2) 0)
        §P i

Early Return

Use conditionals with return for early exit:

Calor
§F{f001:Factorial:pub}
  §I{i32:n}
  §O{i32}
  §Q (>= n 0)
  §IF{if1} (<= n 1) → §R 1
  §EL → §R (* n §C{Factorial} §A (- n 1) §/C)

Pattern Matching

Pattern matching provides concise multi-way branching with C# switch expression semantics.

Switch Expression Syntax

Calor
§W{id} expression
  §K pattern1 → result1
  §K pattern2 → result2
  §K _ → default
PartDescription
§W exprSwitch expression (cases indent below)
expressionValue to match against
§KCase keyword (indented under §W)
patternPattern to match
→Arrow to result (single expression)
_Wildcard (matches anything)
§W{id} exprExplicit ID form (optional)

Literal Patterns

Match exact values:

Calor
§B{day} §W{sw1} dayNum
  §K 0 → "Sunday"
  §K 1 → "Monday"
  §K 2 → "Tuesday"
  §K _ → "Other"

Relational Patterns (§PREL)

Match value ranges using relational operators:

SyntaxMeaningC# Equivalent
§PREL{gte} valueGreater than or equal>= value
§PREL{gt} valueGreater than> value
§PREL{lte} valueLess than or equal<= value
§PREL{lt} valueLess than< value

Example - Grade calculation:

Calor
§B{grade} §W{sw1} score
  §K §PREL{gte} 90 → "A"
  §K §PREL{gte} 80 → "B"
  §K §PREL{gte} 70 → "C"
  §K §PREL{gte} 60 → "D"
  §K _ → "F"

Variable Patterns with Guards (§VAR, §WHEN)

Capture the matched value and add conditions:

Calor
§B{desc} §W{sw1} value
  §K §VAR{n} §WHEN (> n 100) → "large positive"
  §K §VAR{n} §WHEN (> n 0) → "small positive"
  §K 0 → "zero"
  §K §VAR{n} §WHEN (> n -100) → "small negative"
  §K _ → "large negative"
PartDescription
§VAR{name}Captures value into variable name
§WHEN conditionGuard condition (pattern matches only if true)

Option Patterns (§SM, §NN)

Match Option types:

Calor
§R §W{sw1} maybeValue
  §K §SM §VAR{v} → v        // Some(v) - extract value
  §K §NN → 0                 // None - default

Result Patterns (§OK, §ERR)

Match Result types:

Calor
§R §W{sw1} result
  §K §OK §VAR{v} → (+ "Success: " v)
  §K §ERR §VAR{e} → (+ "Error: " e)

Block Syntax

For cases with multiple statements, use block syntax:

Calor
§W{sw1} x
  §K 1 → "one"              // Arrow syntax (single expression)
  §K 2
    §P "matched two"         // Block syntax (multiple statements)
    §R "two"
  §K _ → "other"

The next case dedents to the §K column; no case closer is written.

Complete Example

Calor
§M{m001:HttpStatus}
  §F{f001:GetStatusMessage:pub}
    §I{i32:code}
    §O{str}
    §R §W{sw1} code
      §K 200 → "OK"
      §K 201 → "Created"
      §K 400 → "Bad Request"
      §K 404 → "Not Found"
      §K 500 → "Server Error"
      §K _ → "Unknown Status"

Why Explicit Loop IDs?

  1. Precise targeting - "Modify loop for1" is unambiguous
  2. Verification - Compiler uses indentation to determine loop boundaries
  3. Agent-friendly - Easy to identify loop boundaries
  4. Refactoring safe - IDs survive code movement

Why Arrow Syntax?

The arrow → provides:

  1. Single-line clarity - §IF cond → action is compact
  2. Readable flow - Condition "leads to" action
  3. Consistent pattern - Same syntax for if, elseif, else

Next

  • Contracts - Preconditions and postconditions