redscript-mc 1.2.29 → 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 (274) 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/README.md +29 -28
  8. package/README.zh.md +28 -28
  9. package/demo.gif +0 -0
  10. package/dist/cli.js +2 -554
  11. package/dist/compile.js +2 -266
  12. package/dist/index.js +2 -159
  13. package/dist/lexer/index.js +9 -1
  14. package/dist/lowering/index.js +22 -5
  15. package/dist/src/__tests__/cli.test.d.ts +1 -0
  16. package/dist/src/__tests__/cli.test.js +104 -0
  17. package/dist/src/__tests__/codegen.test.d.ts +1 -0
  18. package/dist/src/__tests__/codegen.test.js +152 -0
  19. package/dist/src/__tests__/compile-all.test.d.ts +10 -0
  20. package/dist/src/__tests__/compile-all.test.js +108 -0
  21. package/dist/src/__tests__/dce.test.d.ts +1 -0
  22. package/dist/src/__tests__/dce.test.js +102 -0
  23. package/dist/src/__tests__/diagnostics.test.d.ts +4 -0
  24. package/dist/src/__tests__/diagnostics.test.js +177 -0
  25. package/dist/src/__tests__/e2e.test.d.ts +6 -0
  26. package/dist/src/__tests__/e2e.test.js +1789 -0
  27. package/dist/src/__tests__/entity-types.test.d.ts +1 -0
  28. package/dist/src/__tests__/entity-types.test.js +203 -0
  29. package/dist/src/__tests__/formatter.test.d.ts +1 -0
  30. package/dist/src/__tests__/formatter.test.js +40 -0
  31. package/dist/src/__tests__/lexer.test.d.ts +1 -0
  32. package/dist/src/__tests__/lexer.test.js +343 -0
  33. package/dist/src/__tests__/lowering.test.d.ts +1 -0
  34. package/dist/src/__tests__/lowering.test.js +1015 -0
  35. package/dist/src/__tests__/macro.test.d.ts +8 -0
  36. package/dist/src/__tests__/macro.test.js +306 -0
  37. package/dist/src/__tests__/mc-integration.test.d.ts +12 -0
  38. package/dist/src/__tests__/mc-integration.test.js +817 -0
  39. package/dist/src/__tests__/mc-syntax.test.d.ts +1 -0
  40. package/dist/src/__tests__/mc-syntax.test.js +124 -0
  41. package/dist/src/__tests__/nbt.test.d.ts +1 -0
  42. package/dist/src/__tests__/nbt.test.js +82 -0
  43. package/dist/src/__tests__/optimizer-advanced.test.d.ts +1 -0
  44. package/dist/src/__tests__/optimizer-advanced.test.js +124 -0
  45. package/dist/src/__tests__/optimizer.test.d.ts +1 -0
  46. package/dist/src/__tests__/optimizer.test.js +149 -0
  47. package/dist/src/__tests__/parser.test.d.ts +1 -0
  48. package/dist/src/__tests__/parser.test.js +807 -0
  49. package/dist/src/__tests__/repl.test.d.ts +1 -0
  50. package/dist/src/__tests__/repl.test.js +27 -0
  51. package/dist/src/__tests__/runtime.test.d.ts +1 -0
  52. package/dist/src/__tests__/runtime.test.js +289 -0
  53. package/dist/src/__tests__/stdlib-advanced.test.d.ts +4 -0
  54. package/dist/src/__tests__/stdlib-advanced.test.js +374 -0
  55. package/dist/src/__tests__/stdlib-bigint.test.d.ts +7 -0
  56. package/dist/src/__tests__/stdlib-bigint.test.js +426 -0
  57. package/dist/src/__tests__/stdlib-math.test.d.ts +7 -0
  58. package/dist/src/__tests__/stdlib-math.test.js +351 -0
  59. package/dist/src/__tests__/stdlib-vec.test.d.ts +4 -0
  60. package/dist/src/__tests__/stdlib-vec.test.js +263 -0
  61. package/dist/src/__tests__/structure-optimizer.test.d.ts +1 -0
  62. package/dist/src/__tests__/structure-optimizer.test.js +33 -0
  63. package/dist/src/__tests__/typechecker.test.d.ts +1 -0
  64. package/dist/src/__tests__/typechecker.test.js +552 -0
  65. package/dist/src/__tests__/var-allocator.test.d.ts +1 -0
  66. package/dist/src/__tests__/var-allocator.test.js +69 -0
  67. package/dist/src/ast/types.d.ts +515 -0
  68. package/dist/src/ast/types.js +9 -0
  69. package/dist/src/builtins/metadata.d.ts +36 -0
  70. package/dist/src/builtins/metadata.js +1014 -0
  71. package/dist/src/cli.d.ts +11 -0
  72. package/dist/src/cli.js +443 -0
  73. package/dist/src/codegen/cmdblock/index.d.ts +26 -0
  74. package/dist/src/codegen/cmdblock/index.js +45 -0
  75. package/dist/src/codegen/mcfunction/index.d.ts +40 -0
  76. package/dist/src/codegen/mcfunction/index.js +606 -0
  77. package/dist/src/codegen/structure/index.d.ts +24 -0
  78. package/dist/src/codegen/structure/index.js +279 -0
  79. package/dist/src/codegen/var-allocator.d.ts +45 -0
  80. package/dist/src/codegen/var-allocator.js +104 -0
  81. package/dist/src/compile.d.ts +37 -0
  82. package/dist/src/compile.js +165 -0
  83. package/dist/src/diagnostics/index.d.ts +44 -0
  84. package/dist/src/diagnostics/index.js +140 -0
  85. package/dist/src/events/types.d.ts +35 -0
  86. package/dist/src/events/types.js +59 -0
  87. package/dist/src/formatter/index.d.ts +1 -0
  88. package/dist/src/formatter/index.js +26 -0
  89. package/dist/src/index.d.ts +22 -0
  90. package/dist/src/index.js +45 -0
  91. package/dist/src/ir/builder.d.ts +33 -0
  92. package/dist/src/ir/builder.js +99 -0
  93. package/dist/src/ir/types.d.ts +132 -0
  94. package/dist/src/ir/types.js +15 -0
  95. package/dist/src/lexer/index.d.ts +37 -0
  96. package/dist/src/lexer/index.js +569 -0
  97. package/dist/src/lowering/index.d.ts +188 -0
  98. package/dist/src/lowering/index.js +3405 -0
  99. package/dist/src/mc-test/client.d.ts +128 -0
  100. package/dist/src/mc-test/client.js +174 -0
  101. package/dist/src/mc-test/runner.d.ts +28 -0
  102. package/dist/src/mc-test/runner.js +151 -0
  103. package/dist/src/mc-test/setup.d.ts +11 -0
  104. package/dist/src/mc-test/setup.js +98 -0
  105. package/dist/src/mc-validator/index.d.ts +17 -0
  106. package/dist/src/mc-validator/index.js +322 -0
  107. package/dist/src/nbt/index.d.ts +86 -0
  108. package/dist/src/nbt/index.js +250 -0
  109. package/dist/src/optimizer/commands.d.ts +38 -0
  110. package/dist/src/optimizer/commands.js +451 -0
  111. package/dist/src/optimizer/dce.d.ts +34 -0
  112. package/dist/src/optimizer/dce.js +639 -0
  113. package/dist/src/optimizer/passes.d.ts +34 -0
  114. package/dist/src/optimizer/passes.js +243 -0
  115. package/dist/src/optimizer/structure.d.ts +9 -0
  116. package/dist/src/optimizer/structure.js +356 -0
  117. package/dist/src/parser/index.d.ts +93 -0
  118. package/dist/src/parser/index.js +1687 -0
  119. package/dist/src/repl.d.ts +16 -0
  120. package/dist/src/repl.js +165 -0
  121. package/dist/src/runtime/index.d.ts +107 -0
  122. package/dist/src/runtime/index.js +1409 -0
  123. package/dist/src/typechecker/index.d.ts +61 -0
  124. package/dist/src/typechecker/index.js +1034 -0
  125. package/dist/src/types/entity-hierarchy.d.ts +29 -0
  126. package/dist/src/types/entity-hierarchy.js +107 -0
  127. package/dist/src2/__tests__/e2e/basic.test.d.ts +8 -0
  128. package/dist/src2/__tests__/e2e/basic.test.js +140 -0
  129. package/dist/src2/__tests__/e2e/macros.test.d.ts +9 -0
  130. package/dist/src2/__tests__/e2e/macros.test.js +182 -0
  131. package/dist/src2/__tests__/e2e/migrate.test.d.ts +13 -0
  132. package/dist/src2/__tests__/e2e/migrate.test.js +2739 -0
  133. package/dist/src2/__tests__/hir/desugar.test.d.ts +1 -0
  134. package/dist/src2/__tests__/hir/desugar.test.js +234 -0
  135. package/dist/src2/__tests__/lir/lower.test.d.ts +1 -0
  136. package/dist/src2/__tests__/lir/lower.test.js +559 -0
  137. package/dist/src2/__tests__/lir/types.test.d.ts +1 -0
  138. package/dist/src2/__tests__/lir/types.test.js +185 -0
  139. package/dist/src2/__tests__/lir/verify.test.d.ts +1 -0
  140. package/dist/src2/__tests__/lir/verify.test.js +221 -0
  141. package/dist/src2/__tests__/mir/arithmetic.test.d.ts +1 -0
  142. package/dist/src2/__tests__/mir/arithmetic.test.js +130 -0
  143. package/dist/src2/__tests__/mir/control-flow.test.d.ts +1 -0
  144. package/dist/src2/__tests__/mir/control-flow.test.js +205 -0
  145. package/dist/src2/__tests__/mir/verify.test.d.ts +1 -0
  146. package/dist/src2/__tests__/mir/verify.test.js +223 -0
  147. package/dist/src2/__tests__/optimizer/block_merge.test.d.ts +1 -0
  148. package/dist/src2/__tests__/optimizer/block_merge.test.js +78 -0
  149. package/dist/src2/__tests__/optimizer/branch_simplify.test.d.ts +1 -0
  150. package/dist/src2/__tests__/optimizer/branch_simplify.test.js +58 -0
  151. package/dist/src2/__tests__/optimizer/constant_fold.test.d.ts +1 -0
  152. package/dist/src2/__tests__/optimizer/constant_fold.test.js +131 -0
  153. package/dist/src2/__tests__/optimizer/copy_prop.test.d.ts +1 -0
  154. package/dist/src2/__tests__/optimizer/copy_prop.test.js +91 -0
  155. package/dist/src2/__tests__/optimizer/dce.test.d.ts +1 -0
  156. package/dist/src2/__tests__/optimizer/dce.test.js +76 -0
  157. package/dist/src2/__tests__/optimizer/pipeline.test.d.ts +1 -0
  158. package/dist/src2/__tests__/optimizer/pipeline.test.js +102 -0
  159. package/dist/src2/emit/compile.d.ts +19 -0
  160. package/dist/src2/emit/compile.js +80 -0
  161. package/dist/src2/emit/index.d.ts +17 -0
  162. package/dist/src2/emit/index.js +172 -0
  163. package/dist/src2/hir/lower.d.ts +15 -0
  164. package/dist/src2/hir/lower.js +378 -0
  165. package/dist/src2/hir/types.d.ts +373 -0
  166. package/dist/src2/hir/types.js +16 -0
  167. package/dist/src2/lir/lower.d.ts +15 -0
  168. package/dist/src2/lir/lower.js +453 -0
  169. package/dist/src2/lir/types.d.ts +136 -0
  170. package/dist/src2/lir/types.js +11 -0
  171. package/dist/src2/lir/verify.d.ts +14 -0
  172. package/dist/src2/lir/verify.js +113 -0
  173. package/dist/src2/mir/lower.d.ts +9 -0
  174. package/dist/src2/mir/lower.js +1030 -0
  175. package/dist/src2/mir/macro.d.ts +22 -0
  176. package/dist/src2/mir/macro.js +168 -0
  177. package/dist/src2/mir/types.d.ts +183 -0
  178. package/dist/src2/mir/types.js +11 -0
  179. package/dist/src2/mir/verify.d.ts +16 -0
  180. package/dist/src2/mir/verify.js +216 -0
  181. package/dist/src2/optimizer/block_merge.d.ts +12 -0
  182. package/dist/src2/optimizer/block_merge.js +84 -0
  183. package/dist/src2/optimizer/branch_simplify.d.ts +9 -0
  184. package/dist/src2/optimizer/branch_simplify.js +28 -0
  185. package/dist/src2/optimizer/constant_fold.d.ts +10 -0
  186. package/dist/src2/optimizer/constant_fold.js +85 -0
  187. package/dist/src2/optimizer/copy_prop.d.ts +9 -0
  188. package/dist/src2/optimizer/copy_prop.js +113 -0
  189. package/dist/src2/optimizer/dce.d.ts +8 -0
  190. package/dist/src2/optimizer/dce.js +155 -0
  191. package/dist/src2/optimizer/pipeline.d.ts +10 -0
  192. package/dist/src2/optimizer/pipeline.js +42 -0
  193. package/dist/tsconfig.tsbuildinfo +1 -0
  194. package/docs/compiler-pipeline-redesign.md +2243 -0
  195. package/docs/optimization-ideas.md +1076 -0
  196. package/editors/vscode/package-lock.json +3 -3
  197. package/editors/vscode/package.json +1 -1
  198. package/examples/readme-demo.mcrs +44 -66
  199. package/jest.config.js +1 -1
  200. package/package.json +6 -5
  201. package/scripts/postbuild.js +15 -0
  202. package/src/__tests__/cli.test.ts +8 -220
  203. package/src/__tests__/dce.test.ts +11 -56
  204. package/src/__tests__/diagnostics.test.ts +59 -38
  205. package/src/__tests__/mc-integration.test.ts +1 -2
  206. package/src/ast/types.ts +6 -1
  207. package/src/cli.ts +29 -156
  208. package/src/compile.ts +6 -162
  209. package/src/index.ts +14 -178
  210. package/src/lexer/index.ts +9 -1
  211. package/src/mc-test/runner.ts +4 -3
  212. package/src/parser/index.ts +1 -1
  213. package/src/repl.ts +1 -1
  214. package/src/runtime/index.ts +1 -1
  215. package/src2/__tests__/e2e/basic.test.ts +154 -0
  216. package/src2/__tests__/e2e/macros.test.ts +199 -0
  217. package/src2/__tests__/e2e/migrate.test.ts +3008 -0
  218. package/src2/__tests__/hir/desugar.test.ts +263 -0
  219. package/src2/__tests__/lir/lower.test.ts +619 -0
  220. package/src2/__tests__/lir/types.test.ts +207 -0
  221. package/src2/__tests__/lir/verify.test.ts +249 -0
  222. package/src2/__tests__/mir/arithmetic.test.ts +156 -0
  223. package/src2/__tests__/mir/control-flow.test.ts +242 -0
  224. package/src2/__tests__/mir/verify.test.ts +254 -0
  225. package/src2/__tests__/optimizer/block_merge.test.ts +84 -0
  226. package/src2/__tests__/optimizer/branch_simplify.test.ts +64 -0
  227. package/src2/__tests__/optimizer/constant_fold.test.ts +145 -0
  228. package/src2/__tests__/optimizer/copy_prop.test.ts +99 -0
  229. package/src2/__tests__/optimizer/dce.test.ts +83 -0
  230. package/src2/__tests__/optimizer/pipeline.test.ts +116 -0
  231. package/src2/emit/compile.ts +99 -0
  232. package/src2/emit/index.ts +222 -0
  233. package/src2/hir/lower.ts +428 -0
  234. package/src2/hir/types.ts +216 -0
  235. package/src2/lir/lower.ts +556 -0
  236. package/src2/lir/types.ts +109 -0
  237. package/src2/lir/verify.ts +129 -0
  238. package/src2/mir/lower.ts +1160 -0
  239. package/src2/mir/macro.ts +167 -0
  240. package/src2/mir/types.ts +106 -0
  241. package/src2/mir/verify.ts +218 -0
  242. package/src2/optimizer/block_merge.ts +93 -0
  243. package/src2/optimizer/branch_simplify.ts +27 -0
  244. package/src2/optimizer/constant_fold.ts +88 -0
  245. package/src2/optimizer/copy_prop.ts +106 -0
  246. package/src2/optimizer/dce.ts +133 -0
  247. package/src2/optimizer/pipeline.ts +44 -0
  248. package/tsconfig.json +2 -2
  249. package/src/__tests__/codegen.test.ts +0 -161
  250. package/src/__tests__/e2e.test.ts +0 -2039
  251. package/src/__tests__/entity-types.test.ts +0 -236
  252. package/src/__tests__/lowering.test.ts +0 -1185
  253. package/src/__tests__/macro.test.ts +0 -343
  254. package/src/__tests__/nbt.test.ts +0 -58
  255. package/src/__tests__/optimizer-advanced.test.ts +0 -144
  256. package/src/__tests__/optimizer.test.ts +0 -162
  257. package/src/__tests__/runtime.test.ts +0 -305
  258. package/src/__tests__/stdlib-advanced.test.ts +0 -379
  259. package/src/__tests__/stdlib-bigint.test.ts +0 -427
  260. package/src/__tests__/stdlib-math.test.ts +0 -374
  261. package/src/__tests__/stdlib-vec.test.ts +0 -259
  262. package/src/__tests__/structure-optimizer.test.ts +0 -38
  263. package/src/__tests__/var-allocator.test.ts +0 -75
  264. package/src/codegen/cmdblock/index.ts +0 -63
  265. package/src/codegen/mcfunction/index.ts +0 -662
  266. package/src/codegen/structure/index.ts +0 -346
  267. package/src/codegen/var-allocator.ts +0 -104
  268. package/src/ir/builder.ts +0 -116
  269. package/src/ir/types.ts +0 -134
  270. package/src/lowering/index.ts +0 -3860
  271. package/src/optimizer/commands.ts +0 -534
  272. package/src/optimizer/dce.ts +0 -679
  273. package/src/optimizer/passes.ts +0 -250
  274. package/src/optimizer/structure.ts +0 -450
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Entity Type Hierarchy
3
+ *
4
+ * Closed inheritance tree mapping to Minecraft's entity registry.
5
+ * Used for type narrowing (is checks), selector<T> annotations,
6
+ * and W_IMPOSSIBLE_AS warnings.
7
+ */
8
+ export interface EntityTypeNode {
9
+ name: string;
10
+ mcId: string | null;
11
+ abstract: boolean;
12
+ parent: string | null;
13
+ }
14
+ export declare const ENTITY_TYPES: EntityTypeNode[];
15
+ /** Map from lowercase name → EntityTypeNode */
16
+ export declare const ENTITY_TYPE_MAP: Map<string, EntityTypeNode>;
17
+ /** Map from mcId (without namespace) → EntityTypeNode */
18
+ export declare const ENTITY_TYPE_BY_MCID: Map<string, EntityTypeNode>;
19
+ /** Check if typeA is a subtype of typeB (recursive ancestry) */
20
+ export declare function isSubtype(typeA: string, typeB: string): boolean;
21
+ /** True if one type is a subtype of the other (in either direction) */
22
+ export declare function areCompatibleTypes(outerType: string, innerType: string): boolean;
23
+ /** Get all non-abstract leaf types under a given node */
24
+ export declare function getConcreteSubtypes(typeName: string): EntityTypeNode[];
25
+ /** Parse "type=zombie" from a selector string, return the entity type name or null */
26
+ export declare function getSelectorEntityType(selector: string): string | null;
27
+ /** Determine the base entity type from a selector kind:
28
+ * @a/@p/@r → "Player", @e → "Entity" or from type filter, @s → null */
29
+ export declare function getBaseSelectorType(selector: string): string | null;
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ /**
3
+ * Entity Type Hierarchy
4
+ *
5
+ * Closed inheritance tree mapping to Minecraft's entity registry.
6
+ * Used for type narrowing (is checks), selector<T> annotations,
7
+ * and W_IMPOSSIBLE_AS warnings.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.ENTITY_TYPE_BY_MCID = exports.ENTITY_TYPE_MAP = exports.ENTITY_TYPES = void 0;
11
+ exports.isSubtype = isSubtype;
12
+ exports.areCompatibleTypes = areCompatibleTypes;
13
+ exports.getConcreteSubtypes = getConcreteSubtypes;
14
+ exports.getSelectorEntityType = getSelectorEntityType;
15
+ exports.getBaseSelectorType = getBaseSelectorType;
16
+ exports.ENTITY_TYPES = [
17
+ // Root
18
+ { name: 'Entity', mcId: null, abstract: true, parent: null },
19
+ // Direct children of Entity
20
+ { name: 'Player', mcId: 'minecraft:player', abstract: false, parent: 'Entity' },
21
+ { name: 'ArmorStand', mcId: 'minecraft:armor_stand', abstract: false, parent: 'Entity' },
22
+ { name: 'Item', mcId: 'minecraft:item', abstract: false, parent: 'Entity' },
23
+ { name: 'Arrow', mcId: 'minecraft:arrow', abstract: false, parent: 'Entity' },
24
+ // Mob hierarchy
25
+ { name: 'Mob', mcId: null, abstract: true, parent: 'Entity' },
26
+ // Hostile mobs
27
+ { name: 'HostileMob', mcId: null, abstract: true, parent: 'Mob' },
28
+ { name: 'Zombie', mcId: 'minecraft:zombie', abstract: false, parent: 'HostileMob' },
29
+ { name: 'Skeleton', mcId: 'minecraft:skeleton', abstract: false, parent: 'HostileMob' },
30
+ { name: 'Creeper', mcId: 'minecraft:creeper', abstract: false, parent: 'HostileMob' },
31
+ { name: 'Spider', mcId: 'minecraft:spider', abstract: false, parent: 'HostileMob' },
32
+ { name: 'Enderman', mcId: 'minecraft:enderman', abstract: false, parent: 'HostileMob' },
33
+ { name: 'Blaze', mcId: 'minecraft:blaze', abstract: false, parent: 'HostileMob' },
34
+ { name: 'Witch', mcId: 'minecraft:witch', abstract: false, parent: 'HostileMob' },
35
+ { name: 'Slime', mcId: 'minecraft:slime', abstract: false, parent: 'HostileMob' },
36
+ { name: 'ZombieVillager', mcId: 'minecraft:zombie_villager', abstract: false, parent: 'HostileMob' },
37
+ { name: 'Husk', mcId: 'minecraft:husk', abstract: false, parent: 'HostileMob' },
38
+ { name: 'Drowned', mcId: 'minecraft:drowned', abstract: false, parent: 'HostileMob' },
39
+ { name: 'Stray', mcId: 'minecraft:stray', abstract: false, parent: 'HostileMob' },
40
+ { name: 'WitherSkeleton', mcId: 'minecraft:wither_skeleton', abstract: false, parent: 'HostileMob' },
41
+ { name: 'CaveSpider', mcId: 'minecraft:cave_spider', abstract: false, parent: 'HostileMob' },
42
+ // Passive mobs
43
+ { name: 'PassiveMob', mcId: null, abstract: true, parent: 'Mob' },
44
+ { name: 'Pig', mcId: 'minecraft:pig', abstract: false, parent: 'PassiveMob' },
45
+ { name: 'Cow', mcId: 'minecraft:cow', abstract: false, parent: 'PassiveMob' },
46
+ { name: 'Sheep', mcId: 'minecraft:sheep', abstract: false, parent: 'PassiveMob' },
47
+ { name: 'Chicken', mcId: 'minecraft:chicken', abstract: false, parent: 'PassiveMob' },
48
+ { name: 'Villager', mcId: 'minecraft:villager', abstract: false, parent: 'PassiveMob' },
49
+ { name: 'WanderingTrader', mcId: 'minecraft:wandering_trader', abstract: false, parent: 'PassiveMob' },
50
+ ];
51
+ /** Map from lowercase name → EntityTypeNode */
52
+ exports.ENTITY_TYPE_MAP = new Map(exports.ENTITY_TYPES.map(t => [t.name.toLowerCase(), t]));
53
+ /** Map from mcId (without namespace) → EntityTypeNode */
54
+ exports.ENTITY_TYPE_BY_MCID = new Map(exports.ENTITY_TYPES
55
+ .filter(t => t.mcId !== null)
56
+ .map(t => [t.mcId.replace('minecraft:', ''), t]));
57
+ /** Check if typeA is a subtype of typeB (recursive ancestry) */
58
+ function isSubtype(typeA, typeB) {
59
+ if (typeA === typeB)
60
+ return true;
61
+ const node = exports.ENTITY_TYPE_MAP.get(typeA.toLowerCase());
62
+ if (!node || !node.parent)
63
+ return false;
64
+ return isSubtype(node.parent, typeB);
65
+ }
66
+ /** True if one type is a subtype of the other (in either direction) */
67
+ function areCompatibleTypes(outerType, innerType) {
68
+ return isSubtype(outerType, innerType) || isSubtype(innerType, outerType);
69
+ }
70
+ /** Get all non-abstract leaf types under a given node */
71
+ function getConcreteSubtypes(typeName) {
72
+ const results = [];
73
+ for (const node of exports.ENTITY_TYPES) {
74
+ if (!node.abstract && isSubtype(node.name, typeName)) {
75
+ results.push(node);
76
+ }
77
+ }
78
+ return results;
79
+ }
80
+ /** Parse "type=zombie" from a selector string, return the entity type name or null */
81
+ function getSelectorEntityType(selector) {
82
+ const match = selector.match(/type=(?:minecraft:)?([a-z_]+)/);
83
+ if (!match)
84
+ return null;
85
+ const mcId = match[1];
86
+ const node = exports.ENTITY_TYPE_BY_MCID.get(mcId);
87
+ return node ? node.name : null;
88
+ }
89
+ /** Determine the base entity type from a selector kind:
90
+ * @a/@p/@r → "Player", @e → "Entity" or from type filter, @s → null */
91
+ function getBaseSelectorType(selector) {
92
+ const trimmed = selector.trim();
93
+ // Check for type filter first (works for any selector)
94
+ const typeFromFilter = getSelectorEntityType(trimmed);
95
+ if (trimmed.startsWith('@a') || trimmed.startsWith('@p') || trimmed.startsWith('@r')) {
96
+ return typeFromFilter ?? 'Player';
97
+ }
98
+ if (trimmed.startsWith('@e')) {
99
+ return typeFromFilter ?? 'Entity';
100
+ }
101
+ // @s — context-dependent, we don't know unless there's a type filter
102
+ if (trimmed.startsWith('@s')) {
103
+ return typeFromFilter ?? null;
104
+ }
105
+ return null;
106
+ }
107
+ //# sourceMappingURL=entity-hierarchy.js.map
@@ -0,0 +1,8 @@
1
+ /**
2
+ * End-to-end tests for the v2 compiler pipeline.
3
+ *
4
+ * These tests compile RedScript source through the full pipeline
5
+ * (Lexer → Parser → HIR → MIR → optimize → LIR → emit) and verify
6
+ * the generated .mcfunction output contains expected MC commands.
7
+ */
8
+ export {};
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ /**
3
+ * End-to-end tests for the v2 compiler pipeline.
4
+ *
5
+ * These tests compile RedScript source through the full pipeline
6
+ * (Lexer → Parser → HIR → MIR → optimize → LIR → emit) and verify
7
+ * the generated .mcfunction output contains expected MC commands.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ const compile_1 = require("../../emit/compile");
11
+ function getFile(files, pathSubstr) {
12
+ const f = files.find(f => f.path.includes(pathSubstr));
13
+ return f?.content;
14
+ }
15
+ describe('e2e: basic compilation', () => {
16
+ test('simple arithmetic function produces scoreboard commands', () => {
17
+ const source = `
18
+ fn add(a: int, b: int): int {
19
+ return a + b;
20
+ }
21
+ `;
22
+ const result = (0, compile_1.compile)(source, { namespace: 'test' });
23
+ expect(result.files.length).toBeGreaterThan(0);
24
+ const addFn = getFile(result.files, 'add.mcfunction');
25
+ expect(addFn).toBeDefined();
26
+ expect(addFn).toContain('scoreboard players operation');
27
+ expect(addFn).toContain('__test');
28
+ });
29
+ test('pack.mcmeta is generated with pack_format 26', () => {
30
+ const source = `fn noop(): void {}`;
31
+ const result = (0, compile_1.compile)(source, { namespace: 'demo' });
32
+ const meta = getFile(result.files, 'pack.mcmeta');
33
+ expect(meta).toBeDefined();
34
+ const parsed = JSON.parse(meta);
35
+ expect(parsed.pack.pack_format).toBe(26);
36
+ });
37
+ test('load.mcfunction creates scoreboard objective', () => {
38
+ const source = `fn noop(): void {}`;
39
+ const result = (0, compile_1.compile)(source, { namespace: 'mypack' });
40
+ const load = getFile(result.files, 'load.mcfunction');
41
+ expect(load).toBeDefined();
42
+ expect(load).toContain('scoreboard objectives add __mypack dummy');
43
+ });
44
+ test('@tick function appears in tick.json', () => {
45
+ const source = `
46
+ @tick fn game_tick(): void {
47
+ let x: int = 1;
48
+ }
49
+ `;
50
+ const result = (0, compile_1.compile)(source, { namespace: 'ticktest' });
51
+ const tickJson = getFile(result.files, 'tick.json');
52
+ expect(tickJson).toBeDefined();
53
+ const parsed = JSON.parse(tickJson);
54
+ expect(parsed.values).toContain('ticktest:game_tick');
55
+ });
56
+ test('@load function appears in load.json', () => {
57
+ const source = `
58
+ @load fn setup(): void {
59
+ let x: int = 42;
60
+ }
61
+ `;
62
+ const result = (0, compile_1.compile)(source, { namespace: 'loadtest' });
63
+ const loadJson = getFile(result.files, 'load.json');
64
+ expect(loadJson).toBeDefined();
65
+ const parsed = JSON.parse(loadJson);
66
+ expect(parsed.values).toContain('loadtest:setup');
67
+ // load.json should also reference the objective-init load function
68
+ expect(parsed.values).toContain('loadtest:load');
69
+ });
70
+ test('if/else produces conditional call pattern', () => {
71
+ const source = `
72
+ fn check(x: int): int {
73
+ if (x > 0) {
74
+ return 1;
75
+ } else {
76
+ return 0;
77
+ }
78
+ }
79
+ `;
80
+ const result = (0, compile_1.compile)(source, { namespace: 'cond' });
81
+ // The main function should contain call_if_matches / call_unless_matches
82
+ const checkFn = getFile(result.files, 'check.mcfunction');
83
+ expect(checkFn).toBeDefined();
84
+ expect(checkFn).toContain('execute if score');
85
+ expect(checkFn).toContain('matches');
86
+ expect(checkFn).toContain('run function');
87
+ });
88
+ test('while loop produces loop structure with recursive call', () => {
89
+ const source = `
90
+ fn count(): void {
91
+ let i: int = 0;
92
+ while (i < 10) {
93
+ i = i + 1;
94
+ }
95
+ }
96
+ `;
97
+ const result = (0, compile_1.compile)(source, { namespace: 'loop' });
98
+ // There should be a loop body function that calls itself (or a header)
99
+ const fnFiles = result.files.filter(f => f.path.endsWith('.mcfunction'));
100
+ expect(fnFiles.length).toBeGreaterThan(1); // main + at least one extracted block
101
+ // At least one file should have a conditional call pattern for the loop
102
+ const allContent = fnFiles.map(f => f.content).join('\n');
103
+ expect(allContent).toContain('execute if score');
104
+ expect(allContent).toContain('run function');
105
+ });
106
+ test('function names are lowercased in output paths', () => {
107
+ const source = `fn MyFunc(): void {}`;
108
+ const result = (0, compile_1.compile)(source, { namespace: 'ns' });
109
+ const fn = result.files.find(f => f.path.includes('myfunc.mcfunction'));
110
+ expect(fn).toBeDefined();
111
+ });
112
+ test('constant assignment produces score_set', () => {
113
+ const source = `
114
+ fn init(): int {
115
+ let x: int = 42;
116
+ return x;
117
+ }
118
+ `;
119
+ const result = (0, compile_1.compile)(source, { namespace: 'cst' });
120
+ const fn = getFile(result.files, 'init.mcfunction');
121
+ expect(fn).toBeDefined();
122
+ expect(fn).toContain('scoreboard players set');
123
+ expect(fn).toContain('42');
124
+ });
125
+ test('load.json always includes namespace:load', () => {
126
+ const source = `fn noop(): void {}`;
127
+ const result = (0, compile_1.compile)(source, { namespace: 'abc' });
128
+ const loadJson = getFile(result.files, 'load.json');
129
+ expect(loadJson).toBeDefined();
130
+ const parsed = JSON.parse(loadJson);
131
+ expect(parsed.values).toContain('abc:load');
132
+ });
133
+ test('no tick.json when no @tick functions', () => {
134
+ const source = `fn noop(): void {}`;
135
+ const result = (0, compile_1.compile)(source, { namespace: 'notick' });
136
+ const tickJson = getFile(result.files, 'tick.json');
137
+ expect(tickJson).toBeUndefined();
138
+ });
139
+ });
140
+ //# sourceMappingURL=basic.test.js.map
@@ -0,0 +1,9 @@
1
+ /**
2
+ * End-to-end tests for MC 1.20.2+ macro function support in the v2 pipeline.
3
+ *
4
+ * When a function uses runtime parameters in positions that require literal
5
+ * values in MC commands (coordinates, entity types, etc.), the compiler should
6
+ * automatically compile it as a macro function using $-prefixed syntax and
7
+ * call it via `function ns:fn with storage rs:macro_args`.
8
+ */
9
+ export {};
@@ -0,0 +1,182 @@
1
+ "use strict";
2
+ /**
3
+ * End-to-end tests for MC 1.20.2+ macro function support in the v2 pipeline.
4
+ *
5
+ * When a function uses runtime parameters in positions that require literal
6
+ * values in MC commands (coordinates, entity types, etc.), the compiler should
7
+ * automatically compile it as a macro function using $-prefixed syntax and
8
+ * call it via `function ns:fn with storage rs:macro_args`.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ const compile_1 = require("../../emit/compile");
12
+ function getFile(files, pathSubstr) {
13
+ const f = files.find(f => f.path.includes(pathSubstr));
14
+ return f?.content;
15
+ }
16
+ // ---------------------------------------------------------------------------
17
+ // Macro function detection
18
+ // ---------------------------------------------------------------------------
19
+ describe('e2e: macro function detection', () => {
20
+ test('function with int params in summon coords emits $-prefixed command', () => {
21
+ const source = `
22
+ fn spawn_zombie(x: int, y: int, z: int) {
23
+ summon("minecraft:zombie", x, y, z);
24
+ }
25
+ `;
26
+ const result = (0, compile_1.compile)(source, { namespace: 'test' });
27
+ const fn = getFile(result.files, 'spawn_zombie.mcfunction');
28
+ expect(fn).toBeDefined();
29
+ // The function body should have a $summon macro line
30
+ expect(fn).toContain('$summon minecraft:zombie $(x) $(y) $(z)');
31
+ });
32
+ test('function with all constant args does NOT produce macro line', () => {
33
+ const source = `
34
+ fn spawn_fixed() {
35
+ summon("minecraft:zombie", 100, 64, 200);
36
+ }
37
+ `;
38
+ const result = (0, compile_1.compile)(source, { namespace: 'test' });
39
+ const fn = getFile(result.files, 'spawn_fixed.mcfunction');
40
+ expect(fn).toBeDefined();
41
+ expect(fn).toContain('summon minecraft:zombie 100 64 200');
42
+ // No $ prefix
43
+ expect(fn).not.toMatch(/^\$summon/m);
44
+ });
45
+ test('function with int params in particle coords emits $-prefixed command', () => {
46
+ const source = `
47
+ fn show_particle(x: int, y: int, z: int) {
48
+ particle("minecraft:flame", x, y, z);
49
+ }
50
+ `;
51
+ const result = (0, compile_1.compile)(source, { namespace: 'test' });
52
+ const fn = getFile(result.files, 'show_particle.mcfunction');
53
+ expect(fn).toBeDefined();
54
+ expect(fn).toContain('$particle minecraft:flame $(x) $(y) $(z)');
55
+ });
56
+ test('function with int params in setblock coords emits $-prefixed command', () => {
57
+ const source = `
58
+ fn place_block(x: int, y: int, z: int) {
59
+ setblock(x, y, z, "minecraft:stone");
60
+ }
61
+ `;
62
+ const result = (0, compile_1.compile)(source, { namespace: 'test' });
63
+ const fn = getFile(result.files, 'place_block.mcfunction');
64
+ expect(fn).toBeDefined();
65
+ expect(fn).toContain('$setblock $(x) $(y) $(z) minecraft:stone');
66
+ });
67
+ test('mixed literal and variable args: only variable args get $()', () => {
68
+ const source = `
69
+ fn teleport_y(y: int) {
70
+ summon("minecraft:zombie", 100, y, 200);
71
+ }
72
+ `;
73
+ const result = (0, compile_1.compile)(source, { namespace: 'test' });
74
+ const fn = getFile(result.files, 'teleport_y.mcfunction');
75
+ expect(fn).toBeDefined();
76
+ expect(fn).toContain('$summon minecraft:zombie 100 $(y) 200');
77
+ });
78
+ });
79
+ // ---------------------------------------------------------------------------
80
+ // Macro call site generation
81
+ // ---------------------------------------------------------------------------
82
+ describe('e2e: macro call site generation', () => {
83
+ test('call site emits store_score_to_nbt + function with storage', () => {
84
+ const source = `
85
+ fn spawn_zombie(x: int, y: int, z: int) {
86
+ summon("minecraft:zombie", x, y, z);
87
+ }
88
+
89
+ fn caller(px: int, pz: int) {
90
+ spawn_zombie(px, 64, pz);
91
+ }
92
+ `;
93
+ const result = (0, compile_1.compile)(source, { namespace: 'test' });
94
+ const callerFn = getFile(result.files, 'caller.mcfunction');
95
+ expect(callerFn).toBeDefined();
96
+ // Should have 'function test:spawn_zombie with storage rs:macro_args'
97
+ expect(callerFn).toContain('with storage rs:macro_args');
98
+ expect(callerFn).toContain('spawn_zombie');
99
+ });
100
+ test('call site stores args to rs:macro_args NBT', () => {
101
+ const source = `
102
+ fn spawn_zombie(x: int, y: int, z: int) {
103
+ summon("minecraft:zombie", x, y, z);
104
+ }
105
+
106
+ fn caller(my_x: int) {
107
+ spawn_zombie(my_x, 64, 0);
108
+ }
109
+ `;
110
+ const result = (0, compile_1.compile)(source, { namespace: 'test' });
111
+ const callerFn = getFile(result.files, 'caller.mcfunction');
112
+ expect(callerFn).toBeDefined();
113
+ // Should have NBT storage setup for macro args
114
+ expect(callerFn).toContain('rs:macro_args');
115
+ expect(callerFn).toContain('with storage');
116
+ });
117
+ });
118
+ // ---------------------------------------------------------------------------
119
+ // Float macro params (local coords)
120
+ // ---------------------------------------------------------------------------
121
+ describe('e2e: float macro params with local coords', () => {
122
+ test('float params in ^coord positions produce macro function', () => {
123
+ const source = `
124
+ fn draw_pt(px: float, py: float) {
125
+ particle("minecraft:end_rod", ^px, ^py, ^5, 0.02, 0.02, 0.02, 0.0, 10);
126
+ }
127
+ `;
128
+ const result = (0, compile_1.compile)(source, { namespace: 'test' });
129
+ const fn = getFile(result.files, 'draw_pt.mcfunction');
130
+ expect(fn).toBeDefined();
131
+ // Should have $particle with ^$(px) and ^$(py)
132
+ expect(fn).toContain('$particle minecraft:end_rod ^$(px) ^$(py) ^5');
133
+ });
134
+ test('float macro call site uses double 0.01 scale for NBT storage', () => {
135
+ const source = `
136
+ fn draw_pt(px: float, py: float) {
137
+ particle("minecraft:end_rod", ^px, ^py, ^5, 0.02, 0.02, 0.02, 0.0, 10);
138
+ }
139
+
140
+ fn caller() {
141
+ draw_pt(100, 200);
142
+ }
143
+ `;
144
+ const result = (0, compile_1.compile)(source, { namespace: 'test' });
145
+ const callerFn = getFile(result.files, 'caller.mcfunction');
146
+ expect(callerFn).toBeDefined();
147
+ // Should store to NBT with double type and 0.01 scale
148
+ expect(callerFn).toContain('rs:macro_args');
149
+ expect(callerFn).toContain('double 0.01');
150
+ expect(callerFn).toContain('with storage rs:macro_args');
151
+ });
152
+ });
153
+ // ---------------------------------------------------------------------------
154
+ // Non-macro functions still work
155
+ // ---------------------------------------------------------------------------
156
+ describe('e2e: non-macro functions', () => {
157
+ test('say builtin emits normal (non-macro) command', () => {
158
+ const source = `
159
+ fn greet() {
160
+ say("hello world");
161
+ }
162
+ `;
163
+ const result = (0, compile_1.compile)(source, { namespace: 'test' });
164
+ const fn = getFile(result.files, 'greet.mcfunction');
165
+ expect(fn).toBeDefined();
166
+ expect(fn).toContain('say hello world');
167
+ // No $ prefix
168
+ expect(fn).not.toMatch(/^\$/m);
169
+ });
170
+ test('kill builtin emits normal command', () => {
171
+ const source = `
172
+ fn cleanup() {
173
+ kill(@e[tag=temp]);
174
+ }
175
+ `;
176
+ const result = (0, compile_1.compile)(source, { namespace: 'test' });
177
+ const fn = getFile(result.files, 'cleanup.mcfunction');
178
+ expect(fn).toBeDefined();
179
+ expect(fn).toContain('kill @e[tag=temp]');
180
+ });
181
+ });
182
+ //# sourceMappingURL=macros.test.js.map
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Migration tests — representative cases from the existing 920-test suite
3
+ * run through the NEW v2 compiler pipeline.
4
+ *
5
+ * Pattern:
6
+ * 1. Compile source with src2/emit/compile.ts
7
+ * 2. Load .mcfunction files into MCRuntime
8
+ * 3. Execute functions and assert scoreboard state
9
+ *
10
+ * NOTE: v2 uses objective `__<ns>` (not `rs`), load function is `ns:load`
11
+ * (not `ns:__load`), and return values go to `$ret` on the objective.
12
+ */
13
+ export {};