redscript-mc 1.0.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 (272) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +40 -0
  2. package/.github/ISSUE_TEMPLATE/feature_request.md +31 -0
  3. package/.github/ISSUE_TEMPLATE/wrong_output.md +33 -0
  4. package/.github/PULL_REQUEST_TEMPLATE.md +34 -0
  5. package/.github/workflows/ci.yml +29 -0
  6. package/.github/workflows/publish-extension.yml +35 -0
  7. package/LICENSE +21 -0
  8. package/README.md +261 -0
  9. package/README.zh.md +261 -0
  10. package/dist/__tests__/cli.test.d.ts +1 -0
  11. package/dist/__tests__/cli.test.js +140 -0
  12. package/dist/__tests__/codegen.test.d.ts +1 -0
  13. package/dist/__tests__/codegen.test.js +121 -0
  14. package/dist/__tests__/diagnostics.test.d.ts +4 -0
  15. package/dist/__tests__/diagnostics.test.js +149 -0
  16. package/dist/__tests__/e2e.test.d.ts +6 -0
  17. package/dist/__tests__/e2e.test.js +1528 -0
  18. package/dist/__tests__/lexer.test.d.ts +1 -0
  19. package/dist/__tests__/lexer.test.js +316 -0
  20. package/dist/__tests__/lowering.test.d.ts +1 -0
  21. package/dist/__tests__/lowering.test.js +819 -0
  22. package/dist/__tests__/mc-integration.test.d.ts +12 -0
  23. package/dist/__tests__/mc-integration.test.js +395 -0
  24. package/dist/__tests__/mc-syntax.test.d.ts +1 -0
  25. package/dist/__tests__/mc-syntax.test.js +112 -0
  26. package/dist/__tests__/nbt.test.d.ts +1 -0
  27. package/dist/__tests__/nbt.test.js +82 -0
  28. package/dist/__tests__/optimizer-advanced.test.d.ts +1 -0
  29. package/dist/__tests__/optimizer-advanced.test.js +124 -0
  30. package/dist/__tests__/optimizer.test.d.ts +1 -0
  31. package/dist/__tests__/optimizer.test.js +118 -0
  32. package/dist/__tests__/parser.test.d.ts +1 -0
  33. package/dist/__tests__/parser.test.js +717 -0
  34. package/dist/__tests__/repl.test.d.ts +1 -0
  35. package/dist/__tests__/repl.test.js +27 -0
  36. package/dist/__tests__/runtime.test.d.ts +1 -0
  37. package/dist/__tests__/runtime.test.js +276 -0
  38. package/dist/__tests__/structure-optimizer.test.d.ts +1 -0
  39. package/dist/__tests__/structure-optimizer.test.js +33 -0
  40. package/dist/__tests__/typechecker.test.d.ts +1 -0
  41. package/dist/__tests__/typechecker.test.js +364 -0
  42. package/dist/ast/types.d.ts +357 -0
  43. package/dist/ast/types.js +9 -0
  44. package/dist/cli.d.ts +11 -0
  45. package/dist/cli.js +407 -0
  46. package/dist/codegen/cmdblock/index.d.ts +26 -0
  47. package/dist/codegen/cmdblock/index.js +45 -0
  48. package/dist/codegen/mcfunction/index.d.ts +34 -0
  49. package/dist/codegen/mcfunction/index.js +413 -0
  50. package/dist/codegen/structure/index.d.ts +18 -0
  51. package/dist/codegen/structure/index.js +249 -0
  52. package/dist/compile.d.ts +30 -0
  53. package/dist/compile.js +152 -0
  54. package/dist/data/arena/function/__load.mcfunction +6 -0
  55. package/dist/data/arena/function/__tick.mcfunction +2 -0
  56. package/dist/data/arena/function/announce_leaders/else_1.mcfunction +3 -0
  57. package/dist/data/arena/function/announce_leaders/foreach_0/merge_2.mcfunction +1 -0
  58. package/dist/data/arena/function/announce_leaders/foreach_0/then_0.mcfunction +3 -0
  59. package/dist/data/arena/function/announce_leaders/foreach_0.mcfunction +7 -0
  60. package/dist/data/arena/function/announce_leaders/foreach_1/merge_2.mcfunction +1 -0
  61. package/dist/data/arena/function/announce_leaders/foreach_1/then_0.mcfunction +4 -0
  62. package/dist/data/arena/function/announce_leaders/foreach_1.mcfunction +6 -0
  63. package/dist/data/arena/function/announce_leaders/merge_2.mcfunction +1 -0
  64. package/dist/data/arena/function/announce_leaders/then_0.mcfunction +4 -0
  65. package/dist/data/arena/function/announce_leaders.mcfunction +6 -0
  66. package/dist/data/arena/function/arena_tick/merge_2.mcfunction +1 -0
  67. package/dist/data/arena/function/arena_tick/then_0.mcfunction +4 -0
  68. package/dist/data/arena/function/arena_tick.mcfunction +11 -0
  69. package/dist/data/counter/function/__load.mcfunction +5 -0
  70. package/dist/data/counter/function/__tick.mcfunction +2 -0
  71. package/dist/data/counter/function/counter_tick/merge_2.mcfunction +1 -0
  72. package/dist/data/counter/function/counter_tick/then_0.mcfunction +3 -0
  73. package/dist/data/counter/function/counter_tick.mcfunction +11 -0
  74. package/dist/data/minecraft/tags/function/load.json +5 -0
  75. package/dist/data/minecraft/tags/function/tick.json +5 -0
  76. package/dist/data/quiz/function/__load.mcfunction +16 -0
  77. package/dist/data/quiz/function/__tick.mcfunction +6 -0
  78. package/dist/data/quiz/function/__trigger_quiz_a_dispatch.mcfunction +4 -0
  79. package/dist/data/quiz/function/__trigger_quiz_b_dispatch.mcfunction +4 -0
  80. package/dist/data/quiz/function/__trigger_quiz_c_dispatch.mcfunction +4 -0
  81. package/dist/data/quiz/function/__trigger_quiz_start_dispatch.mcfunction +4 -0
  82. package/dist/data/quiz/function/answer_a.mcfunction +4 -0
  83. package/dist/data/quiz/function/answer_b.mcfunction +4 -0
  84. package/dist/data/quiz/function/answer_c.mcfunction +4 -0
  85. package/dist/data/quiz/function/ask_question/else_1.mcfunction +5 -0
  86. package/dist/data/quiz/function/ask_question/else_4.mcfunction +5 -0
  87. package/dist/data/quiz/function/ask_question/else_7.mcfunction +4 -0
  88. package/dist/data/quiz/function/ask_question/merge_2.mcfunction +1 -0
  89. package/dist/data/quiz/function/ask_question/merge_5.mcfunction +2 -0
  90. package/dist/data/quiz/function/ask_question/merge_8.mcfunction +2 -0
  91. package/dist/data/quiz/function/ask_question/then_0.mcfunction +4 -0
  92. package/dist/data/quiz/function/ask_question/then_3.mcfunction +4 -0
  93. package/dist/data/quiz/function/ask_question/then_6.mcfunction +4 -0
  94. package/dist/data/quiz/function/ask_question.mcfunction +7 -0
  95. package/dist/data/quiz/function/finish_quiz.mcfunction +6 -0
  96. package/dist/data/quiz/function/handle_answer/else_1.mcfunction +5 -0
  97. package/dist/data/quiz/function/handle_answer/else_10.mcfunction +3 -0
  98. package/dist/data/quiz/function/handle_answer/else_16.mcfunction +3 -0
  99. package/dist/data/quiz/function/handle_answer/else_4.mcfunction +3 -0
  100. package/dist/data/quiz/function/handle_answer/else_7.mcfunction +5 -0
  101. package/dist/data/quiz/function/handle_answer/merge_11.mcfunction +2 -0
  102. package/dist/data/quiz/function/handle_answer/merge_14.mcfunction +2 -0
  103. package/dist/data/quiz/function/handle_answer/merge_17.mcfunction +2 -0
  104. package/dist/data/quiz/function/handle_answer/merge_2.mcfunction +8 -0
  105. package/dist/data/quiz/function/handle_answer/merge_5.mcfunction +2 -0
  106. package/dist/data/quiz/function/handle_answer/merge_8.mcfunction +2 -0
  107. package/dist/data/quiz/function/handle_answer/then_0.mcfunction +5 -0
  108. package/dist/data/quiz/function/handle_answer/then_12.mcfunction +5 -0
  109. package/dist/data/quiz/function/handle_answer/then_15.mcfunction +6 -0
  110. package/dist/data/quiz/function/handle_answer/then_3.mcfunction +6 -0
  111. package/dist/data/quiz/function/handle_answer/then_6.mcfunction +5 -0
  112. package/dist/data/quiz/function/handle_answer/then_9.mcfunction +6 -0
  113. package/dist/data/quiz/function/handle_answer.mcfunction +11 -0
  114. package/dist/data/quiz/function/start_quiz.mcfunction +5 -0
  115. package/dist/data/shop/function/__load.mcfunction +7 -0
  116. package/dist/data/shop/function/__tick.mcfunction +3 -0
  117. package/dist/data/shop/function/__trigger_shop_buy_dispatch.mcfunction +4 -0
  118. package/dist/data/shop/function/complete_purchase/else_1.mcfunction +5 -0
  119. package/dist/data/shop/function/complete_purchase/else_4.mcfunction +5 -0
  120. package/dist/data/shop/function/complete_purchase/else_7.mcfunction +3 -0
  121. package/dist/data/shop/function/complete_purchase/merge_2.mcfunction +2 -0
  122. package/dist/data/shop/function/complete_purchase/merge_5.mcfunction +2 -0
  123. package/dist/data/shop/function/complete_purchase/merge_8.mcfunction +2 -0
  124. package/dist/data/shop/function/complete_purchase/then_0.mcfunction +4 -0
  125. package/dist/data/shop/function/complete_purchase/then_3.mcfunction +4 -0
  126. package/dist/data/shop/function/complete_purchase/then_6.mcfunction +4 -0
  127. package/dist/data/shop/function/complete_purchase.mcfunction +7 -0
  128. package/dist/data/shop/function/handle_shop_trigger.mcfunction +3 -0
  129. package/dist/data/turret/function/__load.mcfunction +5 -0
  130. package/dist/data/turret/function/__tick.mcfunction +4 -0
  131. package/dist/data/turret/function/__trigger_deploy_turret_dispatch.mcfunction +4 -0
  132. package/dist/data/turret/function/deploy_turret.mcfunction +8 -0
  133. package/dist/data/turret/function/turret_tick/at_1.mcfunction +2 -0
  134. package/dist/data/turret/function/turret_tick/foreach_0.mcfunction +2 -0
  135. package/dist/data/turret/function/turret_tick/foreach_2.mcfunction +2 -0
  136. package/dist/data/turret/function/turret_tick/tick_body.mcfunction +3 -0
  137. package/dist/data/turret/function/turret_tick/tick_skip.mcfunction +1 -0
  138. package/dist/data/turret/function/turret_tick.mcfunction +5 -0
  139. package/dist/diagnostics/index.d.ts +44 -0
  140. package/dist/diagnostics/index.js +140 -0
  141. package/dist/index.d.ts +53 -0
  142. package/dist/index.js +126 -0
  143. package/dist/ir/builder.d.ts +32 -0
  144. package/dist/ir/builder.js +99 -0
  145. package/dist/ir/types.d.ts +117 -0
  146. package/dist/ir/types.js +15 -0
  147. package/dist/lexer/index.d.ts +36 -0
  148. package/dist/lexer/index.js +458 -0
  149. package/dist/lowering/index.d.ts +106 -0
  150. package/dist/lowering/index.js +2041 -0
  151. package/dist/mc-test/client.d.ts +128 -0
  152. package/dist/mc-test/client.js +174 -0
  153. package/dist/mc-test/runner.d.ts +28 -0
  154. package/dist/mc-test/runner.js +150 -0
  155. package/dist/mc-test/setup.d.ts +11 -0
  156. package/dist/mc-test/setup.js +98 -0
  157. package/dist/mc-validator/index.d.ts +17 -0
  158. package/dist/mc-validator/index.js +322 -0
  159. package/dist/nbt/index.d.ts +86 -0
  160. package/dist/nbt/index.js +250 -0
  161. package/dist/optimizer/commands.d.ts +36 -0
  162. package/dist/optimizer/commands.js +349 -0
  163. package/dist/optimizer/passes.d.ts +34 -0
  164. package/dist/optimizer/passes.js +227 -0
  165. package/dist/optimizer/structure.d.ts +8 -0
  166. package/dist/optimizer/structure.js +344 -0
  167. package/dist/pack.mcmeta +6 -0
  168. package/dist/parser/index.d.ts +76 -0
  169. package/dist/parser/index.js +1193 -0
  170. package/dist/repl.d.ts +16 -0
  171. package/dist/repl.js +165 -0
  172. package/dist/runtime/index.d.ts +101 -0
  173. package/dist/runtime/index.js +1288 -0
  174. package/dist/typechecker/index.d.ts +42 -0
  175. package/dist/typechecker/index.js +629 -0
  176. package/docs/COMPILATION_STATS.md +142 -0
  177. package/docs/IMPLEMENTATION_GUIDE.md +512 -0
  178. package/docs/LANGUAGE_REFERENCE.md +415 -0
  179. package/docs/MC_MAPPING.md +280 -0
  180. package/docs/STRUCTURE_TARGET.md +80 -0
  181. package/docs/mc-reference/commands.md +259 -0
  182. package/editors/vscode/.vscodeignore +10 -0
  183. package/editors/vscode/LICENSE +21 -0
  184. package/editors/vscode/README.md +78 -0
  185. package/editors/vscode/build.mjs +28 -0
  186. package/editors/vscode/icon.png +0 -0
  187. package/editors/vscode/mcfunction-language-configuration.json +28 -0
  188. package/editors/vscode/out/extension.js +7236 -0
  189. package/editors/vscode/package-lock.json +566 -0
  190. package/editors/vscode/package.json +137 -0
  191. package/editors/vscode/redscript-language-configuration.json +28 -0
  192. package/editors/vscode/snippets/redscript.json +114 -0
  193. package/editors/vscode/src/codeactions.ts +89 -0
  194. package/editors/vscode/src/completion.ts +130 -0
  195. package/editors/vscode/src/extension.ts +239 -0
  196. package/editors/vscode/src/hover.ts +1120 -0
  197. package/editors/vscode/src/symbols.ts +207 -0
  198. package/editors/vscode/syntaxes/mcfunction.tmLanguage.json +740 -0
  199. package/editors/vscode/syntaxes/redscript.tmLanguage.json +357 -0
  200. package/editors/vscode/tsconfig.json +13 -0
  201. package/jest.config.js +5 -0
  202. package/package.json +38 -0
  203. package/src/__tests__/cli.test.ts +130 -0
  204. package/src/__tests__/codegen.test.ts +128 -0
  205. package/src/__tests__/diagnostics.test.ts +195 -0
  206. package/src/__tests__/e2e.test.ts +1721 -0
  207. package/src/__tests__/fixtures/mc-commands-1.21.4.json +18734 -0
  208. package/src/__tests__/formatter.test.ts +46 -0
  209. package/src/__tests__/lexer.test.ts +356 -0
  210. package/src/__tests__/lowering.test.ts +962 -0
  211. package/src/__tests__/mc-integration.test.ts +409 -0
  212. package/src/__tests__/mc-syntax.test.ts +96 -0
  213. package/src/__tests__/nbt.test.ts +58 -0
  214. package/src/__tests__/optimizer-advanced.test.ts +144 -0
  215. package/src/__tests__/optimizer.test.ts +129 -0
  216. package/src/__tests__/parser.test.ts +800 -0
  217. package/src/__tests__/repl.test.ts +33 -0
  218. package/src/__tests__/runtime.test.ts +289 -0
  219. package/src/__tests__/structure-optimizer.test.ts +38 -0
  220. package/src/__tests__/typechecker.test.ts +395 -0
  221. package/src/ast/types.ts +248 -0
  222. package/src/cli.ts +445 -0
  223. package/src/codegen/cmdblock/index.ts +63 -0
  224. package/src/codegen/mcfunction/index.ts +471 -0
  225. package/src/codegen/structure/index.ts +305 -0
  226. package/src/compile.ts +188 -0
  227. package/src/diagnostics/index.ts +186 -0
  228. package/src/examples/README.md +77 -0
  229. package/src/examples/SHOWCASE_GAME.md +43 -0
  230. package/src/examples/arena.rs +44 -0
  231. package/src/examples/counter.rs +12 -0
  232. package/src/examples/pvp_arena.rs +131 -0
  233. package/src/examples/quiz.rs +90 -0
  234. package/src/examples/rpg.rs +13 -0
  235. package/src/examples/shop.rs +30 -0
  236. package/src/examples/showcase_game.rs +552 -0
  237. package/src/examples/stdlib_demo.rs +181 -0
  238. package/src/examples/turret.rs +27 -0
  239. package/src/examples/world_manager.rs +23 -0
  240. package/src/formatter/index.ts +22 -0
  241. package/src/index.ts +161 -0
  242. package/src/ir/builder.ts +114 -0
  243. package/src/ir/types.ts +119 -0
  244. package/src/lexer/index.ts +555 -0
  245. package/src/lowering/index.ts +2406 -0
  246. package/src/mc-test/client.ts +259 -0
  247. package/src/mc-test/runner.ts +140 -0
  248. package/src/mc-test/setup.ts +70 -0
  249. package/src/mc-validator/index.ts +367 -0
  250. package/src/nbt/index.ts +321 -0
  251. package/src/optimizer/commands.ts +416 -0
  252. package/src/optimizer/passes.ts +233 -0
  253. package/src/optimizer/structure.ts +441 -0
  254. package/src/parser/index.ts +1437 -0
  255. package/src/repl.ts +165 -0
  256. package/src/runtime/index.ts +1403 -0
  257. package/src/stdlib/README.md +156 -0
  258. package/src/stdlib/combat.rs +20 -0
  259. package/src/stdlib/cooldown.rs +45 -0
  260. package/src/stdlib/math.rs +49 -0
  261. package/src/stdlib/mobs.rs +99 -0
  262. package/src/stdlib/player.rs +29 -0
  263. package/src/stdlib/strings.rs +7 -0
  264. package/src/stdlib/timer.rs +51 -0
  265. package/src/templates/README.md +126 -0
  266. package/src/templates/combat.rs +96 -0
  267. package/src/templates/economy.rs +40 -0
  268. package/src/templates/mini-game-framework.rs +117 -0
  269. package/src/templates/quest.rs +78 -0
  270. package/src/test_programs/zombie_game.rs +25 -0
  271. package/src/typechecker/index.ts +737 -0
  272. package/tsconfig.json +16 -0
