Skip to main content

Chapter 5

Playing with conditional​

What if today was raining? maybe you using jacket or umbrella, but, what if today are sunny?, you maybe wearing short pants or using sunglasses. We can play it with conditional statement.

If Statement​

The if statement is a conditional statement that executes code based on a boolean condition.

Syntax​

if (condition) {
// then branch - executed when condition is true
}

Basic If Statement​

var today_raining: bool = false;

if (today_raining) {
std::print("wear jacket or use umbrella");
}

If-Else Statement​

var today_raining: bool = false;

if (today_raining) {
std::print("wear jacket or use umbrella");
} else {
std::print("use sunglasses");
}

If-Else-If Chain​

For multiple conditions, use else-if:

var score: int32 = 85;

if (score >= 90) {
std::print("Grade: A");
} else if (score >= 80) {
std::print("Grade: B");
} else if (score >= 70) {
std::print("Grade: C");
} else {
std::print("Grade: F");
}

Nested If Statements​

You can nest if statements inside each other:

var age: int32 = 25;
var has_license: bool = true;

if (age >= 18) {
if (has_license) {
std::print("Can drive");
} else {
std::print("Need a license");
}
} else {
std::print("Too young to drive");
}

In XVR, if can be used as an expression that returns a value. This is similar to ternary-like if expressions.

Basic Expression If​

var x: int32 = 10;
var result: int32 = if (x > 5) { 100 } else { 0 };
std::print("{}", result); // Output: 100

With Else-If Chains​

var score: int32 = 85;
var grade: string = if (score >= 90) {
"A"
} else if (score >= 80) {
"B"
} else if (score >= 70) {
"C"
} else {
"F"
};
std::print(grade); // Output: B

Important Notes​

  1. Type annotation required: When using if as an expression, the variable must have an explicit type annotation
  2. All branches must have values: In expression form, every branch must return a value of compatible type
// This works
var x: int32 = if (condition) { 1 } else { 2 };

// This will cause an error - type annotation required
var x = if (condition) { 1 } else { 2 }; // ERROR

Conditions​

Conditions in if statements must be boolean (bool). The compiler will report an error if you use non-boolean types.

Valid Conditions​

var x: int32 = 10;

// Comparison operators return boolean
if (x > 5) {
std::print("x is greater than 5");
}

// Boolean variables work directly
var is_valid: bool = true;
if (is_valid) {
std::print("Valid!");
}

// Logical operators
if (x > 5 and x < 20) {
std::print("x is between 5 and 20");
}

Comparison Operators​

OperatorDescriptionExample
>Greater thanx > 10
<Less thanx < 10
>=Greater than or equalx >= 10
<=Less than or equalx <= 10
==Equalx == 10
!=Not equalx != 10

Logical Operators​

OperatorDescription
andLogical AND
orLogical OR
!Logical NOT

Error Handling​

The compiler provides clear error messages with helpful hints.

Non-Boolean Condition​

var x = 5;
if (x) { } // ERROR

Compiler output:

error: condition of if statement must be boolean, got 'i32'
help: use a comparison operator (e.g., 'x > 0') or wrap the condition with 'bool()'

Expression If Without Type Annotation​

var x = if (true) { 1 } else { 2 };  // ERROR

Compiler output:

error: expression-based if requires explicit type annotation
help: declare the variable with a type: var x: int32 = if ...

LLVM IR Generation​

When compiled, if statements generate proper LLVM basic blocks:

Statement Form​

entry:
%cond = icmp sgt i32 %x, 10
br i1 %cond, label %then, label %else

then: ; preds = %entry
; then branch code
br label %ifcont

else: ; preds = %entry
; else branch code
br label %ifcont

ifcont: ; preds = %else, %then
; execution continues here

Expression Form​

entry:
%result = alloca i32
%cond = icmp sgt i32 %x, 10
br i1 %cond, label %then, label %else

then: ; preds = %entry
store i32 100, ptr %result
br label %ifcont

else: ; preds = %entry
store i32 0, ptr %result
br label %ifcont

ifcont: ; preds = %else, %then
%value = load i32, ptr %result
; %value contains the result

The compiler generates:

  • Conditional branch (br i1) based on the condition
  • Basic blocks for then and else branches
  • Merge point (ifcont) where control flow joins

Best Practices​

  1. Always use explicit boolean conditions - Don't rely on implicit truthiness
  2. Keep conditions simple - Complex conditions should be extracted to variables
  3. Prefer early returns - Handle edge cases first
  4. Use consistent formatting - Always use braces, even for single statements
  5. Use expression if for simple assignments - Cleaner than if-else statements
// Good - simple conditional assignment
var max: int32 = if (a > b) { a } else { b };

// Good - explicit statement form for complex logic
if (condition) {
doSomething();
doAnotherThing();
}

// Avoid
if (condition)
doSomething();

Summary​

  • if executes code when condition is true
  • else executes when condition is false
  • else if chains multiple conditions
  • Conditions must be boolean
  • Nested ifs are allowed but should be minimized
  • Expression-based if returns values (requires type annotation)
  • Error messages include helpful hints for fixing issues