Expressions
An expression is any piece of code that produces a value. RedScript expressions range from simple literals to complex match expressions.
Literals
Integer literals
42
-7
0
2147483647Type: int (32-bit signed scoreboard integer).
Double / fixed-point literals
3.14 // type: fixed (stored as 31400 internally)
-0.5 // type: fixed
45.0 as double // type: doubleBare decimal literals are fixed (×10000 storage). To get a double, cast explicitly: 1.5 as double.
String literals
"hello"
f"Score: {score}" // f-string interpolation with {expr}Strings are immutable text values. Use canonical f-strings (f"...{expr}...") to interpolate expressions. Plain strings ("...") are not interpolated.
Boolean literals
true
falseType: bool.
Option literals
Some(42) // wraps a value in Option<int>
Some("hello") // wraps a value in Option<string>
None // the empty OptionSome(x) and None are the two constructors for Option<T>. See also if let below.
Operators
Arithmetic
| Operator | Description | Example |
|---|---|---|
+ | Addition | a + b |
- | Subtraction | a - b |
* | Multiplication | a * b |
/ | Division | a / b |
% | Modulo (remainder) | a % b |
- (unary) | Negation | -a |
fixed arithmetic:
fixedoperators are scale-correct by construction. Use normal*and/; the compiler lowers them with×10000compensation. Legacy helpers inmath.mcrsmay still use×1000scales (mulfix,divfix,sin_fixed, etc.) and are not language-levelfixed.
Comparison
| Operator | Description | Example |
|---|---|---|
== | Equal | a == b |
!= | Not equal | a != b |
< | Less than | a < b |
> | Greater than | a > b |
<= | Less or equal | a <= b |
>= | Greater or equal | a >= b |
Logical
| Operator | Description | Example |
|---|---|---|
&& | And | a && b |
|| | Or | a || b |
! | Not | !a |
Operator Precedence (high → low)
| Level | Operators | Associativity |
|---|---|---|
| 7 | - (unary), ! | Right |
| 6 | *, /, % | Left |
| 5 | +, - | Left |
| 4 | <, >, <=, >= | Left |
| 3 | ==, != | Left |
| 2 | && | Left |
| 1 | || | Left |
Use parentheses to override precedence:
let x: int = (2 + 3) * 4; // 20, not 14Function Calls
// Free function call
say("Hello, world!");
// With arguments
tell(@a, f"You have {score} points");
give(@s, "diamond", 3);Arguments are evaluated left to right before the function is called.
Method Calls
Methods are called with dot notation on a value:
let v: Vec2 = Vec2 { x: 3, y: 4 };
let len: int = v.length_sq(); // calls Vec2::length_sq
let scaled: Vec2 = v.scale(2); // calls Vec2::scaleChained Method Calls
Method calls can be chained when each method returns a value:
let result: Vec2 = v.scale(2).add(other);Array Index
Access an element of an array with arr[index]:
let arr: int[] = [10, 20, 30];
let first: int = arr[0]; // 10
let last: int = arr[2]; // 30Indices are zero-based. Accessing out-of-bounds is undefined behavior.
Struct Field Access
Access a field of a struct with .:
struct Point { x: int, y: int }
let p: Point = Point { x: 3, y: 7 };
let px: int = p.x; // 3
let py: int = p.y; // 7Type Casts
Convert a value to a different type with as:
let x: int = 42;
let f: fixed = x as fixed; // int → fixed (× 10000)
let d: double = x as double; // int → double
let back: int = f as int; // fixed → int (÷ 10000, truncated)See types.md for full cast semantics.
Option Constructors
let a: Option<int> = Some(42);
let b: Option<string> = Some("hello");
let c: Option<int> = None;Option<T> is a built-in generic type representing a nullable value. Some(expr) wraps a value; None represents absence.
Enum Constructors
Simple (no payload)
enum Direction { North, South, East, West }
let dir: Direction = Direction::North;With payload fields
enum Color {
Red,
RGB(r: int, g: int, b: int),
}
let c: Color = Color::RGB(r: 255, g: 128, b: 0);Payload fields are named. Supply them as field: value pairs inside the parentheses.
Match Expressions
match dispatches on the value of an expression. Each arm has a pattern and a body block.
Match on integer / range
let score: int = 85;
match score {
90..100 => { say("A"); },
80..89 => { say("B"); },
70..79 => { say("C"); },
_ => { say("Below C"); },
}Ranges are inclusive on both ends (min..max). _ is the wildcard arm.
Match on enum
enum Phase { Idle, Moving, Attacking }
let phase: Phase = Phase::Moving;
match phase {
Phase::Idle => { say("Resting"); },
Phase::Moving => { say("On the move"); },
Phase::Attacking => { say("Attack!"); },
}Match on enum with payload
match color {
Color::RGB(r, g, b) => { tell(@s, f"r={r} g={g} b={b}"); },
Color::Red => { say("plain red"); },
_ => { },
}Match on Option
let maybe: Option<int> = find_score(@p);
match maybe {
Some(v) => { tell(@s, f"Score: {v}"); },
None => { say("No score found"); },
}unwrap_or
Safely extract the value from an Option<T>, falling back to a default if it is None:
let maybe: Option<int> = find_score(@p);
let score: int = maybe.unwrap_or(0); // 0 if NoneEquivalent to:
let score: int = match maybe {
Some(v) => v,
None => 0,
};Lambda Expressions
let double = (x: int) => x * 2;
let clamp = (v: int) => {
if (v < 0) { return 0; }
if (v > 100) { return 100; }
return v;
};Lambdas capture their lexical environment and can be passed to higher-order functions.