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,2 @@
1
+ # block: merge_5
2
+ function shop:complete_purchase/merge_2
@@ -0,0 +1,2 @@
1
+ # block: merge_8
2
+ function shop:complete_purchase/merge_5
@@ -0,0 +1,4 @@
1
+ # block: then_0
2
+ give @s minecraft:bread 1
3
+ tellraw @s {"text":"You bought bread."}
4
+ function shop:complete_purchase/merge_2
@@ -0,0 +1,4 @@
1
+ # block: then_3
2
+ give @s minecraft:steak 1
3
+ tellraw @s {"text":"You bought steak."}
4
+ function shop:complete_purchase/merge_5
@@ -0,0 +1,4 @@
1
+ # block: then_6
2
+ give @s minecraft:diamond 1
3
+ tellraw @s {"text":"You bought a diamond."}
4
+ function shop:complete_purchase/merge_8
@@ -0,0 +1,7 @@
1
+ # block: entry
2
+ execute store result score $t0 rs run scoreboard players get @s shop_choice
3
+ scoreboard players operation $choice rs = $t0 rs
4
+ scoreboard players set $t1 rs 0
5
+ execute if score $t0 rs = $const_1 rs run scoreboard players set $t1 rs 1
6
+ execute if score $t1 rs matches 1.. run function shop:complete_purchase/then_0
7
+ execute if score $t1 rs matches ..0 run function shop:complete_purchase/else_1
@@ -0,0 +1,3 @@
1
+ # block: entry
2
+ function shop:complete_purchase
3
+ scoreboard players operation $t0 rs = $ret rs
@@ -0,0 +1,5 @@
1
+ # RedScript runtime init
2
+ scoreboard objectives add rs dummy
3
+ scoreboard players set $__tick_turret_tick rs 0
4
+ scoreboard objectives add deploy_turret trigger
5
+ scoreboard players enable @a deploy_turret
@@ -0,0 +1,4 @@
1
+ # RedScript tick dispatcher
2
+ function turret:turret_tick
3
+ # Trigger checks
4
+ execute as @a[scores={deploy_turret=1..}] run function turret:__trigger_deploy_turret_dispatch
@@ -0,0 +1,4 @@
1
+ # Trigger dispatch for deploy_turret
2
+ function turret:deploy_turret
3
+ scoreboard players set @s deploy_turret 0
4
+ scoreboard players enable @s deploy_turret
@@ -0,0 +1,8 @@
1
+ # block: entry
2
+ summon minecraft:armor_stand 0 64 0 {Invisible:1b,Marker:1b,NoGravity:1b,Tags:["__rs_obj_0"]}
3
+ scoreboard players set @e[tag=__rs_obj_0,limit=1] rs 40
4
+ tag @e[tag=__rs_obj_0,limit=1] add turret
5
+ data modify storage rs:heap turretstate_state.health set value 40
6
+ execute store result score $t0 rs run data get storage rs:heap turretstate_state.health
7
+ execute store result score turret health run scoreboard players get $t1 rs
8
+ say Turret deployed.
@@ -0,0 +1,2 @@
1
+ # block: entry
2
+ execute as @e[type=zombie,distance=..8] run function turret:turret_tick/foreach_2
@@ -0,0 +1,2 @@
1
+ # block: entry
2
+ execute at @s run function turret:turret_tick/at_1
@@ -0,0 +1,2 @@
1
+ # block: entry
2
+ kill @s
@@ -0,0 +1,3 @@
1
+ # block: tick_body
2
+ scoreboard players set $__tick_turret_tick rs 0
3
+ execute as @e[type=armor_stand,tag=turret] run function turret:turret_tick/foreach_0
@@ -0,0 +1 @@
1
+ # block: tick_skip
@@ -0,0 +1,5 @@
1
+ # block: entry
2
+ scoreboard players add $__tick_turret_tick rs 1
3
+ execute store success score $__tick_turret_tick_check rs if score $__tick_turret_tick rs matches 20..
4
+ execute if score $__tick_turret_tick_check rs matches 1.. run function turret:turret_tick/tick_body
5
+ execute if score $__tick_turret_tick_check rs matches ..0 run function turret:turret_tick/tick_skip
@@ -0,0 +1,44 @@
1
+ /**
2
+ * RedScript Diagnostics
3
+ *
4
+ * Error reporting with file path, line, column, and formatted error messages.
5
+ */
6
+ export type DiagnosticKind = 'LexError' | 'ParseError' | 'LoweringError' | 'TypeError';
7
+ export interface DiagnosticLocation {
8
+ file?: string;
9
+ line: number;
10
+ col: number;
11
+ }
12
+ export declare class DiagnosticError extends Error {
13
+ readonly kind: DiagnosticKind;
14
+ readonly location: DiagnosticLocation;
15
+ readonly sourceLines?: string[];
16
+ constructor(kind: DiagnosticKind, message: string, location: DiagnosticLocation, sourceLines?: string[]);
17
+ /**
18
+ * Format the error for display:
19
+ * ```
20
+ * Error: [ParseError] line 5, col 12: Expected ';' after statement
21
+ * 5 | let x = 42
22
+ * ^ expected ';'
23
+ * ```
24
+ */
25
+ format(): string;
26
+ toString(): string;
27
+ }
28
+ export declare class DiagnosticCollector {
29
+ private diagnostics;
30
+ private sourceLines;
31
+ private filePath?;
32
+ constructor(source?: string, filePath?: string);
33
+ error(kind: DiagnosticKind, message: string, line: number, col: number): void;
34
+ hasErrors(): boolean;
35
+ getErrors(): DiagnosticError[];
36
+ formatAll(): string;
37
+ throwFirst(): never;
38
+ }
39
+ /**
40
+ * Create a DiagnosticError from a raw error message that includes line/col info
41
+ * e.g., "Expected ';' at line 5, col 12"
42
+ */
43
+ export declare function parseErrorMessage(kind: DiagnosticKind, rawMessage: string, sourceLines?: string[], filePath?: string): DiagnosticError;
44
+ export declare function formatError(error: Error | DiagnosticError, source?: string): string;
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ /**
3
+ * RedScript Diagnostics
4
+ *
5
+ * Error reporting with file path, line, column, and formatted error messages.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.DiagnosticCollector = exports.DiagnosticError = void 0;
9
+ exports.parseErrorMessage = parseErrorMessage;
10
+ exports.formatError = formatError;
11
+ function formatSourcePointer(sourceLines, line, col) {
12
+ const lineIdx = line - 1;
13
+ if (lineIdx < 0 || lineIdx >= sourceLines.length) {
14
+ return [];
15
+ }
16
+ const sourceLine = sourceLines[lineIdx];
17
+ const safeCol = Math.max(1, Math.min(col, sourceLine.length + 1));
18
+ const pointer = ` ${' '.repeat(safeCol - 1)}^`;
19
+ return [` ${sourceLine}`, pointer];
20
+ }
21
+ class DiagnosticError extends Error {
22
+ constructor(kind, message, location, sourceLines) {
23
+ super(message);
24
+ this.name = 'DiagnosticError';
25
+ this.kind = kind;
26
+ this.location = location;
27
+ this.sourceLines = sourceLines;
28
+ }
29
+ /**
30
+ * Format the error for display:
31
+ * ```
32
+ * Error: [ParseError] line 5, col 12: Expected ';' after statement
33
+ * 5 | let x = 42
34
+ * ^ expected ';'
35
+ * ```
36
+ */
37
+ format() {
38
+ const { kind, message, location, sourceLines } = this;
39
+ const filePart = location.file ? `${location.file}:` : '';
40
+ const header = `Error: [${kind}] ${filePart}line ${location.line}, col ${location.col}: ${message}`;
41
+ if (!sourceLines || sourceLines.length === 0) {
42
+ return header;
43
+ }
44
+ const pointerLines = formatSourcePointer(sourceLines, location.line, location.col);
45
+ if (pointerLines.length === 0) {
46
+ return header;
47
+ }
48
+ const lineNum = String(location.line).padStart(3);
49
+ const prefix = `${lineNum} | `;
50
+ const sourceLine = sourceLines[location.line - 1];
51
+ const safeCol = Math.max(1, Math.min(location.col, sourceLine.length + 1));
52
+ const pointer = ' '.repeat(prefix.length + safeCol - 1) + '^';
53
+ const hint = message.toLowerCase().includes('expected')
54
+ ? message.split(':').pop()?.trim() || ''
55
+ : '';
56
+ return [
57
+ header,
58
+ `${prefix}${sourceLine}`,
59
+ `${pointer}${hint ? ` ${hint}` : ''}`,
60
+ ].join('\n');
61
+ }
62
+ toString() {
63
+ return this.format();
64
+ }
65
+ }
66
+ exports.DiagnosticError = DiagnosticError;
67
+ // ---------------------------------------------------------------------------
68
+ // Diagnostic Collection
69
+ // ---------------------------------------------------------------------------
70
+ class DiagnosticCollector {
71
+ constructor(source, filePath) {
72
+ this.diagnostics = [];
73
+ this.sourceLines = [];
74
+ if (source) {
75
+ this.sourceLines = source.split('\n');
76
+ }
77
+ this.filePath = filePath;
78
+ }
79
+ error(kind, message, line, col) {
80
+ const diagnostic = new DiagnosticError(kind, message, { file: this.filePath, line, col }, this.sourceLines);
81
+ this.diagnostics.push(diagnostic);
82
+ }
83
+ hasErrors() {
84
+ return this.diagnostics.length > 0;
85
+ }
86
+ getErrors() {
87
+ return this.diagnostics;
88
+ }
89
+ formatAll() {
90
+ return this.diagnostics.map(d => d.format()).join('\n\n');
91
+ }
92
+ throwFirst() {
93
+ if (this.diagnostics.length > 0) {
94
+ throw this.diagnostics[0];
95
+ }
96
+ throw new Error('No diagnostics to throw');
97
+ }
98
+ }
99
+ exports.DiagnosticCollector = DiagnosticCollector;
100
+ // ---------------------------------------------------------------------------
101
+ // Helper Functions
102
+ // ---------------------------------------------------------------------------
103
+ /**
104
+ * Create a DiagnosticError from a raw error message that includes line/col info
105
+ * e.g., "Expected ';' at line 5, col 12"
106
+ */
107
+ function parseErrorMessage(kind, rawMessage, sourceLines, filePath) {
108
+ // Try to extract line and col from message
109
+ const match = rawMessage.match(/at line (\d+), col (\d+)/);
110
+ if (match) {
111
+ const line = parseInt(match[1], 10);
112
+ const col = parseInt(match[2], 10);
113
+ const message = rawMessage.replace(/ at line \d+, col \d+$/, '').trim();
114
+ return new DiagnosticError(kind, message, { file: filePath, line, col }, sourceLines);
115
+ }
116
+ // Fallback: line 1, col 1
117
+ return new DiagnosticError(kind, rawMessage, { file: filePath, line: 1, col: 1 }, sourceLines);
118
+ }
119
+ function formatError(error, source) {
120
+ if (error instanceof DiagnosticError) {
121
+ const sourceLines = source?.split('\n') ?? error.sourceLines ?? [];
122
+ const { file, line, col } = error.location;
123
+ const locationPart = file
124
+ ? ` in ${file} at line ${line}, col ${col}`
125
+ : ` at line ${line}, col ${col}`;
126
+ const lines = [`Error${locationPart}:`];
127
+ const pointerLines = formatSourcePointer(sourceLines, line, col);
128
+ if (pointerLines.length > 0) {
129
+ lines.push(...pointerLines);
130
+ }
131
+ lines.push(error.message);
132
+ return lines.join('\n');
133
+ }
134
+ if (!source) {
135
+ return error.message;
136
+ }
137
+ const parsed = parseErrorMessage('ParseError', error.message, source.split('\n'));
138
+ return formatError(parsed, source);
139
+ }
140
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,53 @@
1
+ /**
2
+ * RedScript Compiler
3
+ *
4
+ * Main entry point for programmatic usage.
5
+ */
6
+ import type { Warning } from './lowering';
7
+ import { DatapackFile } from './codegen/mcfunction';
8
+ import type { IRModule } from './ir/types';
9
+ import type { Program } from './ast/types';
10
+ import type { DiagnosticError } from './diagnostics';
11
+ import { type OptimizationStats } from './optimizer/commands';
12
+ export interface CompileOptions {
13
+ namespace?: string;
14
+ optimize?: boolean;
15
+ typeCheck?: boolean;
16
+ filePath?: string;
17
+ }
18
+ export interface CompileResult {
19
+ files: DatapackFile[];
20
+ advancements: DatapackFile[];
21
+ ast: Program;
22
+ ir: IRModule;
23
+ typeErrors?: DiagnosticError[];
24
+ warnings?: Warning[];
25
+ stats?: OptimizationStats;
26
+ }
27
+ /**
28
+ * Compile RedScript source code to a Minecraft datapack.
29
+ *
30
+ * @param source - The RedScript source code
31
+ * @param options - Compilation options
32
+ * @returns Compiled datapack files
33
+ */
34
+ export declare function compile(source: string, options?: CompileOptions): CompileResult;
35
+ /**
36
+ * Check RedScript source code for errors without generating output.
37
+ *
38
+ * @param source - The RedScript source code
39
+ * @param namespace - Optional namespace
40
+ * @returns null if no errors, or an error object
41
+ */
42
+ export declare function check(source: string, namespace?: string, filePath?: string): Error | null;
43
+ export { Lexer } from './lexer';
44
+ export { Parser } from './parser';
45
+ export { TypeChecker } from './typechecker';
46
+ export { Lowering } from './lowering';
47
+ export { optimize } from './optimizer/passes';
48
+ export { generateDatapack } from './codegen/mcfunction';
49
+ export { MCCommandValidator } from './mc-validator';
50
+ export type { DatapackFile } from './codegen/mcfunction';
51
+ export type { IRModule, IRFunction } from './ir/types';
52
+ export type { Program, FnDecl, Expr, Stmt, Span } from './ast/types';
53
+ export type { DiagnosticError } from './diagnostics';
package/dist/index.js ADDED
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ /**
3
+ * RedScript Compiler
4
+ *
5
+ * Main entry point for programmatic usage.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.MCCommandValidator = exports.generateDatapack = exports.optimize = exports.Lowering = exports.TypeChecker = exports.Parser = exports.Lexer = void 0;
9
+ exports.compile = compile;
10
+ exports.check = check;
11
+ const lexer_1 = require("./lexer");
12
+ const parser_1 = require("./parser");
13
+ const typechecker_1 = require("./typechecker");
14
+ const lowering_1 = require("./lowering");
15
+ const passes_1 = require("./optimizer/passes");
16
+ const mcfunction_1 = require("./codegen/mcfunction");
17
+ const compile_1 = require("./compile");
18
+ const commands_1 = require("./optimizer/commands");
19
+ /**
20
+ * Compile RedScript source code to a Minecraft datapack.
21
+ *
22
+ * @param source - The RedScript source code
23
+ * @param options - Compilation options
24
+ * @returns Compiled datapack files
25
+ */
26
+ function compile(source, options = {}) {
27
+ const namespace = options.namespace ?? 'redscript';
28
+ const shouldOptimize = options.optimize ?? true;
29
+ const shouldTypeCheck = options.typeCheck ?? true;
30
+ const filePath = options.filePath;
31
+ const preprocessedSource = (0, compile_1.preprocessSource)(source, { filePath });
32
+ // Lexing
33
+ const tokens = new lexer_1.Lexer(preprocessedSource, filePath).tokenize();
34
+ // Parsing
35
+ const ast = new parser_1.Parser(tokens, preprocessedSource, filePath).parse(namespace);
36
+ // Type checking (warn mode - collect errors but don't block)
37
+ let typeErrors;
38
+ if (shouldTypeCheck) {
39
+ const checker = new typechecker_1.TypeChecker(preprocessedSource, filePath);
40
+ typeErrors = checker.check(ast);
41
+ }
42
+ // Lowering to IR
43
+ const lowering = new lowering_1.Lowering(namespace);
44
+ const ir = lowering.lower(ast);
45
+ let optimizedIR = ir;
46
+ let generated = (0, mcfunction_1.generateDatapackWithStats)(ir, { optimizeCommands: shouldOptimize });
47
+ let optimizationStats;
48
+ if (shouldOptimize) {
49
+ const stats = (0, commands_1.createEmptyOptimizationStats)();
50
+ const copyPropagatedFunctions = [];
51
+ const deadCodeEliminatedFunctions = [];
52
+ for (const fn of ir.functions) {
53
+ const folded = (0, passes_1.constantFoldingWithStats)(fn);
54
+ stats.constantFolds += folded.stats.constantFolds ?? 0;
55
+ const propagated = (0, passes_1.copyPropagation)(folded.fn);
56
+ copyPropagatedFunctions.push(propagated);
57
+ const dce = (0, passes_1.deadCodeEliminationWithStats)(propagated);
58
+ deadCodeEliminatedFunctions.push(dce.fn);
59
+ }
60
+ const copyPropagatedIR = { ...ir, functions: copyPropagatedFunctions };
61
+ optimizedIR = { ...ir, functions: deadCodeEliminatedFunctions };
62
+ const baselineGenerated = (0, mcfunction_1.generateDatapackWithStats)(ir, { optimizeCommands: false });
63
+ const beforeDceGenerated = (0, mcfunction_1.generateDatapackWithStats)(copyPropagatedIR, { optimizeCommands: false });
64
+ const afterDceGenerated = (0, mcfunction_1.generateDatapackWithStats)(optimizedIR, { optimizeCommands: false });
65
+ generated = (0, mcfunction_1.generateDatapackWithStats)(optimizedIR, { optimizeCommands: true });
66
+ stats.deadCodeRemoved =
67
+ (0, mcfunction_1.countMcfunctionCommands)(beforeDceGenerated.files) - (0, mcfunction_1.countMcfunctionCommands)(afterDceGenerated.files);
68
+ stats.licmHoists = generated.stats.licmHoists;
69
+ stats.licmLoopBodies = generated.stats.licmLoopBodies;
70
+ stats.cseRedundantReads = generated.stats.cseRedundantReads;
71
+ stats.cseArithmetic = generated.stats.cseArithmetic;
72
+ stats.setblockMergedCommands = generated.stats.setblockMergedCommands;
73
+ stats.setblockFillCommands = generated.stats.setblockFillCommands;
74
+ stats.setblockSavedCommands = generated.stats.setblockSavedCommands;
75
+ stats.totalCommandsBefore = (0, mcfunction_1.countMcfunctionCommands)(baselineGenerated.files);
76
+ stats.totalCommandsAfter = (0, mcfunction_1.countMcfunctionCommands)(generated.files);
77
+ optimizationStats = stats;
78
+ }
79
+ else {
80
+ optimizedIR = ir;
81
+ generated = (0, mcfunction_1.generateDatapackWithStats)(ir, { optimizeCommands: false });
82
+ }
83
+ return {
84
+ files: [...generated.files, ...generated.advancements],
85
+ advancements: generated.advancements,
86
+ ast,
87
+ ir: optimizedIR,
88
+ typeErrors,
89
+ warnings: lowering.warnings,
90
+ stats: optimizationStats,
91
+ };
92
+ }
93
+ /**
94
+ * Check RedScript source code for errors without generating output.
95
+ *
96
+ * @param source - The RedScript source code
97
+ * @param namespace - Optional namespace
98
+ * @returns null if no errors, or an error object
99
+ */
100
+ function check(source, namespace = 'redscript', filePath) {
101
+ try {
102
+ const preprocessedSource = (0, compile_1.preprocessSource)(source, { filePath });
103
+ const tokens = new lexer_1.Lexer(preprocessedSource, filePath).tokenize();
104
+ new parser_1.Parser(tokens, preprocessedSource, filePath).parse(namespace);
105
+ return null;
106
+ }
107
+ catch (err) {
108
+ return err;
109
+ }
110
+ }
111
+ // Re-export types and classes for advanced usage
112
+ var lexer_2 = require("./lexer");
113
+ Object.defineProperty(exports, "Lexer", { enumerable: true, get: function () { return lexer_2.Lexer; } });
114
+ var parser_2 = require("./parser");
115
+ Object.defineProperty(exports, "Parser", { enumerable: true, get: function () { return parser_2.Parser; } });
116
+ var typechecker_2 = require("./typechecker");
117
+ Object.defineProperty(exports, "TypeChecker", { enumerable: true, get: function () { return typechecker_2.TypeChecker; } });
118
+ var lowering_2 = require("./lowering");
119
+ Object.defineProperty(exports, "Lowering", { enumerable: true, get: function () { return lowering_2.Lowering; } });
120
+ var passes_2 = require("./optimizer/passes");
121
+ Object.defineProperty(exports, "optimize", { enumerable: true, get: function () { return passes_2.optimize; } });
122
+ var mcfunction_2 = require("./codegen/mcfunction");
123
+ Object.defineProperty(exports, "generateDatapack", { enumerable: true, get: function () { return mcfunction_2.generateDatapack; } });
124
+ var mc_validator_1 = require("./mc-validator");
125
+ Object.defineProperty(exports, "MCCommandValidator", { enumerable: true, get: function () { return mc_validator_1.MCCommandValidator; } });
126
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,32 @@
1
+ /**
2
+ * IRBuilder — helper for constructing IR programmatically.
3
+ * AST → IR lowering uses this.
4
+ */
5
+ import type { IRFunction, IRInstr, IRModule, Operand } from './types';
6
+ export declare class IRBuilder {
7
+ private tempCount;
8
+ private labelCount;
9
+ private currentBlock;
10
+ private blocks;
11
+ private locals;
12
+ freshTemp(): string;
13
+ freshLabel(hint?: string): string;
14
+ startBlock(label: string): void;
15
+ private get block();
16
+ private sealBlock;
17
+ emitAssign(dst: string, src: Operand): void;
18
+ emitBinop(dst: string, lhs: Operand, bop: IRInstr & {
19
+ op: 'binop';
20
+ } extends {
21
+ bop: infer B;
22
+ } ? B : never, rhs: Operand): void;
23
+ emitCmp(dst: string, lhs: Operand, cop: '==' | '!=' | '<' | '<=' | '>' | '>=', rhs: Operand): void;
24
+ emitCall(fn: string, args: Operand[], dst?: string): void;
25
+ emitRaw(cmd: string): void;
26
+ emitJump(target: string): void;
27
+ emitJumpIf(cond: string, then: string, else_: string): void;
28
+ emitReturn(value?: Operand): void;
29
+ emitTickYield(continuation: string): void;
30
+ build(name: string, params: string[], isTickLoop?: boolean): IRFunction;
31
+ }
32
+ export declare function buildModule(namespace: string, fns: IRFunction[], globals?: string[]): IRModule;
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+ /**
3
+ * IRBuilder — helper for constructing IR programmatically.
4
+ * AST → IR lowering uses this.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.IRBuilder = void 0;
8
+ exports.buildModule = buildModule;
9
+ class IRBuilder {
10
+ constructor() {
11
+ this.tempCount = 0;
12
+ this.labelCount = 0;
13
+ this.currentBlock = null;
14
+ this.blocks = [];
15
+ this.locals = new Set();
16
+ }
17
+ // -------------------------------------------------------------------------
18
+ // Names
19
+ // -------------------------------------------------------------------------
20
+ freshTemp() {
21
+ const name = `$t${this.tempCount++}`;
22
+ this.locals.add(name);
23
+ return name;
24
+ }
25
+ freshLabel(hint = 'L') {
26
+ return `${hint}_${this.labelCount++}`;
27
+ }
28
+ // -------------------------------------------------------------------------
29
+ // Block management
30
+ // -------------------------------------------------------------------------
31
+ startBlock(label) {
32
+ this.currentBlock = { label, instrs: [], term: { op: 'return' } };
33
+ }
34
+ get block() {
35
+ if (!this.currentBlock)
36
+ throw new Error('No active block');
37
+ return this.currentBlock;
38
+ }
39
+ sealBlock(term) {
40
+ this.block.term = term;
41
+ this.blocks.push(this.block);
42
+ this.currentBlock = null;
43
+ }
44
+ // -------------------------------------------------------------------------
45
+ // Emit instructions
46
+ // -------------------------------------------------------------------------
47
+ emitAssign(dst, src) {
48
+ this.locals.add(dst);
49
+ this.block.instrs.push({ op: 'assign', dst, src });
50
+ }
51
+ emitBinop(dst, lhs, bop, rhs) {
52
+ this.locals.add(dst);
53
+ this.block.instrs.push({ op: 'binop', dst, lhs, bop, rhs });
54
+ }
55
+ emitCmp(dst, lhs, cop, rhs) {
56
+ this.locals.add(dst);
57
+ this.block.instrs.push({ op: 'cmp', dst, lhs, cop, rhs });
58
+ }
59
+ emitCall(fn, args, dst) {
60
+ if (dst)
61
+ this.locals.add(dst);
62
+ this.block.instrs.push({ op: 'call', fn, args, dst });
63
+ }
64
+ emitRaw(cmd) {
65
+ this.block.instrs.push({ op: 'raw', cmd });
66
+ }
67
+ // -------------------------------------------------------------------------
68
+ // Terminators
69
+ // -------------------------------------------------------------------------
70
+ emitJump(target) {
71
+ this.sealBlock({ op: 'jump', target });
72
+ }
73
+ emitJumpIf(cond, then, else_) {
74
+ this.sealBlock({ op: 'jump_if', cond, then, else_ });
75
+ }
76
+ emitReturn(value) {
77
+ this.sealBlock({ op: 'return', value });
78
+ }
79
+ emitTickYield(continuation) {
80
+ this.sealBlock({ op: 'tick_yield', continuation });
81
+ }
82
+ // -------------------------------------------------------------------------
83
+ // Build
84
+ // -------------------------------------------------------------------------
85
+ build(name, params, isTickLoop = false) {
86
+ return {
87
+ name,
88
+ params,
89
+ locals: Array.from(this.locals),
90
+ blocks: this.blocks,
91
+ isTickLoop,
92
+ };
93
+ }
94
+ }
95
+ exports.IRBuilder = IRBuilder;
96
+ function buildModule(namespace, fns, globals = []) {
97
+ return { namespace, functions: fns, globals };
98
+ }
99
+ //# sourceMappingURL=builder.js.map