redscript-mc 1.2.30 → 2.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 (269) hide show
  1. package/.claude/commands/build-test.md +10 -0
  2. package/.claude/commands/deploy-demo.md +12 -0
  3. package/.claude/commands/stage-status.md +13 -0
  4. package/.claude/settings.json +12 -0
  5. package/.github/workflows/ci.yml +1 -0
  6. package/CLAUDE.md +231 -0
  7. package/demo.gif +0 -0
  8. package/dist/cli.js +2 -554
  9. package/dist/compile.js +2 -266
  10. package/dist/index.js +2 -159
  11. package/dist/lowering/index.js +5 -3
  12. package/dist/src/__tests__/cli.test.d.ts +1 -0
  13. package/dist/src/__tests__/cli.test.js +104 -0
  14. package/dist/src/__tests__/codegen.test.d.ts +1 -0
  15. package/dist/src/__tests__/codegen.test.js +152 -0
  16. package/dist/src/__tests__/compile-all.test.d.ts +10 -0
  17. package/dist/src/__tests__/compile-all.test.js +108 -0
  18. package/dist/src/__tests__/dce.test.d.ts +1 -0
  19. package/dist/src/__tests__/dce.test.js +102 -0
  20. package/dist/src/__tests__/diagnostics.test.d.ts +4 -0
  21. package/dist/src/__tests__/diagnostics.test.js +177 -0
  22. package/dist/src/__tests__/e2e.test.d.ts +6 -0
  23. package/dist/src/__tests__/e2e.test.js +1789 -0
  24. package/dist/src/__tests__/entity-types.test.d.ts +1 -0
  25. package/dist/src/__tests__/entity-types.test.js +203 -0
  26. package/dist/src/__tests__/formatter.test.d.ts +1 -0
  27. package/dist/src/__tests__/formatter.test.js +40 -0
  28. package/dist/src/__tests__/lexer.test.d.ts +1 -0
  29. package/dist/src/__tests__/lexer.test.js +343 -0
  30. package/dist/src/__tests__/lowering.test.d.ts +1 -0
  31. package/dist/src/__tests__/lowering.test.js +1015 -0
  32. package/dist/src/__tests__/macro.test.d.ts +8 -0
  33. package/dist/src/__tests__/macro.test.js +306 -0
  34. package/dist/src/__tests__/mc-integration.test.d.ts +12 -0
  35. package/dist/src/__tests__/mc-integration.test.js +817 -0
  36. package/dist/src/__tests__/mc-syntax.test.d.ts +1 -0
  37. package/dist/src/__tests__/mc-syntax.test.js +124 -0
  38. package/dist/src/__tests__/nbt.test.d.ts +1 -0
  39. package/dist/src/__tests__/nbt.test.js +82 -0
  40. package/dist/src/__tests__/optimizer-advanced.test.d.ts +1 -0
  41. package/dist/src/__tests__/optimizer-advanced.test.js +124 -0
  42. package/dist/src/__tests__/optimizer.test.d.ts +1 -0
  43. package/dist/src/__tests__/optimizer.test.js +149 -0
  44. package/dist/src/__tests__/parser.test.d.ts +1 -0
  45. package/dist/src/__tests__/parser.test.js +807 -0
  46. package/dist/src/__tests__/repl.test.d.ts +1 -0
  47. package/dist/src/__tests__/repl.test.js +27 -0
  48. package/dist/src/__tests__/runtime.test.d.ts +1 -0
  49. package/dist/src/__tests__/runtime.test.js +289 -0
  50. package/dist/src/__tests__/stdlib-advanced.test.d.ts +4 -0
  51. package/dist/src/__tests__/stdlib-advanced.test.js +374 -0
  52. package/dist/src/__tests__/stdlib-bigint.test.d.ts +7 -0
  53. package/dist/src/__tests__/stdlib-bigint.test.js +426 -0
  54. package/dist/src/__tests__/stdlib-math.test.d.ts +7 -0
  55. package/dist/src/__tests__/stdlib-math.test.js +351 -0
  56. package/dist/src/__tests__/stdlib-vec.test.d.ts +4 -0
  57. package/dist/src/__tests__/stdlib-vec.test.js +263 -0
  58. package/dist/src/__tests__/structure-optimizer.test.d.ts +1 -0
  59. package/dist/src/__tests__/structure-optimizer.test.js +33 -0
  60. package/dist/src/__tests__/typechecker.test.d.ts +1 -0
  61. package/dist/src/__tests__/typechecker.test.js +552 -0
  62. package/dist/src/__tests__/var-allocator.test.d.ts +1 -0
  63. package/dist/src/__tests__/var-allocator.test.js +69 -0
  64. package/dist/src/ast/types.d.ts +515 -0
  65. package/dist/src/ast/types.js +9 -0
  66. package/dist/src/builtins/metadata.d.ts +36 -0
  67. package/dist/src/builtins/metadata.js +1014 -0
  68. package/dist/src/cli.d.ts +11 -0
  69. package/dist/src/cli.js +443 -0
  70. package/dist/src/codegen/cmdblock/index.d.ts +26 -0
  71. package/dist/src/codegen/cmdblock/index.js +45 -0
  72. package/dist/src/codegen/mcfunction/index.d.ts +40 -0
  73. package/dist/src/codegen/mcfunction/index.js +606 -0
  74. package/dist/src/codegen/structure/index.d.ts +24 -0
  75. package/dist/src/codegen/structure/index.js +279 -0
  76. package/dist/src/codegen/var-allocator.d.ts +45 -0
  77. package/dist/src/codegen/var-allocator.js +104 -0
  78. package/dist/src/compile.d.ts +37 -0
  79. package/dist/src/compile.js +165 -0
  80. package/dist/src/diagnostics/index.d.ts +44 -0
  81. package/dist/src/diagnostics/index.js +140 -0
  82. package/dist/src/events/types.d.ts +35 -0
  83. package/dist/src/events/types.js +59 -0
  84. package/dist/src/formatter/index.d.ts +1 -0
  85. package/dist/src/formatter/index.js +26 -0
  86. package/dist/src/index.d.ts +22 -0
  87. package/dist/src/index.js +45 -0
  88. package/dist/src/ir/builder.d.ts +33 -0
  89. package/dist/src/ir/builder.js +99 -0
  90. package/dist/src/ir/types.d.ts +132 -0
  91. package/dist/src/ir/types.js +15 -0
  92. package/dist/src/lexer/index.d.ts +37 -0
  93. package/dist/src/lexer/index.js +569 -0
  94. package/dist/src/lowering/index.d.ts +188 -0
  95. package/dist/src/lowering/index.js +3405 -0
  96. package/dist/src/mc-test/client.d.ts +128 -0
  97. package/dist/src/mc-test/client.js +174 -0
  98. package/dist/src/mc-test/runner.d.ts +28 -0
  99. package/dist/src/mc-test/runner.js +151 -0
  100. package/dist/src/mc-test/setup.d.ts +11 -0
  101. package/dist/src/mc-test/setup.js +98 -0
  102. package/dist/src/mc-validator/index.d.ts +17 -0
  103. package/dist/src/mc-validator/index.js +322 -0
  104. package/dist/src/nbt/index.d.ts +86 -0
  105. package/dist/src/nbt/index.js +250 -0
  106. package/dist/src/optimizer/commands.d.ts +38 -0
  107. package/dist/src/optimizer/commands.js +451 -0
  108. package/dist/src/optimizer/dce.d.ts +34 -0
  109. package/dist/src/optimizer/dce.js +639 -0
  110. package/dist/src/optimizer/passes.d.ts +34 -0
  111. package/dist/src/optimizer/passes.js +243 -0
  112. package/dist/src/optimizer/structure.d.ts +9 -0
  113. package/dist/src/optimizer/structure.js +356 -0
  114. package/dist/src/parser/index.d.ts +93 -0
  115. package/dist/src/parser/index.js +1687 -0
  116. package/dist/src/repl.d.ts +16 -0
  117. package/dist/src/repl.js +165 -0
  118. package/dist/src/runtime/index.d.ts +107 -0
  119. package/dist/src/runtime/index.js +1409 -0
  120. package/dist/src/typechecker/index.d.ts +61 -0
  121. package/dist/src/typechecker/index.js +1034 -0
  122. package/dist/src/types/entity-hierarchy.d.ts +29 -0
  123. package/dist/src/types/entity-hierarchy.js +107 -0
  124. package/dist/src2/__tests__/e2e/basic.test.d.ts +8 -0
  125. package/dist/src2/__tests__/e2e/basic.test.js +140 -0
  126. package/dist/src2/__tests__/e2e/macros.test.d.ts +9 -0
  127. package/dist/src2/__tests__/e2e/macros.test.js +182 -0
  128. package/dist/src2/__tests__/e2e/migrate.test.d.ts +13 -0
  129. package/dist/src2/__tests__/e2e/migrate.test.js +2739 -0
  130. package/dist/src2/__tests__/hir/desugar.test.d.ts +1 -0
  131. package/dist/src2/__tests__/hir/desugar.test.js +234 -0
  132. package/dist/src2/__tests__/lir/lower.test.d.ts +1 -0
  133. package/dist/src2/__tests__/lir/lower.test.js +559 -0
  134. package/dist/src2/__tests__/lir/types.test.d.ts +1 -0
  135. package/dist/src2/__tests__/lir/types.test.js +185 -0
  136. package/dist/src2/__tests__/lir/verify.test.d.ts +1 -0
  137. package/dist/src2/__tests__/lir/verify.test.js +221 -0
  138. package/dist/src2/__tests__/mir/arithmetic.test.d.ts +1 -0
  139. package/dist/src2/__tests__/mir/arithmetic.test.js +130 -0
  140. package/dist/src2/__tests__/mir/control-flow.test.d.ts +1 -0
  141. package/dist/src2/__tests__/mir/control-flow.test.js +205 -0
  142. package/dist/src2/__tests__/mir/verify.test.d.ts +1 -0
  143. package/dist/src2/__tests__/mir/verify.test.js +223 -0
  144. package/dist/src2/__tests__/optimizer/block_merge.test.d.ts +1 -0
  145. package/dist/src2/__tests__/optimizer/block_merge.test.js +78 -0
  146. package/dist/src2/__tests__/optimizer/branch_simplify.test.d.ts +1 -0
  147. package/dist/src2/__tests__/optimizer/branch_simplify.test.js +58 -0
  148. package/dist/src2/__tests__/optimizer/constant_fold.test.d.ts +1 -0
  149. package/dist/src2/__tests__/optimizer/constant_fold.test.js +131 -0
  150. package/dist/src2/__tests__/optimizer/copy_prop.test.d.ts +1 -0
  151. package/dist/src2/__tests__/optimizer/copy_prop.test.js +91 -0
  152. package/dist/src2/__tests__/optimizer/dce.test.d.ts +1 -0
  153. package/dist/src2/__tests__/optimizer/dce.test.js +76 -0
  154. package/dist/src2/__tests__/optimizer/pipeline.test.d.ts +1 -0
  155. package/dist/src2/__tests__/optimizer/pipeline.test.js +102 -0
  156. package/dist/src2/emit/compile.d.ts +19 -0
  157. package/dist/src2/emit/compile.js +80 -0
  158. package/dist/src2/emit/index.d.ts +17 -0
  159. package/dist/src2/emit/index.js +172 -0
  160. package/dist/src2/hir/lower.d.ts +15 -0
  161. package/dist/src2/hir/lower.js +378 -0
  162. package/dist/src2/hir/types.d.ts +373 -0
  163. package/dist/src2/hir/types.js +16 -0
  164. package/dist/src2/lir/lower.d.ts +15 -0
  165. package/dist/src2/lir/lower.js +453 -0
  166. package/dist/src2/lir/types.d.ts +136 -0
  167. package/dist/src2/lir/types.js +11 -0
  168. package/dist/src2/lir/verify.d.ts +14 -0
  169. package/dist/src2/lir/verify.js +113 -0
  170. package/dist/src2/mir/lower.d.ts +9 -0
  171. package/dist/src2/mir/lower.js +1030 -0
  172. package/dist/src2/mir/macro.d.ts +22 -0
  173. package/dist/src2/mir/macro.js +168 -0
  174. package/dist/src2/mir/types.d.ts +183 -0
  175. package/dist/src2/mir/types.js +11 -0
  176. package/dist/src2/mir/verify.d.ts +16 -0
  177. package/dist/src2/mir/verify.js +216 -0
  178. package/dist/src2/optimizer/block_merge.d.ts +12 -0
  179. package/dist/src2/optimizer/block_merge.js +84 -0
  180. package/dist/src2/optimizer/branch_simplify.d.ts +9 -0
  181. package/dist/src2/optimizer/branch_simplify.js +28 -0
  182. package/dist/src2/optimizer/constant_fold.d.ts +10 -0
  183. package/dist/src2/optimizer/constant_fold.js +85 -0
  184. package/dist/src2/optimizer/copy_prop.d.ts +9 -0
  185. package/dist/src2/optimizer/copy_prop.js +113 -0
  186. package/dist/src2/optimizer/dce.d.ts +8 -0
  187. package/dist/src2/optimizer/dce.js +155 -0
  188. package/dist/src2/optimizer/pipeline.d.ts +10 -0
  189. package/dist/src2/optimizer/pipeline.js +42 -0
  190. package/dist/tsconfig.tsbuildinfo +1 -0
  191. package/docs/compiler-pipeline-redesign.md +2243 -0
  192. package/docs/optimization-ideas.md +1076 -0
  193. package/editors/vscode/package-lock.json +3 -3
  194. package/editors/vscode/package.json +1 -1
  195. package/jest.config.js +1 -1
  196. package/package.json +6 -5
  197. package/scripts/postbuild.js +15 -0
  198. package/src/__tests__/cli.test.ts +8 -220
  199. package/src/__tests__/dce.test.ts +11 -56
  200. package/src/__tests__/diagnostics.test.ts +59 -38
  201. package/src/__tests__/mc-integration.test.ts +1 -2
  202. package/src/ast/types.ts +6 -1
  203. package/src/cli.ts +29 -156
  204. package/src/compile.ts +6 -162
  205. package/src/index.ts +14 -178
  206. package/src/mc-test/runner.ts +4 -3
  207. package/src/parser/index.ts +1 -1
  208. package/src/repl.ts +1 -1
  209. package/src/runtime/index.ts +1 -1
  210. package/src2/__tests__/e2e/basic.test.ts +154 -0
  211. package/src2/__tests__/e2e/macros.test.ts +199 -0
  212. package/src2/__tests__/e2e/migrate.test.ts +3008 -0
  213. package/src2/__tests__/hir/desugar.test.ts +263 -0
  214. package/src2/__tests__/lir/lower.test.ts +619 -0
  215. package/src2/__tests__/lir/types.test.ts +207 -0
  216. package/src2/__tests__/lir/verify.test.ts +249 -0
  217. package/src2/__tests__/mir/arithmetic.test.ts +156 -0
  218. package/src2/__tests__/mir/control-flow.test.ts +242 -0
  219. package/src2/__tests__/mir/verify.test.ts +254 -0
  220. package/src2/__tests__/optimizer/block_merge.test.ts +84 -0
  221. package/src2/__tests__/optimizer/branch_simplify.test.ts +64 -0
  222. package/src2/__tests__/optimizer/constant_fold.test.ts +145 -0
  223. package/src2/__tests__/optimizer/copy_prop.test.ts +99 -0
  224. package/src2/__tests__/optimizer/dce.test.ts +83 -0
  225. package/src2/__tests__/optimizer/pipeline.test.ts +116 -0
  226. package/src2/emit/compile.ts +99 -0
  227. package/src2/emit/index.ts +222 -0
  228. package/src2/hir/lower.ts +428 -0
  229. package/src2/hir/types.ts +216 -0
  230. package/src2/lir/lower.ts +556 -0
  231. package/src2/lir/types.ts +109 -0
  232. package/src2/lir/verify.ts +129 -0
  233. package/src2/mir/lower.ts +1160 -0
  234. package/src2/mir/macro.ts +167 -0
  235. package/src2/mir/types.ts +106 -0
  236. package/src2/mir/verify.ts +218 -0
  237. package/src2/optimizer/block_merge.ts +93 -0
  238. package/src2/optimizer/branch_simplify.ts +27 -0
  239. package/src2/optimizer/constant_fold.ts +88 -0
  240. package/src2/optimizer/copy_prop.ts +106 -0
  241. package/src2/optimizer/dce.ts +133 -0
  242. package/src2/optimizer/pipeline.ts +44 -0
  243. package/tsconfig.json +2 -2
  244. package/src/__tests__/codegen.test.ts +0 -161
  245. package/src/__tests__/e2e.test.ts +0 -2039
  246. package/src/__tests__/entity-types.test.ts +0 -236
  247. package/src/__tests__/lowering.test.ts +0 -1185
  248. package/src/__tests__/macro.test.ts +0 -343
  249. package/src/__tests__/nbt.test.ts +0 -58
  250. package/src/__tests__/optimizer-advanced.test.ts +0 -144
  251. package/src/__tests__/optimizer.test.ts +0 -162
  252. package/src/__tests__/runtime.test.ts +0 -305
  253. package/src/__tests__/stdlib-advanced.test.ts +0 -379
  254. package/src/__tests__/stdlib-bigint.test.ts +0 -427
  255. package/src/__tests__/stdlib-math.test.ts +0 -374
  256. package/src/__tests__/stdlib-vec.test.ts +0 -259
  257. package/src/__tests__/structure-optimizer.test.ts +0 -38
  258. package/src/__tests__/var-allocator.test.ts +0 -75
  259. package/src/codegen/cmdblock/index.ts +0 -63
  260. package/src/codegen/mcfunction/index.ts +0 -662
  261. package/src/codegen/structure/index.ts +0 -346
  262. package/src/codegen/var-allocator.ts +0 -104
  263. package/src/ir/builder.ts +0 -116
  264. package/src/ir/types.ts +0 -134
  265. package/src/lowering/index.ts +0 -3876
  266. package/src/optimizer/commands.ts +0 -534
  267. package/src/optimizer/dce.ts +0 -679
  268. package/src/optimizer/passes.ts +0 -250
  269. package/src/optimizer/structure.ts +0 -450
