redscript-mc 2.1.1 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +66 -21
  3. package/README.zh.md +61 -61
  4. package/dist/src/__tests__/e2e/basic.test.js +25 -0
  5. package/dist/src/__tests__/e2e/coroutine.test.js +22 -0
  6. package/dist/src/__tests__/mc-integration.test.js +25 -13
  7. package/dist/src/__tests__/schedule.test.js +105 -0
  8. package/dist/src/__tests__/tuner/engine.test.d.ts +4 -0
  9. package/dist/src/__tests__/tuner/engine.test.js +232 -0
  10. package/dist/src/__tests__/typechecker.test.js +63 -0
  11. package/dist/src/emit/compile.js +1 -0
  12. package/dist/src/emit/index.js +3 -1
  13. package/dist/src/lir/lower.js +26 -0
  14. package/dist/src/mir/lower.js +341 -12
  15. package/dist/src/mir/types.d.ts +10 -0
  16. package/dist/src/optimizer/copy_prop.js +4 -0
  17. package/dist/src/optimizer/coroutine.d.ts +2 -0
  18. package/dist/src/optimizer/coroutine.js +33 -1
  19. package/dist/src/optimizer/dce.js +7 -1
  20. package/dist/src/optimizer/lir/const_imm.js +1 -1
  21. package/dist/src/optimizer/lir/dead_slot.js +1 -1
  22. package/dist/src/tuner/adapters/ln-polynomial.d.ts +23 -0
  23. package/dist/src/tuner/adapters/ln-polynomial.js +142 -0
  24. package/dist/src/tuner/adapters/sqrt-newton.d.ts +28 -0
  25. package/dist/src/tuner/adapters/sqrt-newton.js +125 -0
  26. package/dist/src/tuner/cli.d.ts +5 -0
  27. package/dist/src/tuner/cli.js +168 -0
  28. package/dist/src/tuner/engine.d.ts +17 -0
  29. package/dist/src/tuner/engine.js +215 -0
  30. package/dist/src/tuner/metrics.d.ts +15 -0
  31. package/dist/src/tuner/metrics.js +51 -0
  32. package/dist/src/tuner/simulator.d.ts +35 -0
  33. package/dist/src/tuner/simulator.js +78 -0
  34. package/dist/src/tuner/types.d.ts +32 -0
  35. package/dist/src/tuner/types.js +6 -0
  36. package/dist/src/typechecker/index.d.ts +2 -0
  37. package/dist/src/typechecker/index.js +29 -0
  38. package/docs/ROADMAP.md +35 -0
  39. package/docs/STDLIB_ROADMAP.md +142 -0
  40. package/editors/vscode/package-lock.json +3 -3
  41. package/editors/vscode/package.json +1 -1
  42. package/examples/coroutine-demo.mcrs +11 -10
  43. package/jest.config.js +19 -0
  44. package/package.json +1 -1
  45. package/src/__tests__/e2e/basic.test.ts +27 -0
  46. package/src/__tests__/e2e/coroutine.test.ts +23 -0
  47. package/src/__tests__/fixtures/array-test.mcrs +21 -22
  48. package/src/__tests__/fixtures/counter.mcrs +17 -0
  49. package/src/__tests__/fixtures/foreach-at-test.mcrs +9 -10
  50. package/src/__tests__/mc-integration.test.ts +25 -13
  51. package/src/__tests__/schedule.test.ts +112 -0
  52. package/src/__tests__/tuner/engine.test.ts +260 -0
  53. package/src/__tests__/typechecker.test.ts +68 -0
  54. package/src/emit/compile.ts +1 -0
  55. package/src/emit/index.ts +3 -1
  56. package/src/lir/lower.ts +27 -0
  57. package/src/mir/lower.ts +355 -9
  58. package/src/mir/types.ts +4 -0
  59. package/src/optimizer/copy_prop.ts +4 -0
  60. package/src/optimizer/coroutine.ts +37 -1
  61. package/src/optimizer/dce.ts +6 -1
  62. package/src/optimizer/lir/const_imm.ts +1 -1
  63. package/src/optimizer/lir/dead_slot.ts +1 -1
  64. package/src/stdlib/bigint.mcrs +155 -192
  65. package/src/stdlib/bits.mcrs +158 -0
  66. package/src/stdlib/color.mcrs +160 -0
  67. package/src/stdlib/geometry.mcrs +124 -0
  68. package/src/stdlib/list.mcrs +125 -0
  69. package/src/stdlib/math.mcrs +90 -0
  70. package/src/stdlib/math_hp.mcrs +65 -0
  71. package/src/stdlib/random.mcrs +67 -0
  72. package/src/stdlib/signal.mcrs +112 -0
  73. package/src/stdlib/timer.mcrs +10 -5
  74. package/src/stdlib/vec.mcrs +27 -0
  75. package/src/tuner/adapters/ln-polynomial.ts +147 -0
  76. package/src/tuner/adapters/sqrt-newton.ts +135 -0
  77. package/src/tuner/cli.ts +158 -0
  78. package/src/tuner/engine.ts +272 -0
  79. package/src/tuner/metrics.ts +66 -0
  80. package/src/tuner/simulator.ts +69 -0
  81. package/src/tuner/types.ts +44 -0
  82. package/src/typechecker/index.ts +39 -0
  83. package/docs/ARCHITECTURE.zh.md +0 -1088
  84. package/docs/COMPILATION_STATS.md +0 -142
  85. package/docs/IMPLEMENTATION_GUIDE.md +0 -512
