redscript-mc 1.2.30 → 2.1.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.
- package/.claudeignore +21 -0
- package/.github/workflows/ci.yml +1 -0
- package/README.md +12 -16
- package/README.zh.md +2 -2
- package/demo.gif +0 -0
- package/dist/cli.js +2 -554
- package/dist/compile.js +2 -266
- package/dist/index.js +2 -159
- package/dist/src/__tests__/budget.test.js +261 -0
- package/dist/src/__tests__/cli.test.js +104 -0
- package/dist/{__tests__ → src/__tests__}/dce.test.js +11 -47
- package/dist/{__tests__ → src/__tests__}/diagnostics.test.js +67 -40
- package/dist/src/__tests__/e2e/basic.test.d.ts +8 -0
- package/dist/src/__tests__/e2e/basic.test.js +140 -0
- package/dist/src/__tests__/e2e/coroutine.test.d.ts +7 -0
- package/dist/src/__tests__/e2e/coroutine.test.js +132 -0
- package/dist/src/__tests__/e2e/macros.test.d.ts +9 -0
- package/dist/src/__tests__/e2e/macros.test.js +182 -0
- package/dist/src/__tests__/e2e/migrate.test.d.ts +13 -0
- package/dist/src/__tests__/e2e/migrate.test.js +2739 -0
- package/dist/src/__tests__/e2e/stdlib-e2e.test.d.ts +10 -0
- package/dist/src/__tests__/e2e/stdlib-e2e.test.js +324 -0
- package/dist/src/__tests__/enum.test.d.ts +10 -0
- package/dist/src/__tests__/enum.test.js +389 -0
- package/dist/src/__tests__/generics.test.d.ts +14 -0
- package/dist/src/__tests__/generics.test.js +367 -0
- package/dist/src/__tests__/hir/desugar.test.js +234 -0
- package/dist/src/__tests__/incremental.test.d.ts +5 -0
- package/dist/src/__tests__/incremental.test.js +308 -0
- package/dist/src/__tests__/lir/lower.test.js +559 -0
- package/dist/src/__tests__/lir/types.test.js +185 -0
- package/dist/src/__tests__/lir/verify.test.js +221 -0
- package/dist/src/__tests__/lsp.test.d.ts +7 -0
- package/dist/src/__tests__/lsp.test.js +245 -0
- package/dist/{__tests__ → src/__tests__}/mc-integration.test.js +1 -3
- package/dist/src/__tests__/mc-version.test.d.ts +10 -0
- package/dist/src/__tests__/mc-version.test.js +154 -0
- package/dist/src/__tests__/mir/arithmetic.test.js +130 -0
- package/dist/src/__tests__/mir/control-flow.test.js +205 -0
- package/dist/src/__tests__/mir/verify.test.js +223 -0
- package/dist/src/__tests__/modules.test.d.ts +7 -0
- package/dist/src/__tests__/modules.test.js +333 -0
- package/dist/src/__tests__/optimizer/block_merge.test.js +78 -0
- package/dist/src/__tests__/optimizer/branch_simplify.test.js +58 -0
- package/dist/src/__tests__/optimizer/constant_fold.test.js +131 -0
- package/dist/src/__tests__/optimizer/copy_prop.test.js +91 -0
- package/dist/src/__tests__/optimizer/coroutine.test.d.ts +12 -0
- package/dist/src/__tests__/optimizer/coroutine.test.js +251 -0
- package/dist/src/__tests__/optimizer/dce.test.d.ts +1 -0
- package/dist/src/__tests__/optimizer/dce.test.js +76 -0
- package/dist/src/__tests__/optimizer/interprocedural.test.d.ts +1 -0
- package/dist/src/__tests__/optimizer/interprocedural.test.js +145 -0
- package/dist/src/__tests__/optimizer/lir/const_imm.test.d.ts +1 -0
- package/dist/src/__tests__/optimizer/lir/const_imm.test.js +138 -0
- package/dist/src/__tests__/optimizer/lir/dead_slot.test.d.ts +1 -0
- package/dist/src/__tests__/optimizer/lir/dead_slot.test.js +141 -0
- package/dist/src/__tests__/optimizer/lir/peephole.test.d.ts +1 -0
- package/dist/src/__tests__/optimizer/lir/peephole.test.js +126 -0
- package/dist/src/__tests__/optimizer/lir/pipeline.test.d.ts +1 -0
- package/dist/src/__tests__/optimizer/lir/pipeline.test.js +84 -0
- package/dist/src/__tests__/optimizer/nbt-batch.test.d.ts +1 -0
- package/dist/src/__tests__/optimizer/nbt-batch.test.js +110 -0
- package/dist/src/__tests__/optimizer/pipeline.test.d.ts +1 -0
- package/dist/src/__tests__/optimizer/pipeline.test.js +102 -0
- package/dist/src/__tests__/optimizer/selector-cache.test.d.ts +1 -0
- package/dist/src/__tests__/optimizer/selector-cache.test.js +103 -0
- package/dist/src/__tests__/optimizer/unroll.test.d.ts +1 -0
- package/dist/src/__tests__/optimizer/unroll.test.js +206 -0
- package/dist/src/__tests__/option.test.d.ts +14 -0
- package/dist/src/__tests__/option.test.js +275 -0
- package/dist/src/__tests__/parser.test.d.ts +1 -0
- package/dist/src/__tests__/repl.test.d.ts +1 -0
- package/dist/src/__tests__/schedule.test.d.ts +7 -0
- package/dist/src/__tests__/schedule.test.js +98 -0
- package/dist/src/__tests__/sourcemap.test.d.ts +7 -0
- package/dist/src/__tests__/sourcemap.test.js +227 -0
- package/dist/src/__tests__/tuple.test.d.ts +11 -0
- package/dist/src/__tests__/tuple.test.js +202 -0
- package/dist/src/__tests__/typechecker-strict.test.d.ts +10 -0
- package/dist/src/__tests__/typechecker-strict.test.js +197 -0
- package/dist/src/__tests__/typechecker.test.d.ts +1 -0
- package/dist/{ast → src/ast}/types.d.ts +58 -3
- package/dist/src/cache/deps.d.ts +41 -0
- package/dist/src/cache/deps.js +158 -0
- package/dist/src/cache/incremental.d.ts +35 -0
- package/dist/src/cache/incremental.js +165 -0
- package/dist/src/cache/index.d.ts +37 -0
- package/dist/src/cache/index.js +152 -0
- package/dist/{cli.d.ts → src/cli.d.ts} +1 -1
- package/dist/src/cli.js +474 -0
- package/dist/src/compile.d.ts +37 -0
- package/dist/src/compile.js +165 -0
- package/dist/{diagnostics → src/diagnostics}/index.d.ts +1 -1
- package/dist/{diagnostics → src/diagnostics}/index.js +8 -11
- package/dist/src/emit/compile.d.ts +29 -0
- package/dist/src/emit/compile.js +143 -0
- package/dist/src/emit/index.d.ts +26 -0
- package/dist/src/emit/index.js +223 -0
- package/dist/src/emit/modules.d.ts +29 -0
- package/dist/src/emit/modules.js +492 -0
- package/dist/src/emit/sourcemap.d.ts +53 -0
- package/dist/src/emit/sourcemap.js +73 -0
- package/dist/src/hir/lower.d.ts +15 -0
- package/dist/src/hir/lower.js +399 -0
- package/dist/src/hir/monomorphize.d.ts +22 -0
- package/dist/src/hir/monomorphize.js +379 -0
- package/dist/src/hir/types.d.ts +406 -0
- package/dist/src/hir/types.js +16 -0
- package/dist/src/index.d.ts +39 -0
- package/dist/src/index.js +67 -0
- package/dist/{lexer → src/lexer}/index.d.ts +1 -1
- package/dist/{lexer → src/lexer}/index.js +1 -0
- package/dist/src/lir/budget.d.ts +37 -0
- package/dist/src/lir/budget.js +280 -0
- package/dist/src/lir/lower.d.ts +15 -0
- package/dist/src/lir/lower.js +472 -0
- package/dist/src/lir/types.d.ts +139 -0
- package/dist/src/lir/types.js +11 -0
- package/dist/src/lir/verify.d.ts +14 -0
- package/dist/src/lir/verify.js +113 -0
- package/dist/src/lsp/main.d.ts +8 -0
- package/dist/src/lsp/main.js +11 -0
- package/dist/src/lsp/server.d.ts +11 -0
- package/dist/src/lsp/server.js +352 -0
- package/dist/{mc-test → src/mc-test}/runner.js +4 -3
- package/dist/src/mir/lower.d.ts +9 -0
- package/dist/src/mir/lower.js +1264 -0
- package/dist/src/mir/macro.d.ts +22 -0
- package/dist/src/mir/macro.js +168 -0
- package/dist/src/mir/types.d.ts +191 -0
- package/dist/src/mir/types.js +11 -0
- package/dist/src/mir/verify.d.ts +16 -0
- package/dist/src/mir/verify.js +216 -0
- package/dist/src/optimizer/block_merge.d.ts +12 -0
- package/dist/src/optimizer/block_merge.js +84 -0
- package/dist/src/optimizer/branch_simplify.d.ts +9 -0
- package/dist/src/optimizer/branch_simplify.js +28 -0
- package/dist/src/optimizer/constant_fold.d.ts +10 -0
- package/dist/src/optimizer/constant_fold.js +85 -0
- package/dist/src/optimizer/copy_prop.d.ts +9 -0
- package/dist/src/optimizer/copy_prop.js +113 -0
- package/dist/src/optimizer/coroutine.d.ts +34 -0
- package/dist/src/optimizer/coroutine.js +789 -0
- package/dist/src/optimizer/dce.d.ts +8 -0
- package/dist/src/optimizer/dce.js +156 -0
- package/dist/src/optimizer/interprocedural.d.ts +14 -0
- package/dist/src/optimizer/interprocedural.js +186 -0
- package/dist/src/optimizer/lir/const_imm.d.ts +12 -0
- package/dist/src/optimizer/lir/const_imm.js +139 -0
- package/dist/src/optimizer/lir/dead_slot.d.ts +14 -0
- package/dist/src/optimizer/lir/dead_slot.js +130 -0
- package/dist/src/optimizer/lir/peephole.d.ts +21 -0
- package/dist/src/optimizer/lir/peephole.js +52 -0
- package/dist/src/optimizer/lir/pipeline.d.ts +10 -0
- package/dist/src/optimizer/lir/pipeline.js +34 -0
- package/dist/src/optimizer/nbt-batch.d.ts +11 -0
- package/dist/src/optimizer/nbt-batch.js +51 -0
- package/dist/src/optimizer/pipeline.d.ts +14 -0
- package/dist/src/optimizer/pipeline.js +58 -0
- package/dist/src/optimizer/selector-cache.d.ts +22 -0
- package/dist/src/optimizer/selector-cache.js +100 -0
- package/dist/src/optimizer/unroll.d.ts +32 -0
- package/dist/src/optimizer/unroll.js +348 -0
- package/dist/{parser → src/parser}/index.d.ts +8 -0
- package/dist/{parser → src/parser}/index.js +204 -14
- package/dist/{repl.d.ts → src/repl.d.ts} +1 -1
- package/dist/{runtime → src/runtime}/index.js +1 -1
- package/dist/{typechecker → src/typechecker}/index.d.ts +4 -0
- package/dist/{typechecker → src/typechecker}/index.js +198 -13
- package/dist/src/types/mc-version.d.ts +24 -0
- package/dist/src/types/mc-version.js +49 -0
- package/docs/ROADMAP.md +395 -0
- package/docs/compiler-pipeline-redesign.md +2260 -0
- package/docs/optimization-ideas.md +1076 -0
- package/editors/vscode/out/extension.js +25176 -8000
- package/editors/vscode/package-lock.json +90 -6
- package/editors/vscode/package.json +3 -2
- package/editors/vscode/src/extension.ts +97 -67
- package/examples/showcase.mcrs +3 -3
- package/package.json +13 -6
- package/scripts/postbuild.js +15 -0
- package/src/__tests__/budget.test.ts +297 -0
- package/src/__tests__/cli.test.ts +8 -220
- package/src/__tests__/dce.test.ts +11 -56
- package/src/__tests__/diagnostics.test.ts +61 -41
- package/src/__tests__/e2e/basic.test.ts +154 -0
- package/src/__tests__/e2e/coroutine.test.ts +142 -0
- package/src/__tests__/e2e/macros.test.ts +199 -0
- package/src/__tests__/e2e/migrate.test.ts +3008 -0
- package/src/__tests__/e2e/stdlib-e2e.test.ts +348 -0
- package/src/__tests__/enum.test.ts +425 -0
- package/src/__tests__/generics.test.ts +390 -0
- package/src/__tests__/hir/desugar.test.ts +263 -0
- package/src/__tests__/incremental.test.ts +337 -0
- package/src/__tests__/lir/lower.test.ts +619 -0
- package/src/__tests__/lir/types.test.ts +207 -0
- package/src/__tests__/lir/verify.test.ts +249 -0
- package/src/__tests__/lsp.test.ts +270 -0
- package/src/__tests__/mc-integration.test.ts +1 -2
- package/src/__tests__/mc-version.test.ts +178 -0
- package/src/__tests__/mir/arithmetic.test.ts +156 -0
- package/src/__tests__/mir/control-flow.test.ts +242 -0
- package/src/__tests__/mir/verify.test.ts +254 -0
- package/src/__tests__/modules.test.ts +365 -0
- package/src/__tests__/optimizer/block_merge.test.ts +84 -0
- package/src/__tests__/optimizer/branch_simplify.test.ts +64 -0
- package/src/__tests__/optimizer/constant_fold.test.ts +145 -0
- package/src/__tests__/optimizer/copy_prop.test.ts +99 -0
- package/src/__tests__/optimizer/coroutine.test.ts +312 -0
- package/src/__tests__/optimizer/dce.test.ts +83 -0
- package/src/__tests__/optimizer/interprocedural.test.ts +174 -0
- package/src/__tests__/optimizer/lir/const_imm.test.ts +151 -0
- package/src/__tests__/optimizer/lir/dead_slot.test.ts +156 -0
- package/src/__tests__/optimizer/lir/peephole.test.ts +136 -0
- package/src/__tests__/optimizer/lir/pipeline.test.ts +113 -0
- package/src/__tests__/optimizer/nbt-batch.test.ts +119 -0
- package/src/__tests__/optimizer/pipeline.test.ts +116 -0
- package/src/__tests__/optimizer/selector-cache.test.ts +112 -0
- package/src/__tests__/optimizer/unroll.test.ts +231 -0
- package/src/__tests__/option.test.ts +299 -0
- package/src/__tests__/schedule.test.ts +105 -0
- package/src/__tests__/sourcemap.test.ts +254 -0
- package/src/__tests__/tuple.test.ts +220 -0
- package/src/__tests__/typechecker-strict.test.ts +216 -0
- package/src/ast/types.ts +39 -3
- package/src/cache/deps.ts +132 -0
- package/src/cache/incremental.ts +173 -0
- package/src/cache/index.ts +135 -0
- package/src/cli.ts +111 -195
- package/src/compile.ts +6 -162
- package/src/diagnostics/index.ts +8 -11
- package/src/emit/compile.ts +177 -0
- package/src/emit/index.ts +286 -0
- package/src/emit/modules.ts +581 -0
- package/src/emit/sourcemap.ts +101 -0
- package/src/hir/lower.ts +455 -0
- package/src/hir/monomorphize.ts +416 -0
- package/src/hir/types.ts +228 -0
- package/src/index.ts +37 -182
- package/src/lexer/index.ts +2 -1
- package/src/lir/budget.ts +321 -0
- package/src/lir/lower.ts +587 -0
- package/src/lir/types.ts +113 -0
- package/src/lir/verify.ts +129 -0
- package/src/lsp/main.ts +9 -0
- package/src/lsp/server.ts +414 -0
- package/src/mc-test/runner.ts +4 -3
- package/src/mir/lower.ts +1403 -0
- package/src/mir/macro.ts +167 -0
- package/src/mir/types.ts +117 -0
- package/src/mir/verify.ts +218 -0
- package/src/optimizer/block_merge.ts +93 -0
- package/src/optimizer/branch_simplify.ts +27 -0
- package/src/optimizer/constant_fold.ts +88 -0
- package/src/optimizer/copy_prop.ts +106 -0
- package/src/optimizer/coroutine.ts +996 -0
- package/src/optimizer/dce.ts +108 -653
- package/src/optimizer/interprocedural.ts +177 -0
- package/src/optimizer/lir/const_imm.ts +143 -0
- package/src/optimizer/lir/dead_slot.ts +123 -0
- package/src/optimizer/lir/peephole.ts +57 -0
- package/src/optimizer/lir/pipeline.ts +37 -0
- package/src/optimizer/nbt-batch.ts +50 -0
- package/src/optimizer/pipeline.ts +59 -0
- package/src/optimizer/selector-cache.ts +103 -0
- package/src/optimizer/unroll.ts +386 -0
- package/src/parser/index.ts +213 -16
- package/src/repl.ts +1 -1
- package/src/runtime/index.ts +1 -1
- package/src/stdlib/math.mcrs +4 -4
- package/src/templates/quest.mcrs +4 -4
- package/src/typechecker/index.ts +215 -15
- package/src/types/mc-version.ts +46 -0
- package/tsconfig.json +1 -1
- package/dist/__tests__/cli.test.js +0 -278
- package/dist/__tests__/codegen.test.js +0 -152
- package/dist/__tests__/e2e.test.d.ts +0 -6
- package/dist/__tests__/e2e.test.js +0 -1847
- package/dist/__tests__/entity-types.test.js +0 -203
- package/dist/__tests__/lowering.test.js +0 -1015
- package/dist/__tests__/macro.test.d.ts +0 -8
- package/dist/__tests__/macro.test.js +0 -305
- package/dist/__tests__/nbt.test.js +0 -82
- package/dist/__tests__/optimizer-advanced.test.js +0 -124
- package/dist/__tests__/optimizer.test.js +0 -149
- package/dist/__tests__/runtime.test.js +0 -289
- package/dist/__tests__/stdlib-advanced.test.d.ts +0 -4
- package/dist/__tests__/stdlib-advanced.test.js +0 -378
- package/dist/__tests__/stdlib-bigint.test.d.ts +0 -7
- package/dist/__tests__/stdlib-bigint.test.js +0 -428
- package/dist/__tests__/stdlib-math.test.d.ts +0 -7
- package/dist/__tests__/stdlib-math.test.js +0 -352
- package/dist/__tests__/stdlib-vec.test.d.ts +0 -4
- package/dist/__tests__/stdlib-vec.test.js +0 -264
- package/dist/__tests__/structure-optimizer.test.js +0 -33
- package/dist/__tests__/var-allocator.test.js +0 -69
- package/dist/codegen/cmdblock/index.d.ts +0 -26
- package/dist/codegen/cmdblock/index.js +0 -45
- package/dist/codegen/mcfunction/index.d.ts +0 -40
- package/dist/codegen/mcfunction/index.js +0 -606
- package/dist/codegen/structure/index.d.ts +0 -24
- package/dist/codegen/structure/index.js +0 -279
- package/dist/codegen/var-allocator.d.ts +0 -45
- package/dist/codegen/var-allocator.js +0 -104
- package/dist/compile.d.ts +0 -68
- package/dist/data/arena/function/__load.mcfunction +0 -6
- package/dist/data/arena/function/__tick.mcfunction +0 -2
- package/dist/data/arena/function/announce_leaders/else_1.mcfunction +0 -3
- package/dist/data/arena/function/announce_leaders/foreach_0/merge_2.mcfunction +0 -1
- package/dist/data/arena/function/announce_leaders/foreach_0/then_0.mcfunction +0 -3
- package/dist/data/arena/function/announce_leaders/foreach_0.mcfunction +0 -7
- package/dist/data/arena/function/announce_leaders/foreach_1/merge_2.mcfunction +0 -1
- package/dist/data/arena/function/announce_leaders/foreach_1/then_0.mcfunction +0 -4
- package/dist/data/arena/function/announce_leaders/foreach_1.mcfunction +0 -6
- package/dist/data/arena/function/announce_leaders/merge_2.mcfunction +0 -1
- package/dist/data/arena/function/announce_leaders/then_0.mcfunction +0 -4
- package/dist/data/arena/function/announce_leaders.mcfunction +0 -6
- package/dist/data/arena/function/arena_tick/merge_2.mcfunction +0 -1
- package/dist/data/arena/function/arena_tick/then_0.mcfunction +0 -4
- package/dist/data/arena/function/arena_tick.mcfunction +0 -11
- package/dist/data/counter/function/__load.mcfunction +0 -5
- package/dist/data/counter/function/__tick.mcfunction +0 -2
- package/dist/data/counter/function/counter_tick/merge_2.mcfunction +0 -1
- package/dist/data/counter/function/counter_tick/then_0.mcfunction +0 -3
- package/dist/data/counter/function/counter_tick.mcfunction +0 -11
- package/dist/data/gcd2/function/__load.mcfunction +0 -3
- package/dist/data/gcd2/function/abs/merge_2.mcfunction +0 -3
- package/dist/data/gcd2/function/abs/then_0.mcfunction +0 -5
- package/dist/data/gcd2/function/abs.mcfunction +0 -7
- package/dist/data/gcd2/function/gcd/loop_body_1.mcfunction +0 -7
- package/dist/data/gcd2/function/gcd/loop_check_0.mcfunction +0 -5
- package/dist/data/gcd2/function/gcd/loop_exit_2.mcfunction +0 -3
- package/dist/data/gcd2/function/gcd.mcfunction +0 -14
- package/dist/data/gcd3/function/__load.mcfunction +0 -3
- package/dist/data/gcd3/function/abs/merge_2.mcfunction +0 -3
- package/dist/data/gcd3/function/abs/then_0.mcfunction +0 -5
- package/dist/data/gcd3/function/abs.mcfunction +0 -7
- package/dist/data/gcd3/function/gcd/loop_body_1.mcfunction +0 -7
- package/dist/data/gcd3/function/gcd/loop_check_0.mcfunction +0 -5
- package/dist/data/gcd3/function/gcd/loop_exit_2.mcfunction +0 -3
- package/dist/data/gcd3/function/gcd.mcfunction +0 -14
- package/dist/data/gcd3/function/test.mcfunction +0 -7
- package/dist/data/gcd3nm/function/__load.mcfunction +0 -3
- package/dist/data/gcd3nm/function/abs/merge_2.mcfunction +0 -3
- package/dist/data/gcd3nm/function/abs/then_0.mcfunction +0 -5
- package/dist/data/gcd3nm/function/abs.mcfunction +0 -7
- package/dist/data/gcd3nm/function/gcd/loop_body_1.mcfunction +0 -7
- package/dist/data/gcd3nm/function/gcd/loop_check_0.mcfunction +0 -5
- package/dist/data/gcd3nm/function/gcd/loop_exit_2.mcfunction +0 -3
- package/dist/data/gcd3nm/function/gcd.mcfunction +0 -14
- package/dist/data/gcd3nm/function/test.mcfunction +0 -7
- package/dist/data/gcd_test/function/__load.mcfunction +0 -3
- package/dist/data/gcd_test/function/abs/merge_2.mcfunction +0 -3
- package/dist/data/gcd_test/function/abs/then_0.mcfunction +0 -5
- package/dist/data/gcd_test/function/abs.mcfunction +0 -7
- package/dist/data/gcd_test/function/gcd/loop_body_1.mcfunction +0 -7
- package/dist/data/gcd_test/function/gcd/loop_check_0.mcfunction +0 -5
- package/dist/data/gcd_test/function/gcd/loop_exit_2.mcfunction +0 -3
- package/dist/data/gcd_test/function/gcd.mcfunction +0 -14
- package/dist/data/isqrttest/function/__load.mcfunction +0 -6
- package/dist/data/isqrttest/function/isqrt/loop_body_4.mcfunction +0 -12
- package/dist/data/isqrttest/function/isqrt/loop_check_3.mcfunction +0 -5
- package/dist/data/isqrttest/function/isqrt/loop_exit_5.mcfunction +0 -3
- package/dist/data/isqrttest/function/isqrt/merge_2.mcfunction +0 -4
- package/dist/data/isqrttest/function/isqrt/merge_8.mcfunction +0 -6
- package/dist/data/isqrttest/function/isqrt/then_0.mcfunction +0 -3
- package/dist/data/isqrttest/function/isqrt/then_6.mcfunction +0 -3
- package/dist/data/isqrttest/function/isqrt.mcfunction +0 -7
- package/dist/data/isqrttest/function/test.mcfunction +0 -6
- package/dist/data/mathtest/function/__load.mcfunction +0 -3
- package/dist/data/mathtest/function/abs/merge_2.mcfunction +0 -3
- package/dist/data/mathtest/function/abs/then_0.mcfunction +0 -5
- package/dist/data/mathtest/function/abs.mcfunction +0 -6
- package/dist/data/mathtest/function/test.mcfunction +0 -5
- package/dist/data/minecraft/tags/function/load.json +0 -5
- package/dist/data/minecraft/tags/function/tick.json +0 -5
- package/dist/data/mypack/function/__load.mcfunction +0 -13
- package/dist/data/mypack/function/_atan_init.mcfunction +0 -2
- package/dist/data/mypack/function/abs/merge_2.mcfunction +0 -3
- package/dist/data/mypack/function/abs/then_0.mcfunction +0 -5
- package/dist/data/mypack/function/abs.mcfunction +0 -6
- package/dist/data/mypack/function/atan2_fixed/__sgi_1.mcfunction +0 -2
- package/dist/data/mypack/function/atan2_fixed/else_34.mcfunction +0 -3
- package/dist/data/mypack/function/atan2_fixed/loop_body_31.mcfunction +0 -19
- package/dist/data/mypack/function/atan2_fixed/loop_check_30.mcfunction +0 -5
- package/dist/data/mypack/function/atan2_fixed/loop_exit_32.mcfunction +0 -6
- package/dist/data/mypack/function/atan2_fixed/merge_11.mcfunction +0 -6
- package/dist/data/mypack/function/atan2_fixed/merge_14.mcfunction +0 -3
- package/dist/data/mypack/function/atan2_fixed/merge_17.mcfunction +0 -6
- package/dist/data/mypack/function/atan2_fixed/merge_2.mcfunction +0 -5
- package/dist/data/mypack/function/atan2_fixed/merge_20.mcfunction +0 -5
- package/dist/data/mypack/function/atan2_fixed/merge_23.mcfunction +0 -5
- package/dist/data/mypack/function/atan2_fixed/merge_26.mcfunction +0 -6
- package/dist/data/mypack/function/atan2_fixed/merge_29.mcfunction +0 -4
- package/dist/data/mypack/function/atan2_fixed/merge_38.mcfunction +0 -5
- package/dist/data/mypack/function/atan2_fixed/merge_41.mcfunction +0 -5
- package/dist/data/mypack/function/atan2_fixed/merge_44.mcfunction +0 -5
- package/dist/data/mypack/function/atan2_fixed/merge_47.mcfunction +0 -5
- package/dist/data/mypack/function/atan2_fixed/merge_5.mcfunction +0 -5
- package/dist/data/mypack/function/atan2_fixed/merge_8.mcfunction +0 -3
- package/dist/data/mypack/function/atan2_fixed/then_0.mcfunction +0 -5
- package/dist/data/mypack/function/atan2_fixed/then_12.mcfunction +0 -3
- package/dist/data/mypack/function/atan2_fixed/then_15.mcfunction +0 -5
- package/dist/data/mypack/function/atan2_fixed/then_18.mcfunction +0 -5
- package/dist/data/mypack/function/atan2_fixed/then_21.mcfunction +0 -3
- package/dist/data/mypack/function/atan2_fixed/then_24.mcfunction +0 -3
- package/dist/data/mypack/function/atan2_fixed/then_27.mcfunction +0 -6
- package/dist/data/mypack/function/atan2_fixed/then_3.mcfunction +0 -3
- package/dist/data/mypack/function/atan2_fixed/then_33.mcfunction +0 -5
- package/dist/data/mypack/function/atan2_fixed/then_36.mcfunction +0 -5
- package/dist/data/mypack/function/atan2_fixed/then_39.mcfunction +0 -5
- package/dist/data/mypack/function/atan2_fixed/then_42.mcfunction +0 -3
- package/dist/data/mypack/function/atan2_fixed/then_45.mcfunction +0 -5
- package/dist/data/mypack/function/atan2_fixed/then_6.mcfunction +0 -3
- package/dist/data/mypack/function/atan2_fixed/then_9.mcfunction +0 -5
- package/dist/data/mypack/function/atan2_fixed.mcfunction +0 -7
- package/dist/data/mypack/function/my_game.mcfunction +0 -10
- package/dist/data/quiz/function/__load.mcfunction +0 -16
- package/dist/data/quiz/function/__tick.mcfunction +0 -6
- package/dist/data/quiz/function/__trigger_quiz_a_dispatch.mcfunction +0 -4
- package/dist/data/quiz/function/__trigger_quiz_b_dispatch.mcfunction +0 -4
- package/dist/data/quiz/function/__trigger_quiz_c_dispatch.mcfunction +0 -4
- package/dist/data/quiz/function/__trigger_quiz_start_dispatch.mcfunction +0 -4
- package/dist/data/quiz/function/answer_a.mcfunction +0 -4
- package/dist/data/quiz/function/answer_b.mcfunction +0 -4
- package/dist/data/quiz/function/answer_c.mcfunction +0 -4
- package/dist/data/quiz/function/ask_question/else_1.mcfunction +0 -5
- package/dist/data/quiz/function/ask_question/else_4.mcfunction +0 -5
- package/dist/data/quiz/function/ask_question/else_7.mcfunction +0 -4
- package/dist/data/quiz/function/ask_question/merge_2.mcfunction +0 -1
- package/dist/data/quiz/function/ask_question/merge_5.mcfunction +0 -2
- package/dist/data/quiz/function/ask_question/merge_8.mcfunction +0 -2
- package/dist/data/quiz/function/ask_question/then_0.mcfunction +0 -4
- package/dist/data/quiz/function/ask_question/then_3.mcfunction +0 -4
- package/dist/data/quiz/function/ask_question/then_6.mcfunction +0 -4
- package/dist/data/quiz/function/ask_question.mcfunction +0 -7
- package/dist/data/quiz/function/finish_quiz.mcfunction +0 -6
- package/dist/data/quiz/function/handle_answer/else_1.mcfunction +0 -5
- package/dist/data/quiz/function/handle_answer/else_10.mcfunction +0 -3
- package/dist/data/quiz/function/handle_answer/else_16.mcfunction +0 -3
- package/dist/data/quiz/function/handle_answer/else_4.mcfunction +0 -3
- package/dist/data/quiz/function/handle_answer/else_7.mcfunction +0 -5
- package/dist/data/quiz/function/handle_answer/merge_11.mcfunction +0 -2
- package/dist/data/quiz/function/handle_answer/merge_14.mcfunction +0 -2
- package/dist/data/quiz/function/handle_answer/merge_17.mcfunction +0 -2
- package/dist/data/quiz/function/handle_answer/merge_2.mcfunction +0 -8
- package/dist/data/quiz/function/handle_answer/merge_5.mcfunction +0 -2
- package/dist/data/quiz/function/handle_answer/merge_8.mcfunction +0 -2
- package/dist/data/quiz/function/handle_answer/then_0.mcfunction +0 -5
- package/dist/data/quiz/function/handle_answer/then_12.mcfunction +0 -5
- package/dist/data/quiz/function/handle_answer/then_15.mcfunction +0 -6
- package/dist/data/quiz/function/handle_answer/then_3.mcfunction +0 -6
- package/dist/data/quiz/function/handle_answer/then_6.mcfunction +0 -5
- package/dist/data/quiz/function/handle_answer/then_9.mcfunction +0 -6
- package/dist/data/quiz/function/handle_answer.mcfunction +0 -11
- package/dist/data/quiz/function/start_quiz.mcfunction +0 -5
- package/dist/data/reqtest/function/__load.mcfunction +0 -4
- package/dist/data/reqtest/function/_table_init.mcfunction +0 -2
- package/dist/data/reqtest/function/no_trig.mcfunction +0 -3
- package/dist/data/reqtest/function/use_table.mcfunction +0 -4
- package/dist/data/reqtest2/function/__load.mcfunction +0 -3
- package/dist/data/reqtest2/function/no_trig.mcfunction +0 -3
- package/dist/data/runtime/function/__load.mcfunction +0 -5
- package/dist/data/runtime/function/__tick.mcfunction +0 -2
- package/dist/data/runtime/function/counter_tick/then_0.mcfunction +0 -3
- package/dist/data/runtime/function/counter_tick.mcfunction +0 -13
- package/dist/data/shop/function/__load.mcfunction +0 -7
- package/dist/data/shop/function/__tick.mcfunction +0 -3
- package/dist/data/shop/function/__trigger_shop_buy_dispatch.mcfunction +0 -4
- package/dist/data/shop/function/complete_purchase/else_1.mcfunction +0 -5
- package/dist/data/shop/function/complete_purchase/else_4.mcfunction +0 -5
- package/dist/data/shop/function/complete_purchase/else_7.mcfunction +0 -3
- package/dist/data/shop/function/complete_purchase/merge_2.mcfunction +0 -2
- package/dist/data/shop/function/complete_purchase/merge_5.mcfunction +0 -2
- package/dist/data/shop/function/complete_purchase/merge_8.mcfunction +0 -2
- package/dist/data/shop/function/complete_purchase/then_0.mcfunction +0 -4
- package/dist/data/shop/function/complete_purchase/then_3.mcfunction +0 -4
- package/dist/data/shop/function/complete_purchase/then_6.mcfunction +0 -4
- package/dist/data/shop/function/complete_purchase.mcfunction +0 -7
- package/dist/data/shop/function/handle_shop_trigger.mcfunction +0 -3
- package/dist/data/swap_test/function/__load.mcfunction +0 -3
- package/dist/data/swap_test/function/gcd_old/loop_body_1.mcfunction +0 -7
- package/dist/data/swap_test/function/gcd_old/loop_check_0.mcfunction +0 -5
- package/dist/data/swap_test/function/gcd_old/loop_exit_2.mcfunction +0 -3
- package/dist/data/swap_test/function/gcd_old.mcfunction +0 -8
- package/dist/data/turret/function/__load.mcfunction +0 -5
- package/dist/data/turret/function/__tick.mcfunction +0 -4
- package/dist/data/turret/function/__trigger_deploy_turret_dispatch.mcfunction +0 -4
- package/dist/data/turret/function/deploy_turret.mcfunction +0 -8
- package/dist/data/turret/function/turret_tick/at_1.mcfunction +0 -2
- package/dist/data/turret/function/turret_tick/foreach_0.mcfunction +0 -2
- package/dist/data/turret/function/turret_tick/foreach_2.mcfunction +0 -2
- package/dist/data/turret/function/turret_tick/tick_body.mcfunction +0 -3
- package/dist/data/turret/function/turret_tick/tick_skip.mcfunction +0 -1
- package/dist/data/turret/function/turret_tick.mcfunction +0 -5
- package/dist/gcd2.map.json +0 -15
- package/dist/gcd3.map.json +0 -17
- package/dist/gcd_test.map.json +0 -15
- package/dist/index.d.ts +0 -62
- package/dist/ir/builder.d.ts +0 -33
- package/dist/ir/builder.js +0 -99
- package/dist/ir/types.d.ts +0 -132
- package/dist/ir/types.js +0 -15
- package/dist/isqrttest.map.json +0 -15
- package/dist/lowering/index.d.ts +0 -188
- package/dist/lowering/index.js +0 -3403
- package/dist/mathtest.map.json +0 -6
- package/dist/mypack.map.json +0 -27
- package/dist/optimizer/commands.d.ts +0 -38
- package/dist/optimizer/commands.js +0 -451
- package/dist/optimizer/dce.d.ts +0 -34
- package/dist/optimizer/dce.js +0 -639
- package/dist/optimizer/passes.d.ts +0 -34
- package/dist/optimizer/passes.js +0 -243
- package/dist/optimizer/structure.d.ts +0 -9
- package/dist/optimizer/structure.js +0 -356
- package/dist/pack.mcmeta +0 -6
- package/dist/reqtest.map.json +0 -4
- package/dist/reqtest2.map.json +0 -4
- package/dist/runtime.map.json +0 -7
- package/dist/swap_test.map.json +0 -14
- package/src/__tests__/codegen.test.ts +0 -161
- package/src/__tests__/e2e.test.ts +0 -2039
- package/src/__tests__/entity-types.test.ts +0 -236
- package/src/__tests__/lowering.test.ts +0 -1185
- package/src/__tests__/macro.test.ts +0 -343
- package/src/__tests__/nbt.test.ts +0 -58
- package/src/__tests__/optimizer-advanced.test.ts +0 -144
- package/src/__tests__/optimizer.test.ts +0 -162
- package/src/__tests__/runtime.test.ts +0 -305
- package/src/__tests__/stdlib-advanced.test.ts +0 -379
- package/src/__tests__/stdlib-bigint.test.ts +0 -427
- package/src/__tests__/stdlib-math.test.ts +0 -374
- package/src/__tests__/stdlib-vec.test.ts +0 -259
- package/src/__tests__/structure-optimizer.test.ts +0 -38
- package/src/__tests__/var-allocator.test.ts +0 -75
- package/src/codegen/cmdblock/index.ts +0 -63
- package/src/codegen/mcfunction/index.ts +0 -662
- package/src/codegen/structure/index.ts +0 -346
- package/src/codegen/var-allocator.ts +0 -104
- package/src/ir/builder.ts +0 -116
- package/src/ir/types.ts +0 -134
- package/src/lowering/index.ts +0 -3876
- package/src/optimizer/commands.ts +0 -534
- package/src/optimizer/passes.ts +0 -250
- package/src/optimizer/structure.ts +0 -450
- /package/dist/{__tests__/cli.test.d.ts → src/__tests__/budget.test.d.ts} +0 -0
- /package/dist/{__tests__/codegen.test.d.ts → src/__tests__/cli.test.d.ts} +0 -0
- /package/dist/{__tests__ → src/__tests__}/compile-all.test.d.ts +0 -0
- /package/dist/{__tests__ → src/__tests__}/compile-all.test.js +0 -0
- /package/dist/{__tests__ → src/__tests__}/dce.test.d.ts +0 -0
- /package/dist/{__tests__ → src/__tests__}/diagnostics.test.d.ts +0 -0
- /package/dist/{__tests__ → src/__tests__}/formatter.test.d.ts +0 -0
- /package/dist/{__tests__ → src/__tests__}/formatter.test.js +0 -0
- /package/dist/{__tests__/entity-types.test.d.ts → src/__tests__/hir/desugar.test.d.ts} +0 -0
- /package/dist/{__tests__ → src/__tests__}/lexer.test.d.ts +0 -0
- /package/dist/{__tests__ → src/__tests__}/lexer.test.js +0 -0
- /package/dist/{__tests__/lowering.test.d.ts → src/__tests__/lir/lower.test.d.ts} +0 -0
- /package/dist/{__tests__/mc-syntax.test.d.ts → src/__tests__/lir/types.test.d.ts} +0 -0
- /package/dist/{__tests__/nbt.test.d.ts → src/__tests__/lir/verify.test.d.ts} +0 -0
- /package/dist/{__tests__ → src/__tests__}/mc-integration.test.d.ts +0 -0
- /package/dist/{__tests__/optimizer-advanced.test.d.ts → src/__tests__/mc-syntax.test.d.ts} +0 -0
- /package/dist/{__tests__ → src/__tests__}/mc-syntax.test.js +0 -0
- /package/dist/{__tests__/optimizer.test.d.ts → src/__tests__/mir/arithmetic.test.d.ts} +0 -0
- /package/dist/{__tests__/parser.test.d.ts → src/__tests__/mir/control-flow.test.d.ts} +0 -0
- /package/dist/{__tests__/repl.test.d.ts → src/__tests__/mir/verify.test.d.ts} +0 -0
- /package/dist/{__tests__/runtime.test.d.ts → src/__tests__/optimizer/block_merge.test.d.ts} +0 -0
- /package/dist/{__tests__/structure-optimizer.test.d.ts → src/__tests__/optimizer/branch_simplify.test.d.ts} +0 -0
- /package/dist/{__tests__/typechecker.test.d.ts → src/__tests__/optimizer/constant_fold.test.d.ts} +0 -0
- /package/dist/{__tests__/var-allocator.test.d.ts → src/__tests__/optimizer/copy_prop.test.d.ts} +0 -0
- /package/dist/{__tests__ → src/__tests__}/parser.test.js +0 -0
- /package/dist/{__tests__ → src/__tests__}/repl.test.js +0 -0
- /package/dist/{__tests__ → src/__tests__}/typechecker.test.js +0 -0
- /package/dist/{ast → src/ast}/types.js +0 -0
- /package/dist/{builtins → src/builtins}/metadata.d.ts +0 -0
- /package/dist/{builtins → src/builtins}/metadata.js +0 -0
- /package/dist/{events → src/events}/types.d.ts +0 -0
- /package/dist/{events → src/events}/types.js +0 -0
- /package/dist/{formatter → src/formatter}/index.d.ts +0 -0
- /package/dist/{formatter → src/formatter}/index.js +0 -0
- /package/dist/{mc-test → src/mc-test}/client.d.ts +0 -0
- /package/dist/{mc-test → src/mc-test}/client.js +0 -0
- /package/dist/{mc-test → src/mc-test}/runner.d.ts +0 -0
- /package/dist/{mc-test → src/mc-test}/setup.d.ts +0 -0
- /package/dist/{mc-test → src/mc-test}/setup.js +0 -0
- /package/dist/{mc-validator → src/mc-validator}/index.d.ts +0 -0
- /package/dist/{mc-validator → src/mc-validator}/index.js +0 -0
- /package/dist/{nbt → src/nbt}/index.d.ts +0 -0
- /package/dist/{nbt → src/nbt}/index.js +0 -0
- /package/dist/{repl.js → src/repl.js} +0 -0
- /package/dist/{runtime → src/runtime}/index.d.ts +0 -0
- /package/dist/{types → src/types}/entity-hierarchy.d.ts +0 -0
- /package/dist/{types → src/types}/entity-hierarchy.js +0 -0
package/src/typechecker/index.ts
CHANGED
|
@@ -132,6 +132,7 @@ export class TypeChecker {
|
|
|
132
132
|
private structs: Map<string, Map<string, TypeNode>> = new Map()
|
|
133
133
|
private enums: Map<string, Map<string, number>> = new Map()
|
|
134
134
|
private consts: Map<string, TypeNode> = new Map()
|
|
135
|
+
private globals: Map<string, TypeNode> = new Map()
|
|
135
136
|
private currentFn: FnDecl | null = null
|
|
136
137
|
private currentReturnType: TypeNode | null = null
|
|
137
138
|
private scope: Map<string, ScopeSymbol> = new Map()
|
|
@@ -174,6 +175,11 @@ export class TypeChecker {
|
|
|
174
175
|
this.functions.set(fn.name, fn)
|
|
175
176
|
}
|
|
176
177
|
|
|
178
|
+
// Register global variables (mutable) so functions can reference and assign them
|
|
179
|
+
for (const global of program.globals ?? []) {
|
|
180
|
+
this.globals.set(global.name, this.normalizeType(global.type))
|
|
181
|
+
}
|
|
182
|
+
|
|
177
183
|
for (const implBlock of program.implBlocks ?? []) {
|
|
178
184
|
let methods = this.implMethods.get(implBlock.typeName)
|
|
179
185
|
if (!methods) {
|
|
@@ -239,6 +245,10 @@ export class TypeChecker {
|
|
|
239
245
|
}
|
|
240
246
|
|
|
241
247
|
private checkFunction(fn: FnDecl): void {
|
|
248
|
+
// Generic functions (with type params like <T>) are checked after monomorphization.
|
|
249
|
+
// Skip body checking here to avoid false errors for unresolved type params.
|
|
250
|
+
if (fn.typeParams && fn.typeParams.length > 0) return
|
|
251
|
+
|
|
242
252
|
this.currentFn = fn
|
|
243
253
|
this.currentReturnType = this.normalizeType(fn.returnType)
|
|
244
254
|
this.scope = new Map()
|
|
@@ -250,6 +260,10 @@ export class TypeChecker {
|
|
|
250
260
|
this.scope.set(name, { type, mutable: false })
|
|
251
261
|
}
|
|
252
262
|
|
|
263
|
+
for (const [name, type] of this.globals.entries()) {
|
|
264
|
+
this.scope.set(name, { type, mutable: true })
|
|
265
|
+
}
|
|
266
|
+
|
|
253
267
|
// Add parameters to scope
|
|
254
268
|
for (const param of fn.params) {
|
|
255
269
|
this.scope.set(param.name, { type: this.normalizeType(param.type), mutable: true })
|
|
@@ -330,6 +344,9 @@ export class TypeChecker {
|
|
|
330
344
|
case 'let':
|
|
331
345
|
this.checkLetStmt(stmt)
|
|
332
346
|
break
|
|
347
|
+
case 'let_destruct':
|
|
348
|
+
this.checkLetDestructStmt(stmt)
|
|
349
|
+
break
|
|
333
350
|
case 'return':
|
|
334
351
|
this.checkReturnStmt(stmt)
|
|
335
352
|
break
|
|
@@ -375,7 +392,12 @@ export class TypeChecker {
|
|
|
375
392
|
for (const arm of stmt.arms) {
|
|
376
393
|
if (arm.pattern) {
|
|
377
394
|
this.checkExpr(arm.pattern)
|
|
378
|
-
|
|
395
|
+
const subjectType = this.inferType(stmt.expr)
|
|
396
|
+
const patternType = this.inferType(arm.pattern)
|
|
397
|
+
// Skip check if either type is unknown (void) — struct field access not yet inferred
|
|
398
|
+
const isUnknown = (t: TypeNode) => t.kind === 'named' && t.name === 'void'
|
|
399
|
+
if (!isUnknown(subjectType) && !isUnknown(patternType) &&
|
|
400
|
+
!this.typesMatch(subjectType, patternType)) {
|
|
379
401
|
this.report('Match arm pattern type must match subject type', arm.pattern)
|
|
380
402
|
}
|
|
381
403
|
}
|
|
@@ -427,6 +449,46 @@ export class TypeChecker {
|
|
|
427
449
|
}
|
|
428
450
|
}
|
|
429
451
|
|
|
452
|
+
private checkLetDestructStmt(stmt: Extract<Stmt, { kind: 'let_destruct' }>): void {
|
|
453
|
+
this.checkExpr(stmt.init)
|
|
454
|
+
const initType = this.inferType(stmt.init)
|
|
455
|
+
if (stmt.type) {
|
|
456
|
+
// Type annotation must be a tuple
|
|
457
|
+
const normalized = this.normalizeType(stmt.type)
|
|
458
|
+
if (normalized.kind !== 'tuple') {
|
|
459
|
+
this.report(`Destructuring type annotation must be a tuple type`, stmt)
|
|
460
|
+
return
|
|
461
|
+
}
|
|
462
|
+
if (normalized.elements.length !== stmt.names.length) {
|
|
463
|
+
this.report(
|
|
464
|
+
`Destructuring pattern has ${stmt.names.length} bindings but type has ${normalized.elements.length} elements`,
|
|
465
|
+
stmt
|
|
466
|
+
)
|
|
467
|
+
}
|
|
468
|
+
for (let i = 0; i < stmt.names.length; i++) {
|
|
469
|
+
const elemType = normalized.elements[i] ?? { kind: 'named', name: 'int' } as TypeNode
|
|
470
|
+
this.scope.set(stmt.names[i], { type: elemType, mutable: true })
|
|
471
|
+
}
|
|
472
|
+
} else if (initType.kind === 'tuple') {
|
|
473
|
+
// Infer element types from tuple literal type
|
|
474
|
+
if (initType.elements.length !== stmt.names.length) {
|
|
475
|
+
this.report(
|
|
476
|
+
`Destructuring pattern has ${stmt.names.length} bindings but tuple has ${initType.elements.length} elements`,
|
|
477
|
+
stmt
|
|
478
|
+
)
|
|
479
|
+
}
|
|
480
|
+
for (let i = 0; i < stmt.names.length; i++) {
|
|
481
|
+
const elemType = initType.elements[i] ?? { kind: 'named', name: 'int' } as TypeNode
|
|
482
|
+
this.scope.set(stmt.names[i], { type: elemType, mutable: true })
|
|
483
|
+
}
|
|
484
|
+
} else {
|
|
485
|
+
// Can't infer element types — use int as fallback (tuple returns inferred as int from scoreboard)
|
|
486
|
+
for (const name of stmt.names) {
|
|
487
|
+
this.scope.set(name, { type: INT_TYPE, mutable: true })
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
430
492
|
private checkLetStmt(stmt: Extract<Stmt, { kind: 'let' }>): void {
|
|
431
493
|
// Check initializer
|
|
432
494
|
const expectedType = stmt.type ? this.normalizeType(stmt.type) : undefined
|
|
@@ -441,13 +503,21 @@ export class TypeChecker {
|
|
|
441
503
|
expectedType &&
|
|
442
504
|
stmt.init.kind !== 'struct_lit' &&
|
|
443
505
|
stmt.init.kind !== 'array_lit' &&
|
|
444
|
-
!(actualType.kind === 'named' && actualType.name === 'void')
|
|
445
|
-
!this.typesMatch(expectedType, actualType)
|
|
506
|
+
!(actualType.kind === 'named' && actualType.name === 'void')
|
|
446
507
|
) {
|
|
447
|
-
this.
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
508
|
+
if (this.isNumericMismatch(expectedType, actualType)) {
|
|
509
|
+
// Explicit numeric conversion required for let assignments
|
|
510
|
+
this.report(
|
|
511
|
+
`Type mismatch: cannot implicitly convert ${this.typeToString(actualType)} to ${this.typeToString(expectedType)}` +
|
|
512
|
+
` (use an explicit cast: 'as ${this.typeToString(expectedType)}')`,
|
|
513
|
+
stmt
|
|
514
|
+
)
|
|
515
|
+
} else if (!this.typesMatch(expectedType, actualType)) {
|
|
516
|
+
this.report(
|
|
517
|
+
`Type mismatch: expected ${this.typeToString(expectedType)}, got ${this.typeToString(actualType)}`,
|
|
518
|
+
stmt
|
|
519
|
+
)
|
|
520
|
+
}
|
|
451
521
|
}
|
|
452
522
|
}
|
|
453
523
|
|
|
@@ -460,7 +530,14 @@ export class TypeChecker {
|
|
|
460
530
|
const actualType = this.inferType(stmt.value, expectedType)
|
|
461
531
|
this.checkExpr(stmt.value, expectedType)
|
|
462
532
|
|
|
463
|
-
if (
|
|
533
|
+
if (this.isNumericMismatch(expectedType, actualType)) {
|
|
534
|
+
// Explicit numeric conversion required for return statements
|
|
535
|
+
this.report(
|
|
536
|
+
`Return type mismatch: cannot implicitly convert ${this.typeToString(actualType)} to ${this.typeToString(expectedType)}` +
|
|
537
|
+
` (use an explicit cast: 'as ${this.typeToString(expectedType)}')`,
|
|
538
|
+
stmt
|
|
539
|
+
)
|
|
540
|
+
} else if (!this.typesMatch(expectedType, actualType)) {
|
|
464
541
|
this.report(
|
|
465
542
|
`Return type mismatch: expected ${this.typeToString(expectedType)}, got ${this.typeToString(actualType)}`,
|
|
466
543
|
stmt
|
|
@@ -559,7 +636,10 @@ export class TypeChecker {
|
|
|
559
636
|
}
|
|
560
637
|
this.checkExpr(part.expr)
|
|
561
638
|
const partType = this.inferType(part.expr)
|
|
639
|
+
// Skip check if type is unknown (void) — struct field access not yet fully inferred
|
|
640
|
+
const isUnknown = partType.kind === 'named' && partType.name === 'void'
|
|
562
641
|
if (
|
|
642
|
+
!isUnknown &&
|
|
563
643
|
!(partType.kind === 'named' && (partType.name === 'int' || partType.name === 'string' || partType.name === 'format_string'))
|
|
564
644
|
) {
|
|
565
645
|
this.report(
|
|
@@ -576,10 +656,30 @@ export class TypeChecker {
|
|
|
576
656
|
}
|
|
577
657
|
break
|
|
578
658
|
|
|
659
|
+
case 'tuple_lit':
|
|
660
|
+
if (expr.elements.length < 2 || expr.elements.length > 8) {
|
|
661
|
+
this.report(`Tuple must have 2-8 elements, got ${expr.elements.length}`, expr)
|
|
662
|
+
}
|
|
663
|
+
for (const elem of expr.elements) {
|
|
664
|
+
this.checkExpr(elem)
|
|
665
|
+
}
|
|
666
|
+
break
|
|
667
|
+
|
|
579
668
|
case 'lambda':
|
|
580
669
|
this.checkLambdaExpr(expr, expectedType)
|
|
581
670
|
break
|
|
582
671
|
|
|
672
|
+
case 'path_expr':
|
|
673
|
+
if (!this.enums.has(expr.enumName)) {
|
|
674
|
+
this.report(`Unknown enum '${expr.enumName}'`, expr)
|
|
675
|
+
} else {
|
|
676
|
+
const variants = this.enums.get(expr.enumName)!
|
|
677
|
+
if (!variants.has(expr.variant)) {
|
|
678
|
+
this.report(`Enum '${expr.enumName}' has no variant '${expr.variant}'`, expr)
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
break
|
|
682
|
+
|
|
583
683
|
case 'blockpos':
|
|
584
684
|
break
|
|
585
685
|
|
|
@@ -619,6 +719,18 @@ export class TypeChecker {
|
|
|
619
719
|
// Check if function exists and arg count matches
|
|
620
720
|
const fn = this.functions.get(expr.fn)
|
|
621
721
|
if (fn) {
|
|
722
|
+
// Generic functions: skip param-type checking (monomorphizer handles it)
|
|
723
|
+
if (fn.typeParams && fn.typeParams.length > 0) {
|
|
724
|
+
const requiredParams = fn.params.filter(param => !param.default).length
|
|
725
|
+
if (expr.args.length < requiredParams || expr.args.length > fn.params.length) {
|
|
726
|
+
this.report(
|
|
727
|
+
`Function '${expr.fn}' expects ${requiredParams}-${fn.params.length} arguments, got ${expr.args.length}`,
|
|
728
|
+
expr
|
|
729
|
+
)
|
|
730
|
+
}
|
|
731
|
+
for (const arg of expr.args) this.checkExpr(arg)
|
|
732
|
+
return
|
|
733
|
+
}
|
|
622
734
|
const requiredParams = fn.params.filter(param => !param.default).length
|
|
623
735
|
if (expr.args.length < requiredParams || expr.args.length > fn.params.length) {
|
|
624
736
|
const expectedRange = requiredParams === fn.params.length
|
|
@@ -968,7 +1080,15 @@ export class TypeChecker {
|
|
|
968
1080
|
return this.normalizeType(implMethod.returnType)
|
|
969
1081
|
}
|
|
970
1082
|
const fn = this.functions.get(expr.fn)
|
|
971
|
-
|
|
1083
|
+
if (fn) {
|
|
1084
|
+
// For generic functions, the return type may be a type param (e.g. T).
|
|
1085
|
+
// If we have an expected type from context, trust it; otherwise return int as default.
|
|
1086
|
+
if (fn.typeParams && fn.typeParams.length > 0) {
|
|
1087
|
+
return expectedType ?? INT_TYPE
|
|
1088
|
+
}
|
|
1089
|
+
return this.normalizeType(fn.returnType)
|
|
1090
|
+
}
|
|
1091
|
+
return INT_TYPE
|
|
972
1092
|
}
|
|
973
1093
|
case 'static_call': {
|
|
974
1094
|
const method = this.implMethods.get(expr.type)?.get(expr.method)
|
|
@@ -981,6 +1101,11 @@ export class TypeChecker {
|
|
|
981
1101
|
}
|
|
982
1102
|
return { kind: 'named', name: 'void' }
|
|
983
1103
|
}
|
|
1104
|
+
case 'path_expr':
|
|
1105
|
+
if (this.enums.has(expr.enumName)) {
|
|
1106
|
+
return { kind: 'enum', name: expr.enumName }
|
|
1107
|
+
}
|
|
1108
|
+
return { kind: 'named', name: 'void' }
|
|
984
1109
|
case 'member':
|
|
985
1110
|
if (expr.obj.kind === 'ident' && this.enums.has(expr.obj.name)) {
|
|
986
1111
|
return { kind: 'enum', name: expr.obj.name }
|
|
@@ -1007,6 +1132,11 @@ export class TypeChecker {
|
|
|
1007
1132
|
case 'unary':
|
|
1008
1133
|
if (expr.op === '!') return { kind: 'named', name: 'bool' }
|
|
1009
1134
|
return this.inferType(expr.operand)
|
|
1135
|
+
case 'selector': {
|
|
1136
|
+
// Infer entity type from the selector
|
|
1137
|
+
const entityType = this.inferEntityTypeFromSelector(expr.sel)
|
|
1138
|
+
return { kind: 'selector', entityType: entityType ?? undefined }
|
|
1139
|
+
}
|
|
1010
1140
|
case 'array_lit':
|
|
1011
1141
|
if (expr.elements.length > 0) {
|
|
1012
1142
|
return { kind: 'array', elem: this.inferType(expr.elements[0]) }
|
|
@@ -1020,6 +1150,22 @@ export class TypeChecker {
|
|
|
1020
1150
|
}
|
|
1021
1151
|
}
|
|
1022
1152
|
return { kind: 'named', name: 'void' }
|
|
1153
|
+
case 'tuple_lit':
|
|
1154
|
+
return {
|
|
1155
|
+
kind: 'tuple',
|
|
1156
|
+
elements: expr.elements.map(e => this.inferType(e)),
|
|
1157
|
+
}
|
|
1158
|
+
case 'some_lit': {
|
|
1159
|
+
// Some(expr) → Option<T> where T is inferred from inner value
|
|
1160
|
+
const innerType = this.inferType(expr.value,
|
|
1161
|
+
expectedType?.kind === 'option' ? expectedType.inner : undefined)
|
|
1162
|
+
return { kind: 'option', inner: innerType }
|
|
1163
|
+
}
|
|
1164
|
+
case 'none_lit': {
|
|
1165
|
+
// None → Option<T>, use expected type if available
|
|
1166
|
+
if (expectedType?.kind === 'option') return expectedType
|
|
1167
|
+
return { kind: 'option', inner: { kind: 'named', name: 'void' } }
|
|
1168
|
+
}
|
|
1023
1169
|
case 'lambda':
|
|
1024
1170
|
return this.inferLambdaType(
|
|
1025
1171
|
expr,
|
|
@@ -1132,13 +1278,53 @@ export class TypeChecker {
|
|
|
1132
1278
|
return this.selfTypeStack[this.selfTypeStack.length - 1]
|
|
1133
1279
|
}
|
|
1134
1280
|
|
|
1281
|
+
/** Returns true if expected/actual are a numeric type mismatch (int vs float). */
|
|
1282
|
+
private isNumericMismatch(expected: TypeNode, actual: TypeNode): boolean {
|
|
1283
|
+
if (expected.kind !== 'named' || actual.kind !== 'named') return false
|
|
1284
|
+
const numericPairs = [
|
|
1285
|
+
['int', 'float'], ['float', 'int'],
|
|
1286
|
+
['int', 'double'], ['double', 'int'],
|
|
1287
|
+
['float', 'double'], ['double', 'float'],
|
|
1288
|
+
]
|
|
1289
|
+
return numericPairs.some(([e, a]) => expected.name === e && actual.name === a)
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1135
1292
|
private typesMatch(expected: TypeNode, actual: TypeNode): boolean {
|
|
1293
|
+
// Enum values are backed by int — allow enum where int is expected and vice versa
|
|
1294
|
+
if (expected.kind === 'named' && expected.name === 'int' && actual.kind === 'enum') {
|
|
1295
|
+
return true
|
|
1296
|
+
}
|
|
1297
|
+
if (expected.kind === 'enum' && actual.kind === 'named' && actual.name === 'int') {
|
|
1298
|
+
return true
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
// Selector/entity cross-kind compatibility (must come before kind guard)
|
|
1302
|
+
if (expected.kind === 'selector' && actual.kind === 'entity') {
|
|
1303
|
+
return true // entity is a valid selector
|
|
1304
|
+
}
|
|
1305
|
+
if (expected.kind === 'entity' && actual.kind === 'selector') {
|
|
1306
|
+
return true // selector is a valid entity context
|
|
1307
|
+
}
|
|
1308
|
+
if (expected.kind === 'entity' && actual.kind === 'entity') {
|
|
1309
|
+
return this.isEntitySubtype(actual.entityType, expected.entityType)
|
|
1310
|
+
}
|
|
1311
|
+
if (expected.kind === 'selector' && actual.kind === 'selector') {
|
|
1312
|
+
return true // any entity subtype is compatible
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1136
1315
|
if (expected.kind !== actual.kind) return false
|
|
1137
1316
|
|
|
1138
1317
|
if (expected.kind === 'named' && actual.kind === 'named') {
|
|
1139
1318
|
// void matches anything (for inferred types)
|
|
1140
1319
|
if (actual.name === 'void') return true
|
|
1141
|
-
|
|
1320
|
+
if (expected.name === actual.name) return true
|
|
1321
|
+
// int→float/double implicit promotion in function calls (not for let/return — handled separately)
|
|
1322
|
+
const numericPromotion = [
|
|
1323
|
+
['int', 'float'], ['int', 'double'], ['float', 'double'],
|
|
1324
|
+
['float', 'int'], ['double', 'int'], ['double', 'float'],
|
|
1325
|
+
]
|
|
1326
|
+
if (numericPromotion.some(([e, a]) => expected.name === e && actual.name === a)) return true
|
|
1327
|
+
return false
|
|
1142
1328
|
}
|
|
1143
1329
|
|
|
1144
1330
|
if (expected.kind === 'array' && actual.kind === 'array') {
|
|
@@ -1159,13 +1345,17 @@ export class TypeChecker {
|
|
|
1159
1345
|
this.typesMatch(expected.return, actual.return)
|
|
1160
1346
|
}
|
|
1161
1347
|
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1348
|
+
if (expected.kind === 'tuple' && actual.kind === 'tuple') {
|
|
1349
|
+
return expected.elements.length === actual.elements.length &&
|
|
1350
|
+
expected.elements.every((elem, i) => this.typesMatch(elem, actual.elements[i]))
|
|
1165
1351
|
}
|
|
1166
1352
|
|
|
1167
|
-
|
|
1168
|
-
|
|
1353
|
+
if (expected.kind === 'option' && actual.kind === 'option') {
|
|
1354
|
+
return this.typesMatch(expected.inner, actual.inner)
|
|
1355
|
+
}
|
|
1356
|
+
|
|
1357
|
+
// Option<T> is compatible with None (void inner) or partially inferred types
|
|
1358
|
+
if (expected.kind === 'option' && actual.kind === 'named' && actual.name === 'void') {
|
|
1169
1359
|
return true
|
|
1170
1360
|
}
|
|
1171
1361
|
|
|
@@ -1188,6 +1378,10 @@ export class TypeChecker {
|
|
|
1188
1378
|
return type.entityType
|
|
1189
1379
|
case 'selector':
|
|
1190
1380
|
return 'selector'
|
|
1381
|
+
case 'tuple':
|
|
1382
|
+
return `(${type.elements.map(e => this.typeToString(e)).join(', ')})`
|
|
1383
|
+
case 'option':
|
|
1384
|
+
return `Option<${this.typeToString(type.inner)}>`
|
|
1191
1385
|
default:
|
|
1192
1386
|
return 'unknown'
|
|
1193
1387
|
}
|
|
@@ -1197,6 +1391,12 @@ export class TypeChecker {
|
|
|
1197
1391
|
if (type.kind === 'array') {
|
|
1198
1392
|
return { kind: 'array', elem: this.normalizeType(type.elem) }
|
|
1199
1393
|
}
|
|
1394
|
+
if (type.kind === 'option') {
|
|
1395
|
+
return { kind: 'option', inner: this.normalizeType(type.inner) }
|
|
1396
|
+
}
|
|
1397
|
+
if (type.kind === 'tuple') {
|
|
1398
|
+
return { kind: 'tuple', elements: type.elements.map(e => this.normalizeType(e)) }
|
|
1399
|
+
}
|
|
1200
1400
|
if (type.kind === 'function_type') {
|
|
1201
1401
|
return {
|
|
1202
1402
|
kind: 'function_type',
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minecraft version target enumeration.
|
|
3
|
+
*
|
|
4
|
+
* Encoded as: major * 1000 + minor (patch is ignored for feature gating).
|
|
5
|
+
* e.g., 1.20.2 → 20002, 1.21 → 21000, 1.21.4 → 21004
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export enum McVersion {
|
|
9
|
+
v1_19 = 19000,
|
|
10
|
+
v1_20 = 20000,
|
|
11
|
+
v1_20_2 = 20002,
|
|
12
|
+
v1_20_4 = 20004,
|
|
13
|
+
v1_21 = 21000,
|
|
14
|
+
v1_21_4 = 21004,
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Parse a version string like "1.20.2" or "1.21" into a McVersion number.
|
|
19
|
+
* Throws if the string is not a valid Minecraft version.
|
|
20
|
+
*/
|
|
21
|
+
export function parseMcVersion(s: string): McVersion {
|
|
22
|
+
const parts = s.trim().split('.')
|
|
23
|
+
if (parts.length < 2 || parts.length > 3) {
|
|
24
|
+
throw new Error(`Invalid MC version: "${s}" — expected format "1.20" or "1.20.2"`)
|
|
25
|
+
}
|
|
26
|
+
const [majorStr, minorStr, patchStr = '0'] = parts
|
|
27
|
+
const major = parseInt(majorStr, 10)
|
|
28
|
+
const minor = parseInt(minorStr, 10)
|
|
29
|
+
const patch = parseInt(patchStr, 10)
|
|
30
|
+
if (isNaN(major) || isNaN(minor) || isNaN(patch)) {
|
|
31
|
+
throw new Error(`Invalid MC version: "${s}" — non-numeric component`)
|
|
32
|
+
}
|
|
33
|
+
if (major !== 1) {
|
|
34
|
+
throw new Error(`Invalid MC version: "${s}" — only Minecraft 1.x is supported`)
|
|
35
|
+
}
|
|
36
|
+
return minor * 1000 + patch as McVersion
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Compare two McVersion values. Returns negative if a < b, 0 if equal, positive if a > b.
|
|
41
|
+
*/
|
|
42
|
+
export function compareMcVersion(a: McVersion, b: McVersion): number {
|
|
43
|
+
return a - b
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const DEFAULT_MC_VERSION = McVersion.v1_21
|