@@ -0,0 +1,185 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ describe('LIR types — Slot', () => {
4
+ test('Slot has player and obj fields', () => {
5
+ const slot = { player: '$t0', obj: '__test' };
6
+ expect(slot.player).toBe('$t0');
7
+ expect(slot.obj).toBe('__test');
8
+ });
9
+ });
10
+ describe('LIR types — instructions', () => {
11
+ test('score_set instruction', () => {
12
+ const instr = { kind: 'score_set', dst: { player: '$x', obj: '__ns' }, value: 42 };
13
+ expect(instr.kind).toBe('score_set');
14
+ });
15
+ test('score_copy instruction', () => {
16
+ const dst = { player: '$x', obj: '__ns' };
17
+ const src = { player: '$y', obj: '__ns' };
18
+ const instr = { kind: 'score_copy', dst, src };
19
+ expect(instr.kind).toBe('score_copy');
20
+ });
21
+ test('score arithmetic instructions', () => {
22
+ const dst = { player: '$x', obj: '__ns' };
23
+ const src = { player: '$y', obj: '__ns' };
24
+ const ops = ['score_add', 'score_sub', 'score_mul', 'score_div', 'score_mod'];
25
+ for (const kind of ops) {
26
+ const instr = { kind, dst, src };
27
+ expect(instr.kind).toBe(kind);
28
+ }
29
+ });
30
+ test('score_min, score_max instructions', () => {
31
+ const dst = { player: '$x', obj: '__ns' };
32
+ const src = { player: '$y', obj: '__ns' };
33
+ const min = { kind: 'score_min', dst, src };
34
+ const max = { kind: 'score_max', dst, src };
35
+ expect(min.kind).toBe('score_min');
36
+ expect(max.kind).toBe('score_max');
37
+ });
38
+ test('score_swap instruction', () => {
39
+ const a = { player: '$x', obj: '__ns' };
40
+ const b = { player: '$y', obj: '__ns' };
41
+ const instr = { kind: 'score_swap', a, b };
42
+ expect(instr.kind).toBe('score_swap');
43
+ });
44
+ test('store_cmd_to_score instruction', () => {
45
+ const dst = { player: '$x', obj: '__ns' };
46
+ const cmd = { kind: 'call', fn: 'test:foo' };
47
+ const instr = { kind: 'store_cmd_to_score', dst, cmd };
48
+ expect(instr.kind).toBe('store_cmd_to_score');
49
+ });
50
+ test('store_score_to_nbt instruction', () => {
51
+ const instr = {
52
+ kind: 'store_score_to_nbt',
53
+ ns: 'rs:data', path: 'value', type: 'int', scale: 1,
54
+ src: { player: '$x', obj: '__ns' },
55
+ };
56
+ expect(instr.kind).toBe('store_score_to_nbt');
57
+ });
58
+ test('store_nbt_to_score instruction', () => {
59
+ const instr = {
60
+ kind: 'store_nbt_to_score',
61
+ dst: { player: '$x', obj: '__ns' },
62
+ ns: 'rs:data', path: 'value', scale: 1,
63
+ };
64
+ expect(instr.kind).toBe('store_nbt_to_score');
65
+ });
66
+ test('nbt_set_literal instruction', () => {
67
+ const instr = { kind: 'nbt_set_literal', ns: 'rs:data', path: 'x', value: '42' };
68
+ expect(instr.kind).toBe('nbt_set_literal');
69
+ });
70
+ test('nbt_copy instruction', () => {
71
+ const instr = {
72
+ kind: 'nbt_copy',
73
+ srcNs: 'rs:a', srcPath: 'x',
74
+ dstNs: 'rs:b', dstPath: 'y',
75
+ };
76
+ expect(instr.kind).toBe('nbt_copy');
77
+ });
78
+ test('call instruction', () => {
79
+ const instr = { kind: 'call', fn: 'test:foo' };
80
+ expect(instr.kind).toBe('call');
81
+ });
82
+ test('call_macro instruction', () => {
83
+ const instr = { kind: 'call_macro', fn: 'test:draw', storage: 'rs:macro_args' };
84
+ expect(instr.kind).toBe('call_macro');
85
+ });
86
+ test('call_if_matches instruction', () => {
87
+ const instr = {
88
+ kind: 'call_if_matches',
89
+ fn: 'test:branch',
90
+ slot: { player: '$cond', obj: '__ns' },
91
+ range: '1',
92
+ };
93
+ expect(instr.kind).toBe('call_if_matches');
94
+ });
95
+ test('call_unless_matches instruction', () => {
96
+ const instr = {
97
+ kind: 'call_unless_matches',
98
+ fn: 'test:branch',
99
+ slot: { player: '$cond', obj: '__ns' },
100
+ range: '1',
101
+ };
102
+ expect(instr.kind).toBe('call_unless_matches');
103
+ });
104
+ test('call_if_score instruction', () => {
105
+ const instr = {
106
+ kind: 'call_if_score',
107
+ fn: 'test:check',
108
+ a: { player: '$x', obj: '__ns' },
109
+ op: 'lt',
110
+ b: { player: '$y', obj: '__ns' },
111
+ };
112
+ expect(instr.kind).toBe('call_if_score');
113
+ });
114
+ test('call_unless_score instruction', () => {
115
+ const instr = {
116
+ kind: 'call_unless_score',
117
+ fn: 'test:check',
118
+ a: { player: '$x', obj: '__ns' },
119
+ op: 'ge',
120
+ b: { player: '$y', obj: '__ns' },
121
+ };
122
+ expect(instr.kind).toBe('call_unless_score');
123
+ });
124
+ test('call_context instruction', () => {
125
+ const instr = {
126
+ kind: 'call_context',
127
+ fn: 'test:helper',
128
+ subcommands: [{ kind: 'as', selector: '@e[tag=foo]' }, { kind: 'at_self' }],
129
+ };
130
+ expect(instr.kind).toBe('call_context');
131
+ });
132
+ test('return_value instruction', () => {
133
+ const instr = { kind: 'return_value', slot: { player: '$result', obj: '__ns' } };
134
+ expect(instr.kind).toBe('return_value');
135
+ });
136
+ test('macro_line instruction', () => {
137
+ const instr = { kind: 'macro_line', template: '$particle end_rod ^$(px) ^$(py) ^5' };
138
+ expect(instr.kind).toBe('macro_line');
139
+ });
140
+ test('raw instruction', () => {
141
+ const instr = { kind: 'raw', cmd: 'say hello' };
142
+ expect(instr.kind).toBe('raw');
143
+ });
144
+ });
145
+ describe('LIR types — LIRFunction', () => {
146
+ test('basic function structure', () => {
147
+ const fn = {
148
+ name: 'main',
149
+ instructions: [
150
+ { kind: 'score_set', dst: { player: '$x', obj: '__ns' }, value: 0 },
151
+ ],
152
+ isMacro: false,
153
+ macroParams: [],
154
+ };
155
+ expect(fn.name).toBe('main');
156
+ expect(fn.instructions).toHaveLength(1);
157
+ expect(fn.isMacro).toBe(false);
158
+ expect(fn.macroParams).toEqual([]);
159
+ });
160
+ test('macro function structure', () => {
161
+ const fn = {
162
+ name: 'draw_pt',
163
+ instructions: [
164
+ { kind: 'macro_line', template: '$particle end_rod ^$(px) ^$(py) ^5' },
165
+ ],
166
+ isMacro: true,
167
+ macroParams: ['px', 'py'],
168
+ };
169
+ expect(fn.isMacro).toBe(true);
170
+ expect(fn.macroParams).toEqual(['px', 'py']);
171
+ });
172
+ });
173
+ describe('LIR types — LIRModule', () => {
174
+ test('module structure', () => {
175
+ const mod = {
176
+ functions: [],
177
+ namespace: 'mypack',
178
+ objective: '__mypack',
179
+ };
180
+ expect(mod.namespace).toBe('mypack');
181
+ expect(mod.objective).toBe('__mypack');
182
+ expect(mod.functions).toEqual([]);
183
+ });
184
+ });
185
+ //# sourceMappingURL=types.test.js.map
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,221 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const verify_1 = require("../../lir/verify");
4
+ const OBJ = '__test';
5
+ const NS = 'test';
6
+ function mkModule(functions) {
7
+ return { functions, namespace: NS, objective: OBJ };
8
+ }
9
+ function mkFn(name, instructions, isMacro = false, macroParams = []) {
10
+ return { name, instructions, isMacro, macroParams };
11
+ }
12
+ function slot(name) {
13
+ return { player: `$${name}`, obj: OBJ };
14
+ }
15
+ // ---------------------------------------------------------------------------
16
+ // Objective checks
17
+ // ---------------------------------------------------------------------------
18
+ describe('LIR verifier — objective checks', () => {
19
+ test('accepts slots with correct objective', () => {
20
+ const mod = mkModule([
21
+ mkFn('main', [
22
+ { kind: 'score_set', dst: slot('x'), value: 42 },
23
+ { kind: 'score_copy', dst: slot('y'), src: slot('x') },
24
+ ]),
25
+ ]);
26
+ expect((0, verify_1.verifyLIR)(mod)).toEqual([]);
27
+ });
28
+ test('rejects slot with wrong objective', () => {
29
+ const mod = mkModule([
30
+ mkFn('main', [
31
+ { kind: 'score_set', dst: { player: '$x', obj: '__wrong' }, value: 42 },
32
+ ]),
33
+ ]);
34
+ const errors = (0, verify_1.verifyLIR)(mod);
35
+ expect(errors.length).toBe(1);
36
+ expect(errors[0].message).toContain('objective');
37
+ expect(errors[0].message).toContain('__wrong');
38
+ });
39
+ test('rejects wrong objective in src slot', () => {
40
+ const mod = mkModule([
41
+ mkFn('main', [
42
+ { kind: 'score_copy', dst: slot('x'), src: { player: '$y', obj: '__bad' } },
43
+ ]),
44
+ ]);
45
+ const errors = (0, verify_1.verifyLIR)(mod);
46
+ expect(errors.length).toBe(1);
47
+ expect(errors[0].message).toContain('__bad');
48
+ });
49
+ test('checks slots in score_swap', () => {
50
+ const mod = mkModule([
51
+ mkFn('main', [
52
+ { kind: 'score_swap', a: { player: '$x', obj: '__bad' }, b: slot('y') },
53
+ ]),
54
+ ]);
55
+ const errors = (0, verify_1.verifyLIR)(mod);
56
+ expect(errors.length).toBe(1);
57
+ expect(errors[0].message).toContain('__bad');
58
+ });
59
+ test('checks slots in store_cmd_to_score (recursive)', () => {
60
+ const mod = mkModule([
61
+ mkFn('main', [
62
+ {
63
+ kind: 'store_cmd_to_score',
64
+ dst: slot('r'),
65
+ cmd: {
66
+ kind: 'call_if_score',
67
+ fn: 'test:main',
68
+ a: { player: '$a', obj: '__bad' },
69
+ op: 'eq',
70
+ b: slot('b'),
71
+ },
72
+ },
73
+ ]),
74
+ ]);
75
+ const errors = (0, verify_1.verifyLIR)(mod);
76
+ expect(errors.length).toBe(1);
77
+ expect(errors[0].message).toContain('__bad');
78
+ });
79
+ test('checks slot in call_if_matches', () => {
80
+ const mod = mkModule([
81
+ mkFn('main', [
82
+ {
83
+ kind: 'call_if_matches',
84
+ fn: 'test:main',
85
+ slot: { player: '$c', obj: '__bad' },
86
+ range: '1',
87
+ },
88
+ ]),
89
+ ]);
90
+ const errors = (0, verify_1.verifyLIR)(mod);
91
+ expect(errors.length).toBe(1);
92
+ });
93
+ test('checks slot in return_value', () => {
94
+ const mod = mkModule([
95
+ mkFn('main', [
96
+ { kind: 'return_value', slot: { player: '$r', obj: '__bad' } },
97
+ ]),
98
+ ]);
99
+ const errors = (0, verify_1.verifyLIR)(mod);
100
+ expect(errors.length).toBe(1);
101
+ });
102
+ });
103
+ // ---------------------------------------------------------------------------
104
+ // Function reference checks
105
+ // ---------------------------------------------------------------------------
106
+ describe('LIR verifier — function references', () => {
107
+ test('accepts call to existing function', () => {
108
+ const mod = mkModule([
109
+ mkFn('main', [{ kind: 'call', fn: 'test:helper' }]),
110
+ mkFn('helper', []),
111
+ ]);
112
+ expect((0, verify_1.verifyLIR)(mod)).toEqual([]);
113
+ });
114
+ test('rejects call to undefined function', () => {
115
+ const mod = mkModule([
116
+ mkFn('main', [{ kind: 'call', fn: 'test:nonexistent' }]),
117
+ ]);
118
+ const errors = (0, verify_1.verifyLIR)(mod);
119
+ expect(errors.length).toBe(1);
120
+ expect(errors[0].message).toContain('undefined function');
121
+ expect(errors[0].message).toContain('nonexistent');
122
+ });
123
+ test('rejects call_macro to undefined function', () => {
124
+ const mod = mkModule([
125
+ mkFn('main', [{ kind: 'call_macro', fn: 'test:missing', storage: 'rs:macro_args' }]),
126
+ ]);
127
+ const errors = (0, verify_1.verifyLIR)(mod);
128
+ expect(errors.length).toBe(1);
129
+ expect(errors[0].message).toContain('undefined function');
130
+ });
131
+ test('rejects call_if_matches to undefined function', () => {
132
+ const mod = mkModule([
133
+ mkFn('main', [
134
+ { kind: 'call_if_matches', fn: 'test:missing', slot: slot('c'), range: '1' },
135
+ ]),
136
+ ]);
137
+ const errors = (0, verify_1.verifyLIR)(mod);
138
+ expect(errors.length).toBe(1);
139
+ expect(errors[0].message).toContain('undefined function');
140
+ });
141
+ test('rejects call_context to undefined function', () => {
142
+ const mod = mkModule([
143
+ mkFn('main', [
144
+ { kind: 'call_context', fn: 'test:missing', subcommands: [{ kind: 'at_self' }] },
145
+ ]),
146
+ ]);
147
+ const errors = (0, verify_1.verifyLIR)(mod);
148
+ expect(errors.length).toBe(1);
149
+ expect(errors[0].message).toContain('undefined function');
150
+ });
151
+ test('checks function refs inside store_cmd_to_score', () => {
152
+ const mod = mkModule([
153
+ mkFn('main', [
154
+ {
155
+ kind: 'store_cmd_to_score',
156
+ dst: slot('r'),
157
+ cmd: { kind: 'call', fn: 'test:missing' },
158
+ },
159
+ ]),
160
+ ]);
161
+ const errors = (0, verify_1.verifyLIR)(mod);
162
+ expect(errors.length).toBe(1);
163
+ expect(errors[0].message).toContain('undefined function');
164
+ });
165
+ });
166
+ // ---------------------------------------------------------------------------
167
+ // Macro line checks
168
+ // ---------------------------------------------------------------------------
169
+ describe('LIR verifier — macro_line', () => {
170
+ test('accepts macro_line in macro function', () => {
171
+ const mod = mkModule([
172
+ mkFn('draw', [
173
+ { kind: 'macro_line', template: '$particle end_rod ^$(px)' },
174
+ ], true, ['px']),
175
+ ]);
176
+ expect((0, verify_1.verifyLIR)(mod)).toEqual([]);
177
+ });
178
+ test('rejects macro_line in non-macro function', () => {
179
+ const mod = mkModule([
180
+ mkFn('main', [
181
+ { kind: 'macro_line', template: '$particle end_rod ^$(px)' },
182
+ ], false),
183
+ ]);
184
+ const errors = (0, verify_1.verifyLIR)(mod);
185
+ expect(errors.length).toBe(1);
186
+ expect(errors[0].message).toContain('macro_line');
187
+ expect(errors[0].message).toContain('non-macro');
188
+ });
189
+ });
190
+ // ---------------------------------------------------------------------------
191
+ // Clean module
192
+ // ---------------------------------------------------------------------------
193
+ describe('LIR verifier — clean module', () => {
194
+ test('accepts a well-formed module', () => {
195
+ const mod = mkModule([
196
+ mkFn('main', [
197
+ { kind: 'score_set', dst: slot('t0'), value: 1 },
198
+ { kind: 'score_set', dst: slot('t1'), value: 2 },
199
+ { kind: 'score_copy', dst: slot('r'), src: slot('t0') },
200
+ { kind: 'score_add', dst: slot('r'), src: slot('t1') },
201
+ { kind: 'call', fn: 'test:helper' },
202
+ { kind: 'return_value', slot: slot('r') },
203
+ ]),
204
+ mkFn('helper', [
205
+ { kind: 'raw', cmd: 'say hello' },
206
+ ]),
207
+ ]);
208
+ expect((0, verify_1.verifyLIR)(mod)).toEqual([]);
209
+ });
210
+ test('raw and nbt instructions do not trigger errors', () => {
211
+ const mod = mkModule([
212
+ mkFn('main', [
213
+ { kind: 'raw', cmd: 'say hi' },
214
+ { kind: 'nbt_set_literal', ns: 'rs:data', path: 'x', value: '42' },
215
+ { kind: 'nbt_copy', srcNs: 'rs:a', srcPath: 'x', dstNs: 'rs:b', dstPath: 'y' },
216
+ ]),
217
+ ]);
218
+ expect((0, verify_1.verifyLIR)(mod)).toEqual([]);
219
+ });
220
+ });
221
+ //# sourceMappingURL=verify.test.js.map
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const lexer_1 = require("../../../src/lexer");
4
+ const parser_1 = require("../../../src/parser");
5
+ const lower_1 = require("../../hir/lower");
6
+ const lower_2 = require("../../mir/lower");
7
+ const verify_1 = require("../../mir/verify");
8
+ function compile(source) {
9
+ const tokens = new lexer_1.Lexer(source).tokenize();
10
+ const ast = new parser_1.Parser(tokens).parse('test');
11
+ const hir = (0, lower_1.lowerToHIR)(ast);
12
+ return (0, lower_2.lowerToMIR)(hir);
13
+ }
14
+ function getEntryInstrs(mod) {
15
+ const fn = mod.functions[0];
16
+ const entry = fn.blocks.find(b => b.id === fn.entry);
17
+ return entry.instrs;
18
+ }
19
+ describe('MIR lowering — integer arithmetic', () => {
20
+ test('simple addition: let x = a + b', () => {
21
+ const mod = compile('fn f(a: int, b: int): int { return a + b; }');
22
+ expect((0, verify_1.verifyMIR)(mod)).toEqual([]);
23
+ const instrs = getEntryInstrs(mod);
24
+ // Should have an add instruction
25
+ const addInstr = instrs.find(i => i.kind === 'add');
26
+ expect(addInstr).toBeDefined();
27
+ expect(addInstr.kind).toBe('add');
28
+ });
29
+ test('chained arithmetic: a + b * c', () => {
30
+ const mod = compile('fn f(a: int, b: int, c: int): int { return a + b * c; }');
31
+ expect((0, verify_1.verifyMIR)(mod)).toEqual([]);
32
+ const instrs = getEntryInstrs(mod);
33
+ // Should have both mul and add
34
+ const kinds = instrs.map(i => i.kind);
35
+ expect(kinds).toContain('mul');
36
+ expect(kinds).toContain('add');
37
+ // mul should come before add (b*c computed first)
38
+ const mulIdx = kinds.indexOf('mul');
39
+ const addIdx = kinds.indexOf('add');
40
+ expect(mulIdx).toBeLessThan(addIdx);
41
+ });
42
+ test('subtraction and division', () => {
43
+ const mod = compile('fn f(a: int, b: int): int { return (a - b) / b; }');
44
+ expect((0, verify_1.verifyMIR)(mod)).toEqual([]);
45
+ const instrs = getEntryInstrs(mod);
46
+ const kinds = instrs.map(i => i.kind);
47
+ expect(kinds).toContain('sub');
48
+ expect(kinds).toContain('div');
49
+ });
50
+ test('modulo', () => {
51
+ const mod = compile('fn f(a: int, b: int): int { return a % b; }');
52
+ expect((0, verify_1.verifyMIR)(mod)).toEqual([]);
53
+ const instrs = getEntryInstrs(mod);
54
+ expect(instrs.some(i => i.kind === 'mod')).toBe(true);
55
+ });
56
+ test('negation', () => {
57
+ const mod = compile('fn f(a: int): int { return -a; }');
58
+ expect((0, verify_1.verifyMIR)(mod)).toEqual([]);
59
+ const instrs = getEntryInstrs(mod);
60
+ expect(instrs.some(i => i.kind === 'neg')).toBe(true);
61
+ });
62
+ test('not operator', () => {
63
+ const mod = compile('fn f(a: bool): bool { return !a; }');
64
+ expect((0, verify_1.verifyMIR)(mod)).toEqual([]);
65
+ const instrs = getEntryInstrs(mod);
66
+ expect(instrs.some(i => i.kind === 'not')).toBe(true);
67
+ });
68
+ test('comparison operators produce cmp instructions', () => {
69
+ const mod = compile('fn f(a: int, b: int): bool { return a < b; }');
70
+ expect((0, verify_1.verifyMIR)(mod)).toEqual([]);
71
+ const instrs = getEntryInstrs(mod);
72
+ const cmpInstr = instrs.find(i => i.kind === 'cmp');
73
+ expect(cmpInstr).toBeDefined();
74
+ expect(cmpInstr.op).toBe('lt');
75
+ });
76
+ test('let binding produces copy instruction', () => {
77
+ const mod = compile('fn f(a: int): int { let x: int = a; return x; }');
78
+ expect((0, verify_1.verifyMIR)(mod)).toEqual([]);
79
+ const instrs = getEntryInstrs(mod);
80
+ expect(instrs.some(i => i.kind === 'copy')).toBe(true);
81
+ });
82
+ test('constant literal produces const instruction', () => {
83
+ const mod = compile('fn f(): int { return 42; }');
84
+ expect((0, verify_1.verifyMIR)(mod)).toEqual([]);
85
+ // The return terminator should have the const value
86
+ const fn = mod.functions[0];
87
+ const entry = fn.blocks.find(b => b.id === fn.entry);
88
+ expect(entry.term.kind).toBe('return');
89
+ const ret = entry.term;
90
+ expect(ret.value).toEqual({ kind: 'const', value: 42 });
91
+ });
92
+ test('function call produces call instruction', () => {
93
+ const mod = compile('fn add(a: int, b: int): int { return a + b; } fn f(): int { return add(1, 2); }');
94
+ expect((0, verify_1.verifyMIR)(mod)).toEqual([]);
95
+ // f is the second function
96
+ const fn = mod.functions[1];
97
+ const entry = fn.blocks.find(b => b.id === fn.entry);
98
+ const callInstr = entry.instrs.find(i => i.kind === 'call');
99
+ expect(callInstr).toBeDefined();
100
+ expect(callInstr.fn).toBe('add');
101
+ expect(callInstr.args).toHaveLength(2);
102
+ });
103
+ test('3-address form: each instruction has fresh dst', () => {
104
+ const mod = compile('fn f(a: int, b: int, c: int): int { return a + b + c; }');
105
+ expect((0, verify_1.verifyMIR)(mod)).toEqual([]);
106
+ const instrs = getEntryInstrs(mod);
107
+ const dsts = instrs.filter(i => 'dst' in i).map(i => i.dst);
108
+ // All destination temps should be unique
109
+ expect(new Set(dsts).size).toBe(dsts.length);
110
+ });
111
+ });
112
+ describe('MIR lowering — module structure', () => {
113
+ test('namespace and objective set correctly', () => {
114
+ const mod = compile('fn f(): void {}');
115
+ expect(mod.namespace).toBe('test');
116
+ expect(mod.objective).toBe('__test');
117
+ });
118
+ test('multiple functions', () => {
119
+ const mod = compile('fn a(): void {} fn b(): void {} fn c(): void {}');
120
+ expect(mod.functions).toHaveLength(3);
121
+ expect(mod.functions.map(f => f.name)).toEqual(['a', 'b', 'c']);
122
+ });
123
+ test('function params are mapped to temps', () => {
124
+ const mod = compile('fn f(x: int, y: int): int { return x + y; }');
125
+ expect(mod.functions[0].params).toHaveLength(2);
126
+ expect(mod.functions[0].params[0].name).toMatch(/^t\d+$/);
127
+ expect(mod.functions[0].params[1].name).toMatch(/^t\d+$/);
128
+ });
129
+ });
130
+ //# sourceMappingURL=arithmetic.test.js.map
@@ -0,0 +1 @@
1
+ export {};