Types
Calor has a simple type system with primitives, optionals, and results.
Code blocks on this reference page are declaration, expression, or body fragments, not complete files. The nullability guide includes complete checked examples.
Primitive Types
| Calor | Description | C# | Range |
|---|---|---|---|
i32 | 32-bit signed integer | int | -2^31 to 2^31-1 |
i64 | 64-bit signed integer | long | -2^63 to 2^63-1 |
f32 | 32-bit floating point | float | +/-3.4 x 10^38 |
f64 | 64-bit floating point | double | +/-1.8 x 10^308 |
str | String | string | UTF-16 text |
bool | Boolean | bool | true or false |
void | No value | void | (return type only) |
Usage in Declarations
Input Parameters and Return Types
Signature fragments (inside a module):
§F{f1:Count:pub} (i32:count) -> i32
§F{f2:Name:pub} (str:name) -> str
§F{f3:Price:pub} (f64:price, bool:active) -> void
Nullable Types (?T) and Runtime Options
?str is a nullable .NET string reference, not an Option<str>.
str and string are aliases; ?str, ?string, str?, and string?
are supported nullable spellings. A resolved ?User remains an ordinary
nullable object reference. Nullable value types such as ?i32 map to
.NET Nullable<T> (int?).
Signature fragments:
§F{f001:Find:pub} (str:key) -> ?str
§F{f002:Process:pub} (?i32:maybeValue) -> void
Use ordinary values or null with nullable references. Explicit Option<T>
instead represents Some/None using Calor's runtime option type. It is not
implicitly unwrapped into a reference or by ??.
Creating Option Values
Expression fragments for an explicit Option<T>:
§SM value // Some(value) - has a value
§NN // None - no value
See Nullability and .NET Interop for complete nullable-reference examples and the bounded support table. Calor 0.22 checks scalar strings, supported arrays and one-level string generic payloads, and identity-proven nominal reference receiving boundaries. It does not guarantee non-null values after arbitrary writes or validate constructor inputs.
Result Type (T!E)
Results represent computations that may fail.
Syntax
T!E // Result: either T (success) or E (error)
Examples
§F{f001:Divide:pub} (i32:a, i32:b) -> i32!str
§IF{if1} (== b 0)
§R §ERR "Division by zero"
§EL
§R §OK (/ a b)
Creating Result Values
§OK value // Ok(value) - success
§ERR "message" // Err(message) - failure
Common Patterns
Parse integer:
§F{f001:ParseInt:pub} (str:text) -> i32!str
// ...implementation
File read:
§F{f001:ReadFile:pub} (str:path) -> str!str
§E{fs:r}
// ...implementation
Generic Types
Generic types use angle bracket syntax inline.
Syntax
List<T> // List of T
Dictionary<K, V> // Dictionary with key K and value V
IEnumerable<T> // Enumerable of T
Func<T, U> // Function from T to U
Examples
Declaration fragments:
§F{f1:Numbers:pub} (List<i32>:numbers) -> void
§F{f2:Scores:pub} (Dictionary<str, i32>:scores) -> IEnumerable<str>
§FLD{HashSet<T>:_items:pri} // Generic field with type parameter T
Nested Generic Types
Generic types can be nested.
§F{f1:Data:pub} (Dictionary<str, List<i32>>:data) -> List<Tuple<str, i32>>
Type Parameters
When defining generic functions or classes, type parameters (like T, U) can be used as types.
§F{f001:First:pub}<T> (List<T>:items) -> T
§R items[0]
See Structure Tags - Generics for more on defining generic functions and classes.
Collection Types
Calor provides built-in syntax for creating and manipulating collections with type-safe operations.
List Creation
§LIST{name:elementType}
element1
element2
| Part | Description |
|---|---|
name | Variable name for the list |
elementType | Type of elements (i32, str, etc.) |
Example:
§LIST{numbers:i32}
1
2
3
Dictionary Creation
§DICT{name:keyType:valueType}
§KV key1 value1
§KV key2 value2
| Part | Description |
|---|---|
name | Variable name for the dictionary |
keyType | Type of keys |
valueType | Type of values |
§KV | Key-value pair entry |
Example:
§DICT{ages:str:i32}
§KV "alice" 30
§KV "bob" 25
HashSet Creation
§HSET{name:elementType}
element1
element2
Example:
§HSET{tags:str}
"urgent"
"review"
Collection Operations
| Operation | Syntax | Description |
|---|---|---|
| Add to list/set | §PUSH{coll} value | collection.Add(value) |
| Set dictionary entry | §PUT{dict} key value | dict[key] = value |
| Set list index | §SETIDX{list} idx value | list[index] = value |
| Insert at index | §C{list.Insert} §A idx §A val §/C | list.Insert(idx, val) |
| Remove element | §C{coll.Remove} §A val §/C | collection.Remove(val) |
| Clear collection | §C{coll.Clear} §/C | collection.Clear() |
Example:
§PUSH{numbers} 4 // numbers.Add(4)
§PUT{ages} "charlie" 35 // ages["charlie"] = 35
§SETIDX{numbers} 0 10 // numbers[0] = 10
Collection Queries
| Query | Syntax | Returns |
|---|---|---|
| Contains element | §HAS{coll} value | bool |
| Contains key | §HAS{dict} §KEY key | bool |
| Contains value | §HAS{dict} §VAL value | bool |
| Collection count | §CNT{coll} | i32 |
Example:
§IF §HAS{numbers} 5 → §P "Found 5"
§B{count} §CNT{ages}
Type Annotations in Contracts
Types matter in contracts for proper comparisons:
§F{f001:Clamp:pub} (i32:value, i32:min, i32:max) -> i32
§Q (<= min max) // Requires: min <= max
§S (>= result min) // Ensures: result >= min
§S (<= result max) // Ensures: result <= max
// ...
Type Compatibility
| Operation | Valid Types |
|---|---|
Arithmetic (+, -, *, /) | Numeric (i32, i64, f32, f64) |
Modulo (%) | Integer (i32, i64) |
Comparison (<, >, etc.) | Numeric, str |
Equality (==, !=) | Any matching types |
Logical (&&, ||) | bool |
Literals
| Type | Literal Examples |
|---|---|
i32 | 42, -17, 0 |
i64 | 42L, -17L |
f32 | 3.14f |
f64 | 3.14, 2.718 |
str | "hello", "world" |
bool | true, false |
Next
- Expressions - Operators and expressions