@@ -0,0 +1,415 @@
1
+ # RedScript Language Reference
2
+
3
+ This document describes the syntax RedScript accepts today.
4
+
5
+ ## Program Structure
6
+
7
+ A source file may optionally declare a namespace, followed by any number of `struct` and `fn` declarations.
8
+
9
+ ```rs
10
+ namespace turret;
11
+
12
+ struct TurretState { health: int }
13
+
14
+ fn main() {}
15
+ ```
16
+
17
+ If no namespace is provided, the CLI derives one from the filename or uses the compile option you pass.
18
+
19
+ ## Types
20
+
21
+ RedScript currently supports these primitive types:
22
+
23
+ | Type | Notes |
24
+ |:--|:--|
25
+ | `int` | Scoreboard-backed integer values |
26
+ | `bool` | Lowered as `0` or `1` |
27
+ | `float` | Fixed-point values scaled by `1000` |
28
+ | `string` | Used primarily in builtin calls |
29
+ | `void` | Function return type when no value is produced |
30
+
31
+ Composite types:
32
+
33
+ | Type form | Example |
34
+ |:--|:--|
35
+ | Struct | `TurretState` |
36
+ | Array | `int[]`, `string[]` |
37
+
38
+ ### Variables
39
+
40
+ ```rs
41
+ let hp: int = 20;
42
+ let enabled: bool = true;
43
+ let speed: float = 1.5;
44
+ let name: string = "turret";
45
+ let numbers: int[] = [1, 2, 3];
46
+ ```
47
+
48
+ Type annotations are supported on `let` bindings and function parameters. Function return types use `->`.
49
+
50
+ ## Functions
51
+
52
+ Functions use C-style syntax and may return values.
53
+
54
+ ```rs
55
+ fn add(a: int, b: int) -> int {
56
+ return a + b;
57
+ }
58
+
59
+ fn announce() {
60
+ say("Ready");
61
+ }
62
+ ```
63
+
64
+ Rules:
65
+
66
+ - Parameters are positional.
67
+ - A missing return type defaults to `void`.
68
+ - `return;` is valid in `void` functions.
69
+ - Function calls are synchronous and compile to `function <namespace>:<name>`.
70
+
71
+ ## Control Flow
72
+
73
+ ### `if` / `else`
74
+
75
+ ```rs
76
+ fn reward(kills: int) {
77
+ if (kills >= 10) {
78
+ give(@s, "minecraft:diamond", 1);
79
+ } else {
80
+ tell(@s, "Keep going.");
81
+ }
82
+ }
83
+ ```
84
+
85
+ `else if` chains are expressed as nested `if` inside `else`.
86
+
87
+ ### `while`
88
+
89
+ ```rs
90
+ fn countdown() {
91
+ let n: int = 5;
92
+ while (n > 0) {
93
+ n -= 1;
94
+ }
95
+ }
96
+ ```
97
+
98
+ ### `for`
99
+
100
+ RedScript supports C-style `for` loops.
101
+
102
+ ```rs
103
+ fn repeat() {
104
+ for (let i: int = 0; i < 5; i += 1) {
105
+ say("tick");
106
+ }
107
+ }
108
+ ```
109
+
110
+ The initializer is optional, and compound assignment is supported in the step clause.
111
+
112
+ ### `foreach`
113
+
114
+ `foreach` iterates over a selector by extracting the body into a helper function and running it with `execute as ... run function ...`.
115
+
116
+ ```rs
117
+ fn notify_players() {
118
+ foreach (player in @a) {
119
+ title(player, "Fight!");
120
+ }
121
+ }
122
+ ```
123
+
124
+ Inside the loop body, the bound variable refers to the current entity context.
125
+
126
+ ## Structs
127
+
128
+ Structs group fields and are stored in Minecraft storage.
129
+
130
+ ```rs
131
+ struct TurretState {
132
+ health: int,
133
+ level: int
134
+ }
135
+
136
+ fn create() {
137
+ let state: TurretState = { health: 40, level: 1 };
138
+ state.health = 50;
139
+ let hp = state.health;
140
+ }
141
+ ```
142
+
143
+ Supported operations:
144
+
145
+ - Struct declaration
146
+ - Struct literals
147
+ - Field read
148
+ - Field assignment
149
+ - Compound assignment on fields such as `state.health += 5`
150
+
151
+ ## Arrays
152
+
153
+ Arrays are currently backed by Minecraft storage.
154
+
155
+ ```rs
156
+ fn sample() {
157
+ let nums: int[] = [1, 2, 3];
158
+ nums.push(4);
159
+ let first = nums[0];
160
+ }
161
+ ```
162
+
163
+ Current support includes:
164
+
165
+ - Empty arrays: `[]`
166
+ - Array literals with initial values
167
+ - `push(...)`
168
+ - Index reads such as `arr[0]`
169
+
170
+ ## Decorators
171
+
172
+ Decorators attach runtime behavior to functions.
173
+
174
+ ### `@tick`
175
+
176
+ Runs every game tick through the generated `__tick.mcfunction`.
177
+
178
+ ```rs
179
+ @tick
180
+ fn heartbeat() {
181
+ say("tick");
182
+ }
183
+ ```
184
+
185
+ ### `@tick(rate=N)`
186
+
187
+ Runs every `N` ticks using a generated scoreboard counter.
188
+
189
+ ```rs
190
+ @tick(rate=20)
191
+ fn once_per_second() {
192
+ say("1 second");
193
+ }
194
+ ```
195
+
196
+ ### `@on_trigger("name")`
197
+
198
+ Generates trigger plumbing for `/trigger name`.
199
+
200
+ ```rs
201
+ @on_trigger("shop_buy")
202
+ fn handle_shop() {
203
+ complete_purchase();
204
+ }
205
+ ```
206
+
207
+ The compiler creates:
208
+
209
+ - a trigger objective in `__load.mcfunction`
210
+ - a dispatch function
211
+ - trigger checks inside `__tick.mcfunction`
212
+
213
+ ## Execute Context
214
+
215
+ RedScript supports both shorthand context blocks and explicit `execute ... run { ... }`.
216
+
217
+ ### `as`
218
+
219
+ ```rs
220
+ as @a {
221
+ say("Hello from each player");
222
+ }
223
+ ```
224
+
225
+ ### `at`
226
+
227
+ ```rs
228
+ at @s {
229
+ summon("zombie", "~", "~", "~");
230
+ }
231
+ ```
232
+
233
+ ### Combined `as` and `at`
234
+
235
+ ```rs
236
+ as @a at @s {
237
+ particle("flame", "~", "~", "~");
238
+ }
239
+ ```
240
+
241
+ ### `execute ... run { ... }`
242
+
243
+ Supported subcommands today:
244
+
245
+ - `as <selector>`
246
+ - `at <selector>`
247
+ - `if entity <selector>`
248
+ - `unless entity <selector>`
249
+ - `in <dimension>`
250
+
251
+ Examples:
252
+
253
+ ```rs
254
+ execute as @a run {
255
+ say("Hello");
256
+ }
257
+
258
+ execute as @a at @s run {
259
+ particle("flame", "~", "~", "~");
260
+ }
261
+
262
+ execute as @a if entity @s[tag=admin] run {
263
+ give(@s, "minecraft:diamond", 1);
264
+ }
265
+
266
+ execute as @a unless entity @s[tag=dead] run {
267
+ effect(@s, "regeneration", 5);
268
+ }
269
+
270
+ execute as @a at @s if entity @s[tag=vip] in overworld run {
271
+ title(@s, "VIP");
272
+ }
273
+ ```
274
+
275
+ ## Selectors
276
+
277
+ Entity selectors are first-class expressions and can be passed directly to builtins.
278
+
279
+ ### Supported selector heads
280
+
281
+ | Selector | Meaning |
282
+ |:--|:--|
283
+ | `@a` | All players |
284
+ | `@e` | All entities |
285
+ | `@s` | Current executor |
286
+ | `@p` | Nearest player |
287
+
288
+ ### Common filters
289
+
290
+ ```rs
291
+ @e[type=zombie]
292
+ @e[type=zombie, distance=..8]
293
+ @e[type=armor_stand, tag=turret]
294
+ @a[scores={kills=10..}]
295
+ @p[distance=..5]
296
+ ```
297
+
298
+ Supported filter categories in the current parser:
299
+
300
+ - `type`
301
+ - `distance` with ranges such as `..5`, `1..`, `1..10`
302
+ - `tag`
303
+ - score filters
304
+ - `limit`
305
+ - `sort`
306
+ - `nbt`
307
+ - `gamemode`
308
+
309
+ ## Coordinates
310
+
311
+ Block positions are first-class values with the `BlockPos` type.
312
+
313
+ ### Absolute coordinates
314
+
315
+ ```rs
316
+ let spawn: BlockPos = (0, 64, 0);
317
+ setblock((4, 65, 4), "minecraft:gold_block");
318
+ ```
319
+
320
+ ### Relative coordinates
321
+
322
+ ```rs
323
+ tp(@s, (~1, ~0, ~-1));
324
+ ```
325
+
326
+ ### Local coordinates
327
+
328
+ ```rs
329
+ tp(@s, (^0, ^1, ^0));
330
+ ```
331
+
332
+ ### Mixed coordinates
333
+
334
+ ```rs
335
+ setblock((~0, 64, ~0), "minecraft:stone");
336
+ ```
337
+
338
+ Each component can be:
339
+
340
+ - an absolute integer like `64`
341
+ - a relative coordinate like `~` or `~-2`
342
+ - a local coordinate like `^` or `^3`
343
+
344
+ ## Builtins
345
+
346
+ The compiler recognizes these builtins and lowers them directly to Minecraft commands or runtime helpers.
347
+
348
+ | Builtin | Returns | Notes |
349
+ |:--|:--|:--|
350
+ | `say(msg)` | `void` | Emits `say` |
351
+ | `tell(sel, msg)` | `void` | Emits `tellraw` with a plain text JSON component |
352
+ | `title(sel, msg)` | `void` | Emits `title <sel> title` |
353
+ | `give(sel, item, count?)` | `void` | Default count is `1` |
354
+ | `effect(sel, effect, duration?, amplifier?)` | `void` | Defaults: duration `30`, amplifier `0` |
355
+ | `summon(type, x?, y?, z?, nbt?)` | `void` | Defaults position to `~ ~ ~` |
356
+ | `particle(name, x?, y?, z?)` | `void` | Defaults position to `~ ~ ~` |
357
+ | `tp(sel, x?, y?, z?)` | `void` | Also accepts `tp(sel, pos)` with `BlockPos` |
358
+ | `setblock(x, y, z, block)` | `void` | Also accepts `setblock(pos, block)` with `BlockPos` |
359
+ | `fill(x1, y1, z1, x2, y2, z2, block)` | `void` | Also accepts `fill(from, to, block)` with `BlockPos` |
360
+ | `clone(x1, y1, z1, x2, y2, z2, dx, dy, dz)` | `void` | Also accepts `clone(from, to, dest)` with `BlockPos` |
361
+ | `kill(sel?)` | `void` | Defaults to `@s` |
362
+ | `scoreboard_get(target, objective)` | `int` | Reads a scoreboard score |
363
+ | `score(target, objective)` | `int` | Alias of `scoreboard_get` |
364
+ | `scoreboard_set(target, objective, value)` | `void` | Writes a scoreboard score |
365
+ | `data_get(kind, target, path, scale?)` | `int` | Reads NBT with `data get` |
366
+ | `random(min, max)` | `int` | Uses `scoreboard players random` for pre-1.20.3 compatibility |
367
+ | `random_native(min, max)` | `int` | Uses `/random value <min> <max>` (MC 1.20.3+) |
368
+ | `random_sequence(sequence, seed?)` | `void` | Uses `/random reset <sequence> <seed>`; default seed is `0` (MC 1.20.3+) |
369
+ | `spawn_object(x, y, z)` | world object handle | Spawns an invisible armor stand with generated tags |
370
+ | `raw(cmd)` | `void` | Emits a literal Minecraft command |
371
+
372
+ ### Entity helper methods
373
+
374
+ These are written as member calls on selectors or spawned object handles:
375
+
376
+ | Method | Returns | Example |
377
+ |:--|:--|:--|
378
+ | `entity.tag(name)` | `void` | `@s.tag("boss");` |
379
+ | `entity.untag(name)` | `void` | `@s.untag("boss");` |
380
+ | `entity.has_tag(name)` | `bool` | `let boss: bool = @s.has_tag("boss");` |
381
+
382
+ ## Operators
383
+
384
+ Arithmetic and comparison operators:
385
+
386
+ - `+`, `-`, `*`, `/`, `%`
387
+ - `==`, `!=`, `<`, `<=`, `>`, `>=`
388
+ - `&&`, `||`
389
+ - unary `-`, `!`
390
+
391
+ Assignment operators:
392
+
393
+ - `=`
394
+ - `+=`
395
+ - `-=`
396
+ - `*=`
397
+ - `/=`
398
+ - `%=`
399
+
400
+ ## Raw Commands
401
+
402
+ Use `raw(...)` when you need an escape hatch for a command RedScript does not model directly.
403
+
404
+ ```rs
405
+ fn admin() {
406
+ raw("gamemode creative @a");
407
+ }
408
+ ```
409
+
410
+ ## Notes on Numeric Semantics
411
+
412
+ - `int` values map directly to scoreboard integers.
413
+ - `bool` is lowered as integer `0` or `1`.
414
+ - `float` is stored as fixed-point `value * 1000`.
415
+ - String values are currently most useful as builtin arguments rather than general-purpose data values.
@@ -0,0 +1,280 @@
1
+ # RedScript to Minecraft Mapping
2
+
3
+ This document explains how the compiler maps RedScript constructs onto Minecraft commands and generated files.
4
+
5
+ ## Pipeline Overview
6
+
7
+ The compiler pipeline is:
8
+
9
+ ```text
10
+ Lexer -> Parser -> AST -> IR Lowering -> Optimizer -> CodeGen
11
+ ```
12
+
13
+ The lowering stage converts RedScript syntax into a simple three-address IR. The optimizer rewrites that IR, and code generation emits datapack files or command block JSON.
14
+
15
+ ## Variables
16
+
17
+ ### Local scalar variables
18
+
19
+ Scalar locals such as `int`, `bool`, and fixed-point `float` values are stored as scoreboard entries on the `rs` objective.
20
+
21
+ Example RedScript:
22
+
23
+ ```rs
24
+ fn sample() {
25
+ let x: int = 42;
26
+ }
27
+ ```
28
+
29
+ Typical generated command pattern:
30
+
31
+ ```mcfunction
32
+ scoreboard players set $x rs 42
33
+ ```
34
+
35
+ The compiler uses fake-player names such as:
36
+
37
+ - `$x`
38
+ - `$t0`
39
+ - `$ret`
40
+
41
+ This keeps temporary values and user variables addressable through standard scoreboard operations.
42
+
43
+ ### Booleans
44
+
45
+ Booleans are represented as:
46
+
47
+ - `0` for false
48
+ - `1` for true
49
+
50
+ Conditions are compiled into `execute if score ... matches 1..` style checks.
51
+
52
+ ### Floats
53
+
54
+ `float` values are stored as fixed-point integers scaled by `1000`.
55
+
56
+ Example:
57
+
58
+ ```rs
59
+ let speed: float = 1.5;
60
+ ```
61
+
62
+ becomes an internal scoreboard value of `1500`.
63
+
64
+ Multiplication and division insert scaling correction steps during lowering so arithmetic remains approximately correct under the fixed-point scheme.
65
+
66
+ ## Functions
67
+
68
+ Each RedScript function becomes one or more `.mcfunction` files in the generated namespace.
69
+
70
+ Example:
71
+
72
+ ```rs
73
+ fn reward_player() {
74
+ give(@s, "minecraft:diamond", 1);
75
+ }
76
+ ```
77
+
78
+ becomes a datapack function like:
79
+
80
+ ```text
81
+ data/<namespace>/function/reward_player.mcfunction
82
+ ```
83
+
84
+ Function calls map to Minecraft `function` commands:
85
+
86
+ ```mcfunction
87
+ function <namespace>:reward_player
88
+ ```
89
+
90
+ The compiler also generates runtime entrypoints such as:
91
+
92
+ - `__load.mcfunction`
93
+ - `__tick.mcfunction`
94
+ - trigger dispatch helpers like `__trigger_<name>_dispatch.mcfunction`
95
+
96
+ ## Control Flow
97
+
98
+ RedScript control flow is lowered into basic blocks and conditional jumps, then emitted as `execute if score ... run function ...` patterns.
99
+
100
+ Examples:
101
+
102
+ - `if` creates conditional branches plus merge blocks.
103
+ - `while` and `for` create explicit loop check, body, and exit blocks.
104
+ - `foreach` extracts the loop body into a helper function and runs it with `execute as <selector> run function ...`.
105
+
106
+ ## Selectors and Execution Context
107
+
108
+ Selectors such as `@a`, `@e[type=zombie]`, and `@s` are preserved directly in emitted commands.
109
+
110
+ Context blocks map as follows:
111
+
112
+ | RedScript | Minecraft form |
113
+ |:--|:--|
114
+ | `as @a { ... }` | `execute as @a run function ...` |
115
+ | `at @s { ... }` | `execute at @s run function ...` |
116
+ | `execute as @a if entity @s[tag=vip] run { ... }` | `execute as @a if entity @s[tag=vip] run function ...` |
117
+
118
+ The body is extracted into a helper `.mcfunction` so the generated `execute` command stays simple and composable.
119
+
120
+ ## Builtins
121
+
122
+ Many RedScript builtins compile almost directly to one Minecraft command.
123
+
124
+ Examples:
125
+
126
+ | RedScript | Generated command pattern |
127
+ |:--|:--|
128
+ | `say("Hello")` | `say Hello` |
129
+ | `give(@s, "minecraft:bread", 1)` | `give @s minecraft:bread 1` |
130
+ | `kill(@e[type=zombie])` | `kill @e[type=zombie]` |
131
+ | `title(@a, "Fight!")` | `title @a title {"text":"Fight!"}` |
132
+ | `scoreboard_set(@s, "kills", 5)` | `scoreboard players set @s kills 5` |
133
+
134
+ Other builtins need special lowering:
135
+
136
+ - `scoreboard_get(...)` reads a scoreboard into a compiler-managed temp variable.
137
+ - `data_get(...)` uses `execute store result score ... run data get ...`.
138
+ - `random(...)` uses `scoreboard players random` for legacy compatibility.
139
+ - `random_native(...)` uses `/random value <min> <max>` on MC 1.20.3+.
140
+ - `random_sequence(...)` uses `/random reset <sequence> <seed>` on MC 1.20.3+.
141
+ - `spawn_object(...)` spawns an invisible armor stand and returns a selector handle.
142
+
143
+ ## Structs
144
+
145
+ Structs are stored in Minecraft storage under `rs:heap`.
146
+
147
+ Example:
148
+
149
+ ```rs
150
+ struct Point { x: int, y: int }
151
+
152
+ fn test() {
153
+ let p: Point = { x: 10, y: 20 };
154
+ p.x = 30;
155
+ }
156
+ ```
157
+
158
+ Typical generated patterns:
159
+
160
+ ```mcfunction
161
+ data modify storage rs:heap point_p.x set value 10
162
+ data modify storage rs:heap point_p.y set value 20
163
+ data modify storage rs:heap point_p.x set value 30
164
+ ```
165
+
166
+ Field reads use `data get storage ...` together with `execute store result score ...`.
167
+
168
+ ## Arrays
169
+
170
+ Arrays are represented with Minecraft storage and currently behave like NBT-backed collections.
171
+
172
+ Example:
173
+
174
+ ```rs
175
+ let arr: int[] = [1, 2, 3];
176
+ arr.push(4);
177
+ let first = arr[0];
178
+ ```
179
+
180
+ Typical generated patterns:
181
+
182
+ ```mcfunction
183
+ data modify storage rs:heap arr set value []
184
+ data modify storage rs:heap arr append value 1
185
+ data modify storage rs:heap arr append value 2
186
+ data modify storage rs:heap arr append value 3
187
+ data modify storage rs:heap arr append value 4
188
+ ```
189
+
190
+ This part of the storage model is still evolving, so larger collection features should be treated as early-stage compared with scalar scoreboard variables.
191
+
192
+ ## World Objects
193
+
194
+ `spawn_object(...)` creates an invisible marker armor stand and uses tags plus scoreboards to model a world-backed object.
195
+
196
+ Example:
197
+
198
+ ```rs
199
+ let turret = spawn_object(0, 64, 0);
200
+ turret.health = 100;
201
+ turret.tag("turret");
202
+ ```
203
+
204
+ Typical generated behavior:
205
+
206
+ - summon an armor stand with tags like `__rs_obj_<n>`
207
+ - address it with a selector such as `@e[tag=__rs_obj_<n>,limit=1]`
208
+ - map field writes to scoreboard or storage operations
209
+ - map `tag(...)` and `untag(...)` to the vanilla `tag` command
210
+
211
+ ## Tick and Trigger Decorators
212
+
213
+ ### `@tick`
214
+
215
+ Tick handlers are registered through `data/minecraft/tags/function/tick.json` and invoked from `__tick.mcfunction`.
216
+
217
+ ### `@tick(rate=N)`
218
+
219
+ Rate-limited tick handlers get an extra scoreboard counter. The compiler inserts logic equivalent to:
220
+
221
+ 1. increment the counter every tick
222
+ 2. check whether it has reached `N`
223
+ 3. reset it when the body runs
224
+
225
+ ### `@on_trigger("name")`
226
+
227
+ Trigger handlers generate:
228
+
229
+ - `scoreboard objectives add <name> trigger` in `__load.mcfunction`
230
+ - trigger checks in `__tick.mcfunction`
231
+ - a dispatch function that calls the user handler and clears the trigger score
232
+
233
+ ## Command Block Target
234
+
235
+ In command block mode, the compiler emits a JSON description for command block placement instead of a datapack directory. This is meant for command-block-based setups while reusing the same frontend, lowering, and optimization pipeline.
236
+
237
+ ## Optimizations
238
+
239
+ The optimizer currently includes three core passes.
240
+
241
+ ### Constant folding
242
+
243
+ Compile-time constant expressions are evaluated early.
244
+
245
+ Example:
246
+
247
+ ```rs
248
+ return 2 + 3;
249
+ ```
250
+
251
+ is simplified to an IR constant equivalent to `5`.
252
+
253
+ ### Copy propagation
254
+
255
+ Redundant temporaries are removed when values can be forwarded safely.
256
+
257
+ Example idea:
258
+
259
+ ```rs
260
+ let x: int = 10;
261
+ let y: int = x;
262
+ return y;
263
+ ```
264
+
265
+ can emit fewer scoreboard moves because `y` can reuse the known value of `x`.
266
+
267
+ ### Dead code elimination
268
+
269
+ Assignments whose results are never read are removed before code generation. This reduces scoreboard churn and helps keep generated datapacks smaller and easier to inspect.
270
+
271
+ ## Practical Consequences
272
+
273
+ The mapping strategy is intentionally pragmatic:
274
+
275
+ - scoreboard storage is fast and predictable for scalar logic
276
+ - storage-backed structs and arrays handle composite data
277
+ - helper functions keep `execute`-heavy control flow manageable
278
+ - optimization passes reduce unnecessary commands before codegen
279
+
280
+ That combination is what lets RedScript express higher-level gameplay logic while still compiling to vanilla Minecraft primitives.