RedScript v3.0 Feature Deep Dive
What matters most in RedScript v3 is not the marketing line “more powerful.” It is which capabilities are truly wired through parser, typechecker, HIR/MIR, and emit, and which ones are still only present at syntax level. Clarifying that boundary is more useful than listing new keywords.
match on string: string branches without integer hacks
src/__tests__/compiler/match-string.test.ts makes this very explicit: match cmd { "help" => ... } becomes an if data ... matches "help" check against storage rs:strings, instead of mapping strings to a custom enum first. For datapack development this is practical: command names, mode names, and UI inputs can be dispatched directly. The value is not just syntax modernity; string values now participate in compilable control flow.
tuples: from “single return value” to multiple returns
Tuple is the most complete feature in v3. AST has tuple type, tuple_lit, let_destruct; tests cover (int, int) return types, return (a, b), and let (q, r) = divmod(...). More important is that lowering does not stop at syntax: MIR writes to __rf_0/__rf_1, and final emit maps these to $ret_0/$ret_1. That means tuple is not sugar; it participates in the actual call convention. For a Minecraft target with no stack and no registers, this is a very pragmatic design.
interface/trait: syntax has landed, implementation is midstream
The boundary matters here. src/ast/types.ts and src/parser/index.ts already support interface Foo { ... }; impl Display for Vec2 { ... } can be parsed and kept in HIR, and src/__tests__/struct-display.test.ts confirms that path. But I have not found a full set of typechecker constraints, trait method resolution, or complete codegen today—there are still todos in tests. So the accurate statement is: v3 has built syntax scaffolding and partial HIR plumbing for interface/trait, but it is not yet a fully usable Rust/TS-style trait system.
decorators: @singleton, @config, @watch, @deprecated, @inline
This group is the most “engineering-focused” part of v3.
@singleton is not mere sugar. It injects a global state model into structs. The typechecker synthesizes Type::get() / Type::set(...) for singleton structs; emit generates scoreboard objectives plus get/set functions for fields. This is ideal for game-wide global state.
@config is compile-time injection. In tests, compile(..., { config: { difficulty: 5 } }) directly changes output mcfunction constants. So it is build-time specialization, not runtime config loading.
@watch follows another path: the compiler generates a dispatcher that, each tick, compares a scoreboard objective’s current and previous values and fires callbacks only when the value changes. That makes scores useful as event sources.
@deprecated currently emits compile-time warnings. src/hir/deprecated.ts walks HIR call sites and emits [DeprecatedUsage] warnings without blocking compilation.
@inline has reached the optimizer. src/__tests__/optimizer/inline_fn.test.ts shows it can inline single-block functions and multi-block CFG functions while explicitly skipping recursive, macro, and external functions. For a datapack backend where a function call is mostly file dispatch, this is high-value optimization.
do-while / repeat
Both loops are more than parser recognition. src/__tests__/compiler/do-while.test.ts shows do { ... } while cond lowers in HIR as “execute body first, then while.” repeat 5 { ... } lowers to a hidden counter plus while. In other words, these are complete semantic features, not sugar. That lowering is appropriate because Minecraft ultimately needs explicit loop blocks.
const, Result, and format_string fixes
const now works at top level and also enters typechecker readonly constraints; assigning to const produces a direct error. This change is not flashy, but it significantly reduces accidental constant mutation in datapack scripts.
Result needs careful wording. The docs call it Result<T>, but current implementation in src/stdlib/result.mcrs is actually concrete enum Result { Ok(value: int), Err(code: int) }, not a generic ADT. It is sufficient for safe division and error-code propagation, but cannot be described as full generic Result<T> yet.
format_string updates are mostly compatibility and bug fixes: the typechecker keeps the legacy format_string type annotation, and the rich-text builtin parameter checks are relaxed to string or format_string. With stronger f-string tests, v3 clearly moves away from treating formatted strings as a side channel and back toward normal string semantics.
Closing
If you only read the feature list, v3 looks like a major upgrade, but from source it is a maturation of compiler convergence. The features truly end-to-end today are string match, tuples, several decorators, do-while/repeat, const, and several string/warning/optimization capabilities. interface/trait and truly generic Result<T> are still on the way. Distinguishing “stable mcfunction emit” from “just entering syntax and IR” is the right way to evaluate RedScript v3.