- Rust implementation of Molang expression runtime with full JIT compilation via Cranelift - all code is compiled to native machine code.
- Grammar closely mirrors Bedrock's Molang spec (case-insensitive identifiers, ternaries,
??, logical ops, namespaces,loop,for_each, brace blocks). - Runtime context exposes
temp.,variable.,context.namespaces, supports numbers, strings, arrays, and structured assignments. - Comprehensive math library with 67+ functions including trigonometry, easing, interpolation, and more (full Bedrock math namespace).
- Interactive REPL with multi-line support, command history, and syntax highlighting.
- Expressions: numeric ops, precedence,
?:,??, logical&&/||/!, unary +/-. - Literals: numbers, quoted strings, array literals
[a, b, c], struct literals{ x: 1, y: 2 }. - Namespaces:
t.,temp.,v.,variable.,context.,query.with dot-path segments. - Statements: brace-delimited blocks, semicolon-separated statements, assignments,
loop(count, expr_or_block),for_each(var, collection, expr_or_block),break,continue,return. - Struct members are built automatically: assigning
temp.location.z = 3populatestemp.locationas a nested struct. Array literals support indexing (temp.values[i]) and.length. - Builtins:
math.*functions JIT-compiled to direct native calls. - Query namespace: bind dynamic values with
RuntimeContext::with_query("speed", 2.5)and readquery.speedinside Molang. - JIT caching: repeated pure expressions re-use compiled code keyed by source string.
- Control flow: loops, for_each, break, and continue all compiled to native control flow instructions.
All math functions are JIT-compiled to direct native calls for maximum performance.
math.abs(x)- Absolute valuemath.floor(x),math.ceil(x),math.round(x),math.trunc(x)- Roundingmath.clamp(value, min, max)- Clamp value to rangemath.max(a, b),math.min(a, b)- Min/maxmath.mod(value, denominator)- Modulomath.sign(x)- Returns 1 if positive, -1 otherwisemath.copy_sign(a, b)- Returnsawith the sign ofbmath.sqrt(x)- Square rootmath.pi()- Returns π constant
math.cos(degrees),math.sin(degrees)- Cosine and sinemath.acos(x),math.asin(x),math.atan(x)- Inverse trig functionsmath.atan2(y, x)- Two-argument arctangent
math.exp(x)- e^xmath.ln(x)- Natural logarithmmath.pow(base, exponent)- Power function
math.random(low, high)- Random float in rangemath.random_integer(low, high)- Random integer in rangemath.die_roll(num, low, high)- Sum ofnumrandom floatsmath.die_roll_integer(num, low, high)- Sum ofnumrandom integers
math.min_angle(degrees)- Normalize angle to [-180, 180)
math.lerp(start, end, t)- Linear interpolationmath.inverse_lerp(start, end, value)- Inverse linear interpolationmath.lerprotate(start, end, t)- Shortest rotation interpolationmath.hermite_blend(t)- Hermite smoothing: 3t² - 2t³
All easing functions take (start, end, t) parameters where t is in [0,1].
Quadratic: ease_in_quad, ease_out_quad, ease_in_out_quad
Cubic: ease_in_cubic, ease_out_cubic, ease_in_out_cubic
Quartic: ease_in_quart, ease_out_quart, ease_in_out_quart
Quintic: ease_in_quint, ease_out_quint, ease_in_out_quint
Sine: ease_in_sine, ease_out_sine, ease_in_out_sine
Exponential: ease_in_expo, ease_out_expo, ease_in_out_expo
Circular: ease_in_circ, ease_out_circ, ease_in_out_circ
Back (overshoot): ease_in_back, ease_out_back, ease_in_out_back
Elastic (spring): ease_in_elastic, ease_out_elastic, ease_in_out_elastic
Bounce: ease_in_bounce, ease_out_bounce, ease_in_out_bounce
- Minecraft-specific systems (textures, geometry, queries beyond math namespace).
- Arrow (
->) operator and entity references. - Experimental operators not covered in the public Molang math/documented subset.
- Persistence of
variable.values across executions (context resets per run). - Array mutation/slicing (beyond literals, indexing, and
.length).
- All code is JIT-compiled to native machine code via Cranelift - there is no interpreter fallback.
- Pure expressions are cached; programs with statements are compiled on-demand.
- Random functions use a process-global
SmallRng; results are non-deterministic between runs but thread-safe. ??is implemented as "null-like" check; onlynullcounts as missing, unlike Bedrock's broader definition.
temp.location = { x: 1, y: 2 };
temp.location.z = 3;
return temp.location.x + temp.location.y + temp.location.z; # -> 6
temp.counter = 0;
loop(10, {
temp.counter = temp.counter + 1;
(temp.counter > 5) ? break;
});
return temp.counter; # -> 6
temp.values = [2, 4, 6, 8];
temp.total = 0;
for_each(temp.item, temp.values, {
temp.total = temp.total + temp.item;
(temp.item >= 6) ? break;
});
return temp.total; # -> 12
# Array indexing + length
temp.index = 1;
return temp.values[temp.index] + temp.values[3] + temp.values.length; # -> 33
# Pure expression hits the JIT cache
math.clamp(math.random(0, 5), 1, 4) ?? 2
Run without arguments to start the interactive REPL:
cargo run --releaseFeatures:
- Multi-line input with
\continuation - Command history (up/down arrows)
- Special commands:
:help,:vars,:clear,:exit - Syntax highlighting and colored output
See REPL_DEMO.md for examples.
Evaluate a single expression from the command line:
cargo run -- "return math.sqrt(16);"
cargo run -- "temp.x = 5; temp.y = 10; return temp.x + temp.y"cargo testIn Rust you can inject query data before evaluation:
let mut ctx = RuntimeContext::default()
.with_query("speed", 2.5)
.with_query("offset", -1.0);
let value = evaluate_expression("query.speed + math.abs(query.offset)", &mut ctx).unwrap();