Control Flow & Patterns
Flame provides a robust set of control flow structures designed for both safety and readability.
Conditionals
Section titled “Conditionals”if / else if / else
Section titled “if / else if / else”Standard conditional branching:
let score = 85
if score >= 90 { print("Grade: A")} else if score >= 80 { print("Grade: B")} else { print("Grade: C")}if as an Expression
Section titled “if as an Expression”In Flame, if is not only a statement—it is also a first-class expression that produces a value! This allows you to directly assign the outcome of conditionals to variables, pass them to functions, return them, or interpolate them without needing mutable temporary variables:
Compact Single-Line Form
Section titled “Compact Single-Line Form”let b = 0let a = if b == 0 { 10 } else { 20 }
let connected = truelet status = if connected { "connected" } else { "offline" }Multiline Block Form
Section titled “Multiline Block Form”Blocks in Flame evaluate each statement sequentially, and the trailing expression yields the value of that branch:
let score = 85let grade = if score >= 90 { "A"} else if score >= 80 { "B"} else { "C"}
// Blocks can contain local statements before returning the final expressionlet config_timeout = if is_production { let base_seconds = 30 let buffer = 10 base_seconds + buffer} else { 5}In Expressions, Calls, & Interpolations
Section titled “In Expressions, Calls, & Interpolations”Because if is an expression, it can be passed anywhere expressions are valid:
println(if is_admin { "Welcome Admin" } else { "Access Denied" })
let message = $"Status: { if ready { 100 } else { 0 } }%"Compile-Time Type Checking & Safety
Section titled “Compile-Time Type Checking & Safety”The Flame typechecker statically enforces two critical safety guarantees:
-
Branch Type Compatibility: Every branch must produce compatible types. If branches yield conflicting types (for example,
Intin theifbranch andStringin theelsebranch), Flame raises a compile error:// ❌ Compile Error: incompatible branch types in if expression: expected 'Int', found 'String'let x = if ready { 10 } else { "not ready" } -
Exhaustive Branches: When
ifis used as an expression to produce a value, anelsebranch is strictly required so that every execution path yields a valid typed value:// ❌ Compile Error: if expression missing 'else' branchlet x = if ready { 10 }
Stored Boolean Conditions & One-Line Checks
Section titled “Stored Boolean Conditions & One-Line Checks”In Flame, conditional expressions are first-class and evaluate directly to Bool (true or false). You can capture one-line boolean checks directly into variables and store them for reuse across branching logic.
This is a clean, recommended idiom for hardware register bitmasking, sensor telemetry, and complex validation:
const FLAG_OVERTEMP: Int = 1 << 0 // 0x01 (Bit 0)const FLAG_OVERVOLTAGE: Int = 1 << 1 // 0x02 (Bit 1)
let register_value: Int = 0x03 // Both flags active
// One-line checks that evaluate to Bool and store in variableslet is_overtemp = (register_value & FLAG_OVERTEMP) != 0let is_overvoltage = (register_value & FLAG_OVERVOLTAGE) != 0
// Combine cleanly using keyword operators (and, or, not)if is_overtemp and is_overvoltage { print("[CRITICAL] Dual hardware thermal and electrical fault detected!")} else if is_overtemp { print("[WARNING] High temperature detected on thermal sensor.")} else if is_overvoltage { print("[WARNING] Electrical over-voltage detected.")}Why Stored Boolean Checks Are Recommended:
Section titled “Why Stored Boolean Checks Are Recommended:”- Self-Documenting Intent: Naming the condition (such as
is_overtemp) clarifies business and hardware logic without needing inline comments. - Single Evaluation: The bitwise or arithmetic expression is computed once and can be safely referenced across multiple branches.
- Direct Reusability: Stored boolean variables can be passed straight to assertions, logged in diagnostics, or returned from helper functions:
@Testfn main() { let payload = "Hello, World!" let checksum = &payload let expected = "Hello, World!" let is_valid = payload.len() > 0 and checksum == expected
println(assert(is_valid))}Pattern Matching (match)
Section titled “Pattern Matching (match)”Flame features powerful, expressive pattern matching with match:
let status_code = 200
match status_code { 200 => print("OK"), 404 => print("Not Found"), 500 => print("Internal Server Error"), _ => print("Unknown Status Code") // `_` acts as default fallback}Enum Destructuring & Blocks
Section titled “Enum Destructuring & Blocks”You can unpack data embedded inside Enums (like Result and Option) using tuple destructuring (value) and paths in your match arms. If your logic requires multiple statements, you can use { ... } blocks directly as the body of your match arm!
let opt = Option.Some(42)
match opt { Option.Some(value) => { let doubled = value * 2 print($"Found value: {doubled}") }, Option.None => print("No value found!")}
let result: Result<Int, Error> = divide(10, 2)
match result { Result.Ok(ans) => print($"Success: {ans}"), Result.Err(err) => { print("An error occurred!") print(err.message) }}Flame supports three distinct looping paradigms:
while Loops
Section titled “while Loops”Executes as long as the condition evaluates to true:
let mut count = 0while count < 5 { print($"Count: {count}") count = count + 1}Infinite Loops (loop)
Section titled “Infinite Loops (loop)”Creates an infinite loop, ideal for servers, game loops, or event dispatchers:
let mut ticks = 0loop { ticks = ticks + 1 if ticks > 10 { break // explicitly break out }}for .. in Iteration
Section titled “for .. in Iteration”Iterates over dynamic collections, ranges, or vectors:
let fruits = ["Apple", "Banana", "Orange"]
for fruit in fruits { print($"Fruit: {fruit}")}Scope Exit Cleanup (defer)
Section titled “Scope Exit Cleanup (defer)”The defer statement schedules a statement or block of code to run at the exact moment the enclosing function or scope exits.
import std.fs
fn process_log() { let file = fs.read("app.log") defer print("Finished processing file!") // Runs when process_log() returns
// ... parse log data ... if file.len() == 0 { return // defer still runs here! }
print("Log processed successfully.")}Loop Modifiers
Section titled “Loop Modifiers”break: Immediately terminates the innermost loop.continue: Skips the remaining statements in the current iteration and begins the next iteration.return: Exits the current function, optionally returning a value.