package/CHANGELOG.md CHANGED
@@ -2,6 +2,37 @@
2
2
 
3
3
  All notable changes to RedScript will be documented in this file.
4
4
 
5
+ ## [2.3.0] - 2026-03-17
6
+
7
+ ### Added
8
+ - `stdlib/math.mcrs`: `ln` (SA-tuned atanh series, max_error < 0.0006), `sqrt_fx` (×10000 scale), `exp_fx` (Horner Taylor + 2^k scaling)
9
+ - `stdlib/math_hp.mcrs`: `sin_hp`/`cos_hp` using MC entity rotation trick (double precision), `init_trig()` bootstrap
10
+ - `stdlib/random.mcrs`: LCG (`next_lcg`, `random_range`, `random_bool`) + PCG (`pcg_next_lo/hi`, `pcg_output`)
11
+ - `stdlib/color.mcrs`: RGB packing/unpacking, `rgb_lerp`, HSL↔RGB conversion (`hsl_to_r/g/b`, `rgb_to_h/s/l`)
12
+ - `stdlib/bits.mcrs`: bitwise AND/OR/XOR/NOT, left/right shift, bit get/set/clear/toggle, popcount (all integer-simulated)
13
+ - `stdlib/list.mcrs`: `sort3`, min/max/avg for 3 and 5 values, weighted choice utilities
14
+ - `stdlib/geometry.mcrs`: AABB/sphere/cylinder contains checks, parabola physics, grid/tile helpers, angle normalization, MC sun angle
15
+ - `stdlib/signal.mcrs`: uniform, normal (12-sample approximation), exponential distribution, bernoulli trial, weighted2/3 choice
16
+ - `stdlib/bigint.mcrs`: 96-bit base-10000 arithmetic (add, sub, mul, div, cmp, int32↔bigint3 conversion)
17
+ - `src/tuner/`: hyperparameter search framework (Nelder-Mead + Simulated Annealing) for stdlib coefficient optimization
18
+ - `adapters/ln-polynomial.ts`: atanh series adapter
19
+ - `adapters/sqrt-newton.ts`: Newton iteration adapter
20
+ - CLI: `redscript tune --adapter <name> [--strategy nm|sa] [--budget N] [--out path]`
21
+
22
+ ### Changed
23
+ - `stdlib/vec.mcrs`: added 2D/3D add/sub/scale/neg component helpers
24
+
25
+ ## [2.1.1] - 2026-03-16
26
+
27
+ ### Added
28
+ - stdlib include path: `import "stdlib/math"` without specifying full path
29
+ - `--include <dir>` CLI flag for custom library paths
30
+ - LSP hover for 50+ builtin functions and all decorators (@tick/@load/@coroutine/@schedule/@on_trigger)
31
+ - f-string syntax highlighting in VSCode extension
32
+
33
+ ### Changed
34
+ - Example files cleaned up: removed stale/redundant examples, added coroutine/enum/scheduler demos
35
+
5
36
  ## [1.2.15] - 2026-03-13
6
37
 
7
38
  ### Changed
package/README.md CHANGED
@@ -2,14 +2,14 @@
2
2
 
3
3
  <img src="./logo.png" alt="RedScript Logo" width="64" />
4
4
 
5
- <img src="https://img.shields.io/badge/RedScript-2.0.0-red?style=for-the-badge&logo=minecraft&logoColor=white" alt="RedScript" />
5
+ <img src="https://img.shields.io/badge/RedScript-2.1.1-red?style=for-the-badge&logo=minecraft&logoColor=white" alt="RedScript" />
6
6
 
7
7
  **A typed scripting language that compiles to Minecraft datapacks.**
8
8
 
9
9
  Write clean game logic. RedScript handles the scoreboard spaghetti.
10
10
 
