Expressions

Calor uses Lisp-style prefix notation for all operations. This eliminates operator precedence ambiguity.


Prefix Notation

Instead of infix a + b, Calor uses prefix (+ a b):

InfixCalor Prefix
a + b(+ a b)
a * b + c(+ (* a b) c)
a + b * c(+ a (* b c))
(a + b) * c(* (+ a b) c)

Arithmetic Operators

OperatorMeaningExample
+Addition(+ a b)
-Subtraction(- a b)
*Multiplication(* a b)
/Division(/ a b)
%Modulo(% a b)

Examples

Plain Text
(+ 1 2)           // 3
(- 10 3)          // 7
(* 4 5)           // 20
(/ 15 3)          // 5
(% 17 5)          // 2

Nested Expressions

Plain Text
// (1 + 2) * 3 = 9
(* (+ 1 2) 3)

// 1 + (2 * 3) = 7
(+ 1 (* 2 3))

// ((a + b) * c) - d
(- (* (+ a b) c) d)

Comparison Operators

OperatorMeaningExample
==Equal(== a b)
!=Not equal(!= a b)
<Less than(< a b)
<=Less or equal(<= a b)
>Greater than(> a b)
>=Greater or equal(>= a b)

Examples

Plain Text
(== x 0)          // x equals 0
(!= y "")         // y is not empty string
(< age 18)        // age less than 18
(>= score 70)     // score at least 70

Logical Operators

OperatorMeaningExample
&&Logical AND(&& a b)
||Logical OR(|| a b)
!Logical NOT(! a)

Examples

Plain Text
(&& (> x 0) (< x 100))      // x > 0 AND x < 100
(|| (== a 1) (== a 2))      // a == 1 OR a == 2
(! (== x 0))                // NOT (x == 0)

Complex Conditions

Plain Text
// (x > 0 && x < 100) || y == 0
(|| (&& (> x 0) (< x 100)) (== y 0))

// !(a == b && c == d)
(! (&& (== a b) (== c d)))

Using Expressions

In Return Statements

Plain Text
§R (+ a b)
§R (* (- x 1) 2)
§R (>= score 70)

In Bindings

Plain Text
§B{sum} (+ a b)
§B{product} (* x y)
§B{isValid} (&& (> x 0) (< x 100))

In Print Statements

Plain Text
§P (+ 1 2)          // prints 3
§P (* x x)          // prints x squared

In Conditions

Plain Text
§IF{if1} (> x 0) → §P "positive"
§EI (< x 0) → §P "negative"
§EL → §P "zero"
§/I{if1}

In Contracts

Plain Text
§Q (>= x 0)                      // Requires: x >= 0
§Q (!= divisor 0)                // Requires: divisor not zero
§S (>= result 0)                 // Ensures: result >= 0
§S (<= result (* x x))           // Ensures: result <= x^2

In Loop Bounds

Loop bounds can be expressions:

Plain Text
§L{for1:i:0:(- n 1):1}    // i from 0 to n-1
§L{for2:j:1:(* 2 n):2}    // j from 1 to 2n, step 2

Collection Expressions

Calor provides expressions for querying collections.

Contains Check (§HAS)

Check if a collection contains an element.

SyntaxDescriptionC# Equivalent
§HAS{coll} valueElement in list/setcoll.Contains(value)
§HAS{dict} §KEY keyKey in dictionarydict.ContainsKey(key)
§HAS{dict} §VAL valueValue in dictionarydict.ContainsValue(value)

Examples:

Plain Text
// Check if list contains element
§IF{if1} §HAS{numbers} 5
  §P "Found 5"
§/I{if1}

// Check if key exists in dictionary
§IF{if2} §HAS{ages} §KEY "alice"
  §P "Alice found"
§/I{if2}

// Use in binding
§B{hasItem} §HAS{inventory} "sword"

Collection Count (§CNT)

Get the number of elements in a collection.

SyntaxReturnsC# Equivalent
§CNT{coll}i32coll.Count

Examples:

Plain Text
// Get count
§B{size} §CNT{items}

// Use in condition
§IF{if1} (> §CNT{queue} 0)
  §P "Queue not empty"
§/I{if1}

// Use in loop bound
§L{for1:i:0:(- §CNT{list} 1):1}
  §P list[i]
§/L{for1}

Using Collection Expressions in Contracts

Plain Text
§F{f001:ProcessItems:pub}
  §I{List<i32>:items}
  §O{i32}
  §Q (> §CNT{items} 0)           // Requires: items not empty
  §S (>= result 0)
  // ...
§/F{f001}

Why Prefix Notation?

1. No Precedence Ambiguity

Infix:

JavaScript
a + b * c    // Is this (a+b)*c or a+(b*c)?

Calor:

Plain Text
(+ a (* b c))    // Clearly a + (b * c)
(* (+ a b) c)    // Clearly (a + b) * c

2. Easy AST Manipulation

The structure (op arg1 arg2) directly represents the AST node.

3. Uniform Syntax

Every operation follows the same pattern: (operator arguments...)


Common Patterns

FizzBuzz Check

Plain Text
(== (% i 15) 0)    // i divisible by 15
(== (% i 3) 0)     // i divisible by 3
(== (% i 5) 0)     // i divisible by 5

Range Check

Plain Text
(&& (>= x min) (<= x max))    // min <= x <= max

Null Check

Plain Text
(!= value null)    // value is not null

Equality with Multiple Values

Plain Text
(|| (== x 1) (|| (== x 2) (== x 3)))    // x is 1, 2, or 3

Next