11
11
  [![CI](https://github.com/bkmashiro/redscript/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/bkmashiro/redscript/actions/workflows/ci.yml)
12
- [![Tests](https://img.shields.io/badge/tests-857%20passing-brightgreen)](https://github.com/bkmashiro/redscript)
12
+ [![Tests](https://img.shields.io/badge/tests-1123%20passing-brightgreen)](https://github.com/bkmashiro/redscript)
13
13
  [![npm](https://img.shields.io/npm/v/redscript-mc?color=cb3837)](https://www.npmjs.com/package/redscript-mc)
14
14
  [![npm downloads](https://img.shields.io/npm/dm/redscript-mc?color=cb3837)](https://www.npmjs.com/package/redscript-mc)
15
15
  [![VSCode](https://img.shields.io/badge/VSCode-Extension-007ACC?logo=visualstudiocode)](https://marketplace.visualstudio.com/items?itemName=bkmashiro.redscript-vscode)
@@ -37,7 +37,7 @@ RedScript is a typed scripting language that compiles to vanilla Minecraft datap
37
37
  **The demo above?** Five math curves drawn with 64 sample points each. The core logic:
38
38
 
39
39
  ```rs
40
- import "stdlib/math.mcrs"
40
+ import "stdlib/math"
41
41
 
42
42
  let phase: int = 0;
43
43
  let frame: int = 0;
@@ -73,20 +73,32 @@ let frame: int = 0;
73
73
  - ✅ Builtins accept runtime macro variables in any argument position
74
74
  - ✅ f-strings like `f"Score: {points}"` for dynamic output
75
75
  - ✅ Public functions are preserved automatically; `_privateFn()` stays private
76
+ - ✅ `enum` types with `match` dispatch (zero-runtime overhead)
77
+ - ✅ Multi-return values: `fn divmod(a: int, b: int): (int, int)`
78
+ - ✅ Generics: `fn max<T>(a: T, b: T): T` (monomorphized)
79
+ - ✅ `Option<T>` null safety: `Some(x)` / `None` / `if let Some(x) = opt`
80
+ - ✅ `@coroutine(batch=N)` for tick-spread loops (no more maxCommandChain hits)
81
+ - ✅ `@schedule(ticks=N)` to delay function execution
82
+ - ✅ Module system: `module math; import math::sin;`
83
+ - ✅ Multi-version targets: `--mc-version 1.20.2`
84
+ - ✅ Source maps: `--source-map` for debugging
85
+ - ✅ Language Server Protocol: diagnostics, hover, go-to-def, completion
76
86
  - ✅ One file -> ready-to-use datapack
77
87
 
78
88
  ---
79
89
 
80
- ### What's New in v2.0.0
90
+ ### What's New in v2.1.x
81
91
 
82
- - New compiler pipeline: **AST HIR MIR LIR emit**
83
- - New LIR optimizer passes (dead slot elimination + constant immediate folding)
84
- - CLI `compile` now runs on the v2 pipeline by default
85
- - `use "..."` import resolution fully supported in v2 (including library modules)
86
- - Macro calls (`^var`/`~var`) supported end-to-end in v2 emitter
87
- - Struct/impl lowering completed in v2 (field slots + method dispatch)
88
- - Unified source tree: old `src2/` merged back into `src/`
89
- - Published as **redscript-mc@2.0.0**
92
+ - **`enum` + `match` dispatch** zero-runtime-overhead state machines; the compiler folds enum variants to integer constants and uses `execute if score` dispatch with no heap allocation
93
+ - **Multi-return values** `fn divmod(a: int, b: int): (int, int)` unpacks to separate scoreboard slots; no struct wrapper needed
94
+ - **Generics** `fn max<T>(a: T, b: T): T` is fully monomorphized at compile time; no boxing, no indirection
95
+ - **`Option<T>` null safety** — `Some(x)` / `None` with `if let Some(x) = opt` pattern binding; safe access to optional values without sentinel integers
96
+ - **`@coroutine(batch=N)`** spreads a heavy loop across multiple ticks (`batch=50` means 50 iterations/tick), avoiding `maxCommandChainLength` hits on large workloads
97
+ - **`@schedule(ticks=N)`** delays a function call by N game ticks; compiles to `schedule function` with automatic namespace scoping
98
+ - **Module system** `module math;` declares a named module; consumers `import math::sin` to tree-shake individual symbols
99
+ - **Multi-version targets** — `--mc-version 1.20.2` switches emit strategy (macro sub-functions vs. legacy scoreboards) for the target server version
100
+ - **Source maps** — `--source-map` emits a `.mcrs.map` sidecar that maps each `.mcfunction` line back to the original source; enables in-editor debugging
101
+ - **LSP: hover + completion for builtins & decorators** — 50+ builtin functions and all decorators (`@tick`/`@load`/`@coroutine`/`@schedule`/`@on_trigger`) now show inline docs on hover
90
102
 
91
103
  ---
92
104
 
@@ -277,6 +289,9 @@ redscript compile <file> Compile to datapack (default) or structure
277
289
  -o, --output <dir> Output directory [default: ./out]
278
290
  --target datapack|structure Output format [default: datapack]
279
291
  --namespace <ns> Datapack namespace [default: filename]
292
+ --mc-version <ver> Target MC version [default: 1.21]
293
+ --include <dir> Extra library search path (repeatable)
294
+ --source-map Emit .mcrs.map source map for debugging
280
295
  --no-optimize Skip optimizer passes
281
296
  --stats Print optimizer statistics
282
297
 
@@ -286,39 +301,63 @@ redscript validate <file> Validate MC commands
286
301
 
287
302
  ---
288
303
 
304
+ ### Stdlib
305
+
306
+ RedScript ships a built-in standard library. Use the short form — no path needed:
307
+
308
+ ```rs
309
+ import "stdlib/math" // fixed-point math: ln, sqrt_fx, exp_fx, sin_fixed, cos_fixed...
310
+ import "stdlib/math_hp" // high-precision trig via entity rotation (init_trig required)
311
+ import "stdlib/vec" // 2D/3D vector: dot, cross, length, distance, atan2, rotate...
312
+ import "stdlib/random" // LCG & PCG random number generators
313
+ import "stdlib/color" // RGB/HSL color packing, blending, conversion
314
+ import "stdlib/bits" // bitwise AND/OR/XOR/NOT/shift/popcount (integer-simulated)
315
+ import "stdlib/list" // sort3, min/max/avg, weighted utilities
316
+ import "stdlib/geometry" // AABB/sphere contains, parabola physics, angle helpers
317
+ import "stdlib/signal" // normal/exponential distributions, bernoulli, weighted choice
318
+ import "stdlib/bigint" // 96-bit base-10000 arithmetic (add/sub/mul/div/cmp)
319
+ import "stdlib/combat" // damage, kill-check helpers
320
+ import "stdlib/player" // health, alive check, range
321
+ import "stdlib/cooldown" // per-player cooldown tracking
322
+ ```
323
+
324
+ Custom library paths can be added with `--include <dir>` so your own modules work the same way.
325
+
289
326
  ### Standard Library
290
327
 
291
328
  All stdlib files use `module library;` — only the functions you actually call are compiled in.
292
329
 
330
+ > Parts of the standard library are inspired by [kaer-3058/large_number](https://github.com/kaer-3058/large_number), a comprehensive math library for Minecraft datapacks.
331
+
293
332
  ```rs
294
- import "stdlib/math.mcrs" // abs, sign, min, max, clamp, lerp, isqrt, sqrt_fixed,
333
+ import "stdlib/math" // abs, sign, min, max, clamp, lerp, isqrt, sqrt_fixed,
295
334
  // pow_int, gcd, lcm, sin_fixed, cos_fixed, map, ceil_div,
296
335
  // log2_int, mulfix, divfix, smoothstep, smootherstep
297
336
 
298
- import "stdlib/vec.mcrs" // dot2d, cross2d, length2d_fixed, distance2d_fixed,
337
+ import "stdlib/vec" // dot2d, cross2d, length2d_fixed, distance2d_fixed,
299
338
  // manhattan, chebyshev, atan2_fixed, normalize2d_x/y,
300
339
  // rotate2d_x/y, lerp2d_x/y, dot3d, cross3d_x/y/z,
301
340
  // length3d_fixed
302
341
 
303
- import "stdlib/advanced.mcrs" // fib, is_prime, collatz_steps, digit_sum, reverse_int,
342
+ import "stdlib/advanced" // fib, is_prime, collatz_steps, digit_sum, reverse_int,
304
343
  // mod_pow, hash_int, noise1d, bezier_quad,
305
344
  // mandelbrot_iter, julia_iter, angle_between,
306
345
  // clamp_circle_x/y, newton_sqrt, digital_root
307
346
 
308
- import "stdlib/bigint.mcrs" // bigint_init, bigint_from_int_a/b, bigint_add/sub/mul,
347
+ import "stdlib/bigint" // bigint_init, bigint_from_int_a/b, bigint_add/sub/mul,
309
348
  // bigint_compare, bigint_mul_small, bigint_fib
310
349
  // — up to 32 decimal digits, runs on MC scoreboard
311
350
 
312
- import "stdlib/player.mcrs" // is_alive, in_range, get_health
313
- import "stdlib/timer.mcrs" // start_timer, tick_timer, has_elapsed
314
- import "stdlib/cooldown.mcrs" // set_cooldown, check_cooldown
315
- import "stdlib/mobs.mcrs" // ZOMBIE, SKELETON, CREEPER, ... (60+ constants)
351
+ import "stdlib/player" // is_alive, in_range, get_health
352
+ import "stdlib/timer" // start_timer, tick_timer, has_elapsed
353
+ import "stdlib/cooldown" // set_cooldown, check_cooldown
354
+ import "stdlib/mobs" // ZOMBIE, SKELETON, CREEPER, ... (60+ constants)
316
355
  ```
317
356
 
318
357
  **Example — computing Fibonacci(50) in-game:**
319
358
 
320
359
  ```rs
321
- import "stdlib/bigint.mcrs"
360
+ import "stdlib/bigint"
322
361
 
323
362
  fn show_fib() {
324
363
  bigint_fib(50);
@@ -415,6 +454,12 @@ See [CHANGELOG.md](./CHANGELOG.md) for the full release notes.
415
454
 
416
455
  ---
417
456
 
457
+ ## Acknowledgements
458
+
459
+ Parts of the standard library are inspired by [kaer-3058/large_number](https://github.com/kaer-3058/large_number), a comprehensive math library for Minecraft datapacks. RedScript provides a higher-level, type-safe API over similar algorithms.
460
+
461
+ ---
462
+
418
463
  <div align="center">
419
464
 
420
465
  MIT License · Copyright © 2026 [bkmashiro](https://github.com/bkmashiro)
package/README.zh.md CHANGED
@@ -2,14 +2,14 @@
2
2
 
3
3
  <img src="./logo.png" alt="RedScript Logo" width="64" />
4
4
 
5
- <img src="https://img.shields.io/badge/RedScript-2.0.0-red?style=for-the-badge&logo=minecraft&logoColor=white" alt="RedScript" />
5
+ <img src="https://img.shields.io/badge/RedScript-2.1.1-red?style=for-the-badge&logo=minecraft&logoColor=white" alt="RedScript" />
6
6
 
7
7
  **一个编译到 Minecraft Datapack 的类型化脚本语言。**
8
8
 
9
9
  写干净的游戏逻辑,把记分板的面条代码交给 RedScript 处理。
10
10
 
11
11
  [![CI](https://github.com/bkmashiro/redscript/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/bkmashiro/redscript/actions/workflows/ci.yml)
12
- [![Tests](https://img.shields.io/badge/tests-857%20passing-brightgreen)](https://github.com/bkmashiro/redscript)
12
+ [![Tests](https://img.shields.io/badge/tests-1123%20passing-brightgreen)](https://github.com/bkmashiro/redscript)
13
13
  [![npm](https://img.shields.io/npm/v/redscript-mc?color=cb3837)](https://www.npmjs.com/package/redscript-mc)
14
14
  [![npm downloads](https://img.shields.io/npm/dm/redscript-mc?color=cb3837)](https://www.npmjs.com/package/redscript-mc)
15
15
  [![VSCode](https://img.shields.io/badge/VSCode-插件-007ACC?logo=visualstudiocode)](https://marketplace.visualstudio.com/items?itemName=bkmashiro.redscript-vscode)
@@ -37,7 +37,7 @@ RedScript 是一门编译到原版 Minecraft 数据包的脚本语言。用变
37
37
  **上面的演示?** 五条数学曲线,每条 64 个采样点,核心逻辑:
38
38
 
39
39
  ```rs
40
- import "stdlib/math.mcrs"
40
+ import "stdlib/math"
41
41
 
42
42
  let phase: int = 0;
43
43
  let frame: int = 0;
@@ -65,40 +65,36 @@ let frame: int = 0;
65
65
 
66
66
  **你得到:**
67
67
  - ✅ `let` / `const` 变量(告别 `scoreboard players set`)
68
- - ✅ `if` / `else` / `for` / `foreach` 完整控制流
68
+ - ✅ `if` / `else` / `for` / `foreach` / `break` / `continue` 完整控制流
69
69
  - ✅ `@tick` / `@load` / `@on(Event)` 装饰器
70
70
  - ✅ `foreach (p in @a) at @s` — 遍历实体并设置执行上下文
71
71
  - ✅ f-strings 如 `f"分数: {points}"` 动态输出
72
+ - ✅ `enum` 类型 + `match` 分发(零运行时开销)
73
+ - ✅ 多返回值:`fn divmod(a: int, b: int): (int, int)`
74
+ - ✅ 泛型:`fn max<T>(a: T, b: T): T`(单态化)
75
+ - ✅ `Option<T>` 空值安全:`Some(x)` / `None` / `if let Some(x) = opt`
76
+ - ✅ `@coroutine(batch=N)` 将循环分散到多个 tick(不再触发 maxCommandChain 限制)
77
+ - ✅ `@schedule(ticks=N)` 延迟执行函数
78
+ - ✅ 模块系统:`module math; import math::sin;`
79
+ - ✅ 多版本目标:`--mc-version 1.20.2`
80
+ - ✅ 源码映射:`--source-map` 支持调试
81
+ - ✅ 语言服务协议(LSP):诊断、悬停提示、跳转定义、代码补全
72
82
  - ✅ 一个文件 → 可直接使用的 datapack
73
83
 
74
84
  ---
75
85
 
76
- ### v1.2.27 新增内容
86
+ ### v2.1.x 新增内容
77
87
 
78
- - **BigInt 实机验证通过** (`bigint.mcrs`):任意精度整数在 MC 记分板 + NBT 上完整运行 base 10000 × 8 limbs = 最多 32 位十进制数;`bigint_fib(50)` = 12,586,269,025 在 Paper 1.21.4 实机验证正确
79
- - **`storage_set_int` 宏修复**:动态 NBT 数组写入改用 `execute store result storage` 而非 `data modify set value $(n)` — 规避 Minecraft 宏机制对整数值的静默替换 bug
80
- - **完整标准库** (`math.mcrs`、`vec.mcrs`、`advanced.mcrs`、`bigint.mcrs`、`showcase.mcrs`):18 个数学函数、14 个向量几何函数、20+ 数论与分形函数
81
- - **`module library;` pragma**:库文件零成本树摇 标准库永远不会撑大你的数据包
82
- - **`@require_on_load(fn)` 装饰器**:sin/cos/atan 查找表初始化器的声明式加载依赖跟踪
83
-
84
- ### v1.2.26 新增内容
85
-
86
- - **数学标准库** (`math.mcrs`):18 个定点数函数 `abs`、`sign`、`min`、`max`、`clamp`、`lerp`、`isqrt`、`sqrt_fixed`、`pow_int`、`gcd`、`lcm`、`sin_fixed`、`cos_fixed`、`map`、`ceil_div`、`log2_int`、`mulfix`、`divfix`、`smoothstep`、`smootherstep`
87
- - **向量标准库** (`vec.mcrs`):2D / 3D 几何 点积/叉积、`length2d_fixed`、`atan2_fixed`(二分搜索正切表,O(log 46))、`normalize2d`、`rotate2d`、`lerp2d`、完整 3D 叉积
88
- - **高级标准库** (`advanced.mcrs`):数论(`fib`、`is_prime`、`collatz_steps`、`mod_pow`)、哈希/噪声(splitmix32 `hash_int`、`noise1d`)、曲线(`bezier_quad`)、分形(`mandelbrot_iter`、`julia_iter`)、几何实验
89
- - **BigInt** (`bigint.mcrs`):任意精度整数架构设计 — base 10000 × 8 limbs = 最多 32 位十进制数
90
- - **编译器修复**:`isqrt` 大数收敛、优化器拷贝传播别名失效、跨函数变量命名冲突、MCRuntime 数组索引正则
91
-
92
- ### v1.2.25 新增内容
93
-
94
- - `impl` 块与方法,支持围绕结构体构建面向对象风格 API
95
- - `is` 类型收窄,实体判断更安全
96
- - 使用 `@on(Event)` 的静态事件系统
97
- - 面向运行时输出的 f-string
98
- - `Timer::new(...)` 与实例方法组成的 Timer OOP API
99
- - `setTimeout(...)` 与 `setInterval(...)` 调度辅助函数
100
- - 优化器中的死代码消除
101
- - 标准库新增 313 个 Minecraft 标签常量
88
+ - **`enum` + `match` 分发**零运行时开销的状态机;编译器将枚举变体折叠为整数常量,用 `execute if score` 分发,无堆分配
89
+ - **多返回值** `fn divmod(a: int, b: int): (int, int)` 解包到独立记分板槽位,不需要结构体包装
90
+ - **泛型** — `fn max<T>(a: T, b: T): T` 在编译期完整单态化,无装箱无间接引用
91
+ - **`Option<T>` 空值安全**`Some(x)` / `None` 与 `if let Some(x) = opt` 模式绑定,不再依赖哨兵整数
92
+ - **`@coroutine(batch=N)`** — 将繁重循环分散到多个 tick(`batch=50` 表示每 tick 执行 50 次迭代),避免触发 `maxCommandChainLength` 限制
93
+ - **`@schedule(ticks=N)`** — 延迟 N 个游戏 tick 后执行函数,编译为带自动命名空间前缀的 `schedule function`
94
+ - **模块系统** — `module math;` 声明命名模块;调用方 `import math::sin` 可按符号树摇
95
+ - **多版本目标** — `--mc-version 1.20.2` 针对目标服务器版本切换发射策略(宏子函数 vs 传统记分板)
96
+ - **源码映射** — `--source-map` 生成 `.mcrs.map` 附属文件,将每行 `.mcfunction` 映射回原始源码,支持编辑器内调试
97
+ - **LSP 悬停 + 补全**50+ 内置函数及所有装饰器(`@tick`/`@load`/`@coroutine`/`@schedule`/`@on_trigger`)均支持悬停内联文档
102
98
 
103
99
  ---
104
100
 
@@ -273,6 +269,9 @@ redscript compile <file> 编译为 datapack(默认)或 structure
273
269
  -o, --output <dir> 输出目录 [默认: ./out]
274
270
  --target datapack|structure 输出格式 [默认: datapack]
275
271
  --namespace <ns> Datapack 命名空间 [默认: 文件名]
272
+ --mc-version <ver> 目标 MC 版本 [默认: 1.21]
273
+ --include <dir> 额外库搜索路径(可重复)
274
+ --source-map 生成 .mcrs.map 源码映射文件
276
275
  --no-optimize 禁用优化器
277
276
  --stats 输出优化器统计信息
278
277
 
@@ -284,37 +283,49 @@ redscript validate <file> 验证 MC 命令语法
284
283
 
285
284
  ### 标准库
286
285
 
286
+ RedScript 内置标准库,使用短路径直接导入,无需指定完整文件路径:
287
+
288
+ ```rs
289
+ import "stdlib/math" // 定点数学
290
+ import "stdlib/vec" // 2D/3D 向量几何
291
+ import "stdlib/combat" // 伤害、击杀检测辅助函数
292
+ import "stdlib/player" // 血量、存活检测、范围判断
293
+ import "stdlib/cooldown" // 每玩家冷却时间管理
294
+ ```
295
+
296
+ 通过 `--include <dir>` 可添加自定义库路径,自有模块也能用同样的短路径导入。
297
+
287
298
  所有标准库文件都使用 `module library;` —— 只有你实际调用的函数才会编译进去。
288
299
 
289
300
  ```rs
290
- import "stdlib/math.mcrs" // abs, sign, min, max, clamp, lerp, isqrt, sqrt_fixed,
301
+ import "stdlib/math" // abs, sign, min, max, clamp, lerp, isqrt, sqrt_fixed,
291
302
  // pow_int, gcd, lcm, sin_fixed, cos_fixed, map, ceil_div,
292
303
  // log2_int, mulfix, divfix, smoothstep, smootherstep
293
304
 
294
- import "stdlib/vec.mcrs" // dot2d, cross2d, length2d_fixed, distance2d_fixed,
305
+ import "stdlib/vec" // dot2d, cross2d, length2d_fixed, distance2d_fixed,
295
306
  // manhattan, chebyshev, atan2_fixed, normalize2d_x/y,
296
307
  // rotate2d_x/y, lerp2d_x/y, dot3d, cross3d_x/y/z,
297
308
  // length3d_fixed
298
309
 
299
- import "stdlib/advanced.mcrs" // fib, is_prime, collatz_steps, digit_sum, reverse_int,
310
+ import "stdlib/advanced" // fib, is_prime, collatz_steps, digit_sum, reverse_int,
300
311
  // mod_pow, hash_int, noise1d, bezier_quad,
301
312
  // mandelbrot_iter, julia_iter, angle_between,
302
313
  // clamp_circle_x/y, newton_sqrt, digital_root
303
314
 
304
- import "stdlib/bigint.mcrs" // bigint_init, bigint_from_int_a/b, bigint_add/sub/mul,
315
+ import "stdlib/bigint" // bigint_init, bigint_from_int_a/b, bigint_add/sub/mul,
305
316
  // bigint_compare, bigint_mul_small, bigint_fib
306
317
  // — 最多 32 位十进制数,纯记分板运行
307
318
 
308
- import "stdlib/player.mcrs" // is_alive, in_range, get_health
309
- import "stdlib/timer.mcrs" // start_timer, tick_timer, has_elapsed
310
- import "stdlib/cooldown.mcrs" // set_cooldown, check_cooldown
311
- import "stdlib/mobs.mcrs" // ZOMBIE, SKELETON, CREEPER ... (60+ 实体常量)
319
+ import "stdlib/player" // is_alive, in_range, get_health
320
+ import "stdlib/timer" // start_timer, tick_timer, has_elapsed
321
+ import "stdlib/cooldown" // set_cooldown, check_cooldown
322
+ import "stdlib/mobs" // ZOMBIE, SKELETON, CREEPER ... (60+ 实体常量)
312
323
  ```
313
324
 
314
325
  **示例 — 游戏内计算斐波那契数列第 50 项:**
315
326
 
316
327
  ```rs
317
- import "stdlib/bigint.mcrs"
328
+ import "stdlib/bigint"
318
329
 
319
330
  fn show_fib() {
320
331
  bigint_fib(50);
@@ -343,32 +354,21 @@ fn show_fib() {
343
354
 
344
355
  ### 更新日志亮点
345
356
 
346
- #### v1.2.27(2026-03-14
347
-
348
- - **BigInt 实机修复**:`storage_set_int` 宏改用 `execute store result storage`,规避 MC 宏整数替换 bug;BigInt 在 Paper 1.21.4 实机验证通过
349
- - showcase 示例修复:`atan2_fixed` 返回度数(0–360),更正不必要的除以 1000;`mod_pow` 测试改用小 modulus 避免 INT32 溢出
350
-
351
- #### v1.2.26(2026-03-14)
352
-
353
- - 完整的数学/向量/高级/BigInt 标准库(详见上方)
354
- - `module library;` pragma,实现零成本树摇
355
- - `storage_get_int` / `storage_set_int` 动态 NBT 数组内置函数
356
- - 编译器修复:`isqrt` 收敛、拷贝传播、变量作用域命名
357
-
358
- #### v1.2.25(2026-03-13)
357
+ #### v2.1.1(2026-03-16
359
358
 
360
- - 实体类型层级与 `W_IMPOSSIBLE_AS` 警告
361
- - 变量名混淆(`$a`、`$b`、`$c` ...),最小化记分板占用
362
- - CI/CD 自动化:每次推送自动发布 npm + VSCode 插件
359
+ - stdlib 包含路径支持:`import "stdlib/math"` 无需指定完整路径
360
+ - `--include <dir>` CLI 参数,支持自定义库路径
361
+ - LSP 悬停支持 50+ 内置函数及全部装饰器
362
+ - VSCode 插件支持 f-string 语法高亮
363
363
 
364
- #### v1.2.0
364
+ #### v2.0.0
365
365
 
366
- - 新增 `impl` 块、实例方法与静态构造函数
367
- - 新增 `is` 类型收窄,提升实体相关控制流的类型安全
368
- - 新增 `@on(Event)` 静态事件与回调调度内置函数
369
- - 新增运行时输出用 f-string
370
- - 标准库补充 Timer OOP API 与 313 个 MC 标签常量
371
- - 优化器支持死代码消除
366
+ - 新编译器管线:**AST HIR → MIR → LIR → emit**
367
+ - LIR 优化器(死槽位消除 + 常量立即数折叠)
368
+ - CLI `compile` 默认使用 v2 管线
369
+ - 完整 `use "..."` 导入解析(含库模块)
370
+ - 宏调用(`^var`/`~var`)在 v2 发射器中端到端支持
371
+ - v2 中完成结构体/impl 降级(字段槽位 + 方法分发)
372
372
 
373
373
  完整发布说明见 [CHANGELOG.md](./CHANGELOG.md)。
374
374
 
@@ -136,5 +136,30 @@ describe('e2e: basic compilation', () => {
136
136
  const tickJson = getFile(result.files, 'tick.json');
137
137
  expect(tickJson).toBeUndefined();
138
138
  });
139
+ test('array literal emits data modify storage command', () => {
140
+ const source = `
141
+ fn test_arrays(): void {
142
+ let nums: int[] = [10, 20, 30, 40, 50];
143
+ }
144
+ `;
145
+ const result = (0, compile_1.compile)(source, { namespace: 'array_test' });
146
+ const fn = getFile(result.files, 'test_arrays.mcfunction');
147
+ expect(fn).toBeDefined();
148
+ expect(fn).toContain('data modify storage array_test:arrays nums set value [10, 20, 30, 40, 50]');
149
+ });
150
+ test('array index access emits data get storage command', () => {
151
+ const source = `
152
+ fn test_arrays(): void {
153
+ let nums: int[] = [10, 20, 30, 40, 50];
154
+ scoreboard_set("#arr_0", #rs, nums[0]);
155
+ }
156
+ `;
157
+ const result = (0, compile_1.compile)(source, { namespace: 'array_test' });
158
+ const fn = getFile(result.files, 'test_arrays.mcfunction');
159
+ expect(fn).toBeDefined();
160
+ expect(fn).toContain('data modify storage array_test:arrays nums set value [10, 20, 30, 40, 50]');
161
+ expect(fn).toContain('data get storage array_test:arrays nums[0]');
162
+ expect(fn).toContain('#arr_0');
163
+ });
139
164
  });
140
165
  //# sourceMappingURL=basic.test.js.map
@@ -109,6 +109,28 @@ describe('e2e: @coroutine', () => {
109
109
  const helperFn = getFile(result.files, 'helper.mcfunction');
110
110
  expect(helperFn).toBeDefined();
111
111
  });
112
+ test('@coroutine with macro call_macro is skipped with warning', () => {
113
+ // call_macro: a function that has isMacro params will be called via call_macro
114
+ // We simulate this with raw() containing ${var} which generates __raw:\x01 in MIR
115
+ const source = `
116
+ @coroutine(batch=10)
117
+ fn with_macro_raw(): void {
118
+ let i: int = 0;
119
+ while (i < 100) {
120
+ let x: int = i;
121
+ raw("particle minecraft:end_rod ^$\{x} ^0 ^0 0 0 0 0 1 force @a");
122
+ i = i + 1;
123
+ }
124
+ }
125
+ `;
126
+ const result = (0, compile_1.compile)(source, { namespace: 'corotest' });
127
+ // Should emit a warning about skipping
128
+ expect(result.warnings.some(w => w.includes('@coroutine cannot be applied') && w.includes('with_macro_raw'))).toBe(true);
129
+ // Should NOT generate continuation files — function kept as-is
130
+ const paths = getFileNames(result.files);
131
+ const contFiles = paths.filter(p => p.includes('_coro_'));
132
+ expect(contFiles.length).toBe(0);
133
+ });
112
134
  test('default batch value is 10 when not specified', () => {
113
135
  // @coroutine without batch should default to batch=10
114
136
  // We test by ensuring compilation succeeds
@@ -105,13 +105,25 @@ beforeAll(async () => {
105
105
  console.warn(` Then restart the MC server and re-run tests.`);
106
106
  return;
107
107
  }
108
- // ── Write fixtures + use safe reloadData (no /reload confirm) ───────
109
- // counter.mcrs
110
- if (fs.existsSync(path.join(__dirname, '../examples/counter.mcrs'))) {
111
- writeFixture(fs.readFileSync(path.join(__dirname, '../examples/counter.mcrs'), 'utf-8'), 'counter');
108
+ // ── Clear stale minecraft tag files before writing fixtures ──────────
109
+ for (const tagFile of ['data/minecraft/tags/function/tick.json', 'data/minecraft/tags/function/load.json',
110
+ 'data/minecraft/tags/functions/tick.json', 'data/minecraft/tags/functions/load.json']) {
111
+ const p = path.join(DATAPACK_DIR, tagFile);
112
+ if (fs.existsSync(p))
113
+ fs.writeFileSync(p, JSON.stringify({ values: [] }, null, 2));
112
114
  }
113
- if (fs.existsSync(path.join(__dirname, '../examples/world_manager.mcrs'))) {
114
- writeFixture(fs.readFileSync(path.join(__dirname, '../examples/world_manager.mcrs'), 'utf-8'), 'world_manager');
115
+ // ── Write fixtures + use safe reloadData (no /reload confirm) ───────
116
+ // counter.mcrs (use fixtures if examples was removed)
117
+ const counterSrc = fs.existsSync(path.join(__dirname, '../examples/counter.mcrs'))
118
+ ? fs.readFileSync(path.join(__dirname, '../examples/counter.mcrs'), 'utf-8')
119
+ : fs.readFileSync(path.join(__dirname, 'fixtures/counter.mcrs'), 'utf-8');
120
+ writeFixture(counterSrc, 'counter');
121
+ // world_manager.mcrs
122
+ const wmPath = fs.existsSync(path.join(__dirname, '../examples/world_manager.mcrs'))
123
+ ? path.join(__dirname, '../examples/world_manager.mcrs')
124
+ : path.join(__dirname, '../src/examples/world_manager.mcrs');
125
+ if (fs.existsSync(wmPath)) {
126
+ writeFixture(fs.readFileSync(wmPath, 'utf-8'), 'world_manager');
115
127
  }
116
128
  writeFixture(`
117
129
  @tick
@@ -394,9 +406,9 @@ describe('MC Integration Tests', () => {
394
406
  if (!serverOnline)
395
407
  return;
396
408
  await mc.fullReset({ clearArea: false, killEntities: true, resetScoreboards: false });
397
- await mc.command('/summon minecraft:armor_stand 0 65 0');
398
- await mc.command('/summon minecraft:armor_stand 2 65 0');
399
- await mc.command('/summon minecraft:armor_stand 4 65 0');
409
+ await mc.command('/summon minecraft:armor_stand 0 65 0 {NoGravity:1b}');
410
+ await mc.command('/summon minecraft:armor_stand 2 65 0 {NoGravity:1b}');
411
+ await mc.command('/summon minecraft:armor_stand 4 65 0 {NoGravity:1b}');
400
412
  await mc.ticks(5);
401
413
  const stands = await mc.entities('@e[type=minecraft:armor_stand]');
402
414
  expect(stands.length).toBe(3);
@@ -538,21 +550,21 @@ describe('E2E Scenario Tests', () => {
538
550
  return;
539
551
  await mc.command('/function match_test:__load');
540
552
  // Test match on value 2
541
- await mc.command('/scoreboard players set $p0 rs 2');
553
+ await mc.command('/scoreboard players set $p0 __match_test 2');
542
554
  await mc.command('/function match_test:classify');
543
555
  await mc.ticks(5);
544
556
  let out = await mc.scoreboard('#match', 'out');
545
557
  expect(out).toBe(20);
546
558
  console.log(` match(2) → out=${out} (expect 20) ✓`);
547
559
  // Test match on value 3
548
- await mc.command('/scoreboard players set $p0 rs 3');
560
+ await mc.command('/scoreboard players set $p0 __match_test 3');
549
561
  await mc.command('/function match_test:classify');
550
562
  await mc.ticks(5);
551
563
  out = await mc.scoreboard('#match', 'out');
552
564
  expect(out).toBe(30);
553
565
  console.log(` match(3) → out=${out} (expect 30) ✓`);
554
566
  // Test default branch (value 99)
555
- await mc.command('/scoreboard players set $p0 rs 99');
567
+ await mc.command('/scoreboard players set $p0 __match_test 99');
556
568
  await mc.command('/function match_test:classify');
557
569
  await mc.ticks(5);
558
570
  out = await mc.scoreboard('#match', 'out');
@@ -714,7 +726,7 @@ describe('MC Integration - New Features', () => {
714
726
  expect(armorStands).toBe(2); // 2 armor_stands matched
715
727
  expect(items).toBe(1); // 1 item matched
716
728
  await mc.command('/function is_check_test:cleanup').catch(() => { });
717
- });
729
+ }, 30000); // extended timeout: entity spawn + reload can take >5 s
718
730
  test('event-test.mcrs: @on(PlayerDeath) compiles and loads', async () => {
719
731
  if (!serverOnline)
720
732
  return;