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
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dead Code Elimination — MIR optimization pass.
|
|
3
|
+
*
|
|
4
|
+
* 1. Removes definitions of temps that are never used anywhere in the function.
|
|
5
|
+
* 2. Removes unreachable blocks (no predecessors and not the entry block).
|
|
6
|
+
*/
|
|
7
|
+
import type { MIRFunction } from '../mir/types';
|
|
8
|
+
export declare function dce(fn: MIRFunction): MIRFunction;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Dead Code Elimination — MIR optimization pass.
|
|
4
|
+
*
|
|
5
|
+
* 1. Removes definitions of temps that are never used anywhere in the function.
|
|
6
|
+
* 2. Removes unreachable blocks (no predecessors and not the entry block).
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.dce = dce;
|
|
10
|
+
function dce(fn) {
|
|
11
|
+
// Phase 1: Remove unreachable blocks
|
|
12
|
+
let blocks = removeUnreachable(fn);
|
|
13
|
+
// Phase 2: Remove unused temp definitions
|
|
14
|
+
blocks = removeDeadDefs(fn.params, blocks);
|
|
15
|
+
// Phase 3: Recompute preds after block removal
|
|
16
|
+
blocks = recomputePreds(blocks);
|
|
17
|
+
return { ...fn, blocks };
|
|
18
|
+
}
|
|
19
|
+
function removeUnreachable(fn) {
|
|
20
|
+
const reachable = new Set();
|
|
21
|
+
const queue = [fn.entry];
|
|
22
|
+
const blockMap = new Map(fn.blocks.map(b => [b.id, b]));
|
|
23
|
+
while (queue.length > 0) {
|
|
24
|
+
const id = queue.shift();
|
|
25
|
+
if (reachable.has(id))
|
|
26
|
+
continue;
|
|
27
|
+
reachable.add(id);
|
|
28
|
+
const block = blockMap.get(id);
|
|
29
|
+
if (block) {
|
|
30
|
+
for (const target of getTermTargets(block.term)) {
|
|
31
|
+
if (!reachable.has(target))
|
|
32
|
+
queue.push(target);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return fn.blocks.filter(b => reachable.has(b.id));
|
|
37
|
+
}
|
|
38
|
+
function removeDeadDefs(params, blocks) {
|
|
39
|
+
// Collect all used temps across the entire function
|
|
40
|
+
const used = new Set();
|
|
41
|
+
for (const block of blocks) {
|
|
42
|
+
for (const instr of block.instrs) {
|
|
43
|
+
for (const t of getUsedTemps(instr))
|
|
44
|
+
used.add(t);
|
|
45
|
+
}
|
|
46
|
+
for (const t of getUsedTemps(block.term))
|
|
47
|
+
used.add(t);
|
|
48
|
+
}
|
|
49
|
+
// Remove instructions whose dst is never used, unless they have side effects
|
|
50
|
+
return blocks.map(block => ({
|
|
51
|
+
...block,
|
|
52
|
+
instrs: block.instrs.filter(instr => {
|
|
53
|
+
const dst = getDst(instr);
|
|
54
|
+
if (dst === null)
|
|
55
|
+
return true; // no dst → keep (side-effectful)
|
|
56
|
+
if (hasSideEffects(instr))
|
|
57
|
+
return true;
|
|
58
|
+
return used.has(dst);
|
|
59
|
+
}),
|
|
60
|
+
}));
|
|
61
|
+
}
|
|
62
|
+
function recomputePreds(blocks) {
|
|
63
|
+
const predMap = new Map();
|
|
64
|
+
for (const b of blocks)
|
|
65
|
+
predMap.set(b.id, []);
|
|
66
|
+
for (const block of blocks) {
|
|
67
|
+
for (const target of getTermTargets(block.term)) {
|
|
68
|
+
const preds = predMap.get(target);
|
|
69
|
+
if (preds)
|
|
70
|
+
preds.push(block.id);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return blocks.map(b => ({ ...b, preds: predMap.get(b.id) ?? [] }));
|
|
74
|
+
}
|
|
75
|
+
function hasSideEffects(instr) {
|
|
76
|
+
if (instr.kind === 'call' || instr.kind === 'call_macro' ||
|
|
77
|
+
instr.kind === 'call_context' || instr.kind === 'nbt_write')
|
|
78
|
+
return true;
|
|
79
|
+
// Return field temps (__rf_) write to global return slots — not dead even if unused locally
|
|
80
|
+
// Option slot temps (__opt_) write observable scoreboard state — preserve even if var unused
|
|
81
|
+
const dst = getDst(instr);
|
|
82
|
+
if (dst && (dst.startsWith('__rf_') || dst.startsWith('__opt_')))
|
|
83
|
+
return true;
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
function getTermTargets(term) {
|
|
87
|
+
switch (term.kind) {
|
|
88
|
+
case 'jump': return [term.target];
|
|
89
|
+
case 'branch': return [term.then, term.else];
|
|
90
|
+
default: return [];
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function getDst(instr) {
|
|
94
|
+
switch (instr.kind) {
|
|
95
|
+
case 'const':
|
|
96
|
+
case 'copy':
|
|
97
|
+
case 'add':
|
|
98
|
+
case 'sub':
|
|
99
|
+
case 'mul':
|
|
100
|
+
case 'div':
|
|
101
|
+
case 'mod':
|
|
102
|
+
case 'neg':
|
|
103
|
+
case 'cmp':
|
|
104
|
+
case 'and':
|
|
105
|
+
case 'or':
|
|
106
|
+
case 'not':
|
|
107
|
+
case 'nbt_read':
|
|
108
|
+
return instr.dst;
|
|
109
|
+
case 'call':
|
|
110
|
+
case 'call_macro':
|
|
111
|
+
return instr.dst;
|
|
112
|
+
default:
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
function getUsedTemps(instr) {
|
|
117
|
+
const temps = [];
|
|
118
|
+
const addOp = (op) => { if (op.kind === 'temp')
|
|
119
|
+
temps.push(op.name); };
|
|
120
|
+
switch (instr.kind) {
|
|
121
|
+
case 'copy':
|
|
122
|
+
case 'neg':
|
|
123
|
+
case 'not':
|
|
124
|
+
addOp(instr.src);
|
|
125
|
+
break;
|
|
126
|
+
case 'add':
|
|
127
|
+
case 'sub':
|
|
128
|
+
case 'mul':
|
|
129
|
+
case 'div':
|
|
130
|
+
case 'mod':
|
|
131
|
+
case 'cmp':
|
|
132
|
+
case 'and':
|
|
133
|
+
case 'or':
|
|
134
|
+
addOp(instr.a);
|
|
135
|
+
addOp(instr.b);
|
|
136
|
+
break;
|
|
137
|
+
case 'nbt_write':
|
|
138
|
+
addOp(instr.src);
|
|
139
|
+
break;
|
|
140
|
+
case 'call':
|
|
141
|
+
instr.args.forEach(addOp);
|
|
142
|
+
break;
|
|
143
|
+
case 'call_macro':
|
|
144
|
+
instr.args.forEach(a => addOp(a.value));
|
|
145
|
+
break;
|
|
146
|
+
case 'branch':
|
|
147
|
+
addOp(instr.cond);
|
|
148
|
+
break;
|
|
149
|
+
case 'return':
|
|
150
|
+
if (instr.value)
|
|
151
|
+
addOp(instr.value);
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
return temps;
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=dce.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interprocedural Constant Propagation — MIR module-level optimization pass.
|
|
3
|
+
*
|
|
4
|
+
* For each call site where all arguments are compile-time constants, creates
|
|
5
|
+
* a specialized clone of the callee with the parameters substituted as
|
|
6
|
+
* constants, then runs constant folding on the clone.
|
|
7
|
+
*
|
|
8
|
+
* Specialized function naming: `original__const_N1_N2_...` where N1, N2 are
|
|
9
|
+
* the constant argument values.
|
|
10
|
+
*
|
|
11
|
+
* This pass iterates to fixpoint to handle transitively specialized callees.
|
|
12
|
+
*/
|
|
13
|
+
import type { MIRModule } from '../mir/types';
|
|
14
|
+
export declare function interproceduralConstProp(mod: MIRModule): MIRModule;
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Interprocedural Constant Propagation — MIR module-level optimization pass.
|
|
4
|
+
*
|
|
5
|
+
* For each call site where all arguments are compile-time constants, creates
|
|
6
|
+
* a specialized clone of the callee with the parameters substituted as
|
|
7
|
+
* constants, then runs constant folding on the clone.
|
|
8
|
+
*
|
|
9
|
+
* Specialized function naming: `original__const_N1_N2_...` where N1, N2 are
|
|
10
|
+
* the constant argument values.
|
|
11
|
+
*
|
|
12
|
+
* This pass iterates to fixpoint to handle transitively specialized callees.
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.interproceduralConstProp = interproceduralConstProp;
|
|
16
|
+
const constant_fold_1 = require("./constant_fold");
|
|
17
|
+
function interproceduralConstProp(mod) {
|
|
18
|
+
let current = mod;
|
|
19
|
+
// Iterate to fixpoint (new specializations may enable further specializations)
|
|
20
|
+
for (let i = 0; i < 10; i++) {
|
|
21
|
+
const next = runOnePass(current);
|
|
22
|
+
if (next.functions.length === current.functions.length &&
|
|
23
|
+
JSON.stringify(next.functions.map(f => f.name)) === JSON.stringify(current.functions.map(f => f.name))) {
|
|
24
|
+
// No new specializations
|
|
25
|
+
return next;
|
|
26
|
+
}
|
|
27
|
+
current = next;
|
|
28
|
+
}
|
|
29
|
+
return current;
|
|
30
|
+
}
|
|
31
|
+
function runOnePass(mod) {
|
|
32
|
+
const fnMap = new Map(mod.functions.map(f => [f.name, f]));
|
|
33
|
+
const newFunctions = [...mod.functions];
|
|
34
|
+
const added = new Set();
|
|
35
|
+
for (const fn of mod.functions) {
|
|
36
|
+
for (const block of fn.blocks) {
|
|
37
|
+
for (const instr of block.instrs) {
|
|
38
|
+
if (instr.kind !== 'call')
|
|
39
|
+
continue;
|
|
40
|
+
if (instr.args.length === 0)
|
|
41
|
+
continue;
|
|
42
|
+
if (!instr.args.every(a => a.kind === 'const'))
|
|
43
|
+
continue;
|
|
44
|
+
const callee = fnMap.get(instr.fn);
|
|
45
|
+
if (!callee)
|
|
46
|
+
continue;
|
|
47
|
+
if (callee.isMacro)
|
|
48
|
+
continue;
|
|
49
|
+
if (callee.name === fn.name)
|
|
50
|
+
continue; // no direct recursion at call site
|
|
51
|
+
if (callee.params.length !== instr.args.length)
|
|
52
|
+
continue;
|
|
53
|
+
// Skip if the callee is self-recursive (would cause infinite specialization)
|
|
54
|
+
if (isSelfRecursive(callee))
|
|
55
|
+
continue;
|
|
56
|
+
// Only specialize single-block (loop-free) functions — loop bodies mutate
|
|
57
|
+
// variables in ways that make constant-param substitution unsafe.
|
|
58
|
+
if (callee.blocks.length > 1)
|
|
59
|
+
continue;
|
|
60
|
+
const constArgs = instr.args;
|
|
61
|
+
const mangledName = mangleName(instr.fn, constArgs.map(a => a.value));
|
|
62
|
+
if (fnMap.has(mangledName) || added.has(mangledName))
|
|
63
|
+
continue;
|
|
64
|
+
// Create specialized clone
|
|
65
|
+
const specialized = specialize(callee, constArgs.map(a => a.value), mangledName);
|
|
66
|
+
newFunctions.push(specialized);
|
|
67
|
+
added.add(mangledName);
|
|
68
|
+
fnMap.set(mangledName, specialized);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (added.size === 0)
|
|
73
|
+
return mod;
|
|
74
|
+
// Rewrite call sites to use specialized names
|
|
75
|
+
const updatedFunctions = newFunctions.map(fn => rewriteCallSites(fn, fnMap));
|
|
76
|
+
return { ...mod, functions: updatedFunctions };
|
|
77
|
+
}
|
|
78
|
+
/** Returns true if the function contains a call to itself (direct recursion). */
|
|
79
|
+
function isSelfRecursive(fn) {
|
|
80
|
+
for (const block of fn.blocks) {
|
|
81
|
+
for (const instr of block.instrs) {
|
|
82
|
+
if (instr.kind === 'call' && instr.fn === fn.name)
|
|
83
|
+
return true;
|
|
84
|
+
if (instr.kind === 'call_macro' && instr.fn === fn.name)
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
function mangleName(name, args) {
|
|
91
|
+
return `${name}__const_${args.map(v => v < 0 ? `n${Math.abs(v)}` : String(v)).join('_')}`;
|
|
92
|
+
}
|
|
93
|
+
function specialize(fn, args, newName) {
|
|
94
|
+
// Build substitution map: param.name → const operand
|
|
95
|
+
const sub = new Map();
|
|
96
|
+
for (let i = 0; i < fn.params.length; i++) {
|
|
97
|
+
sub.set(fn.params[i].name, { kind: 'const', value: args[i] });
|
|
98
|
+
}
|
|
99
|
+
const newBlocks = fn.blocks.map(block => substituteBlock(block, sub));
|
|
100
|
+
const specialized = {
|
|
101
|
+
...fn,
|
|
102
|
+
name: newName,
|
|
103
|
+
params: [], // no params — all specialized
|
|
104
|
+
blocks: newBlocks,
|
|
105
|
+
isMacro: false,
|
|
106
|
+
};
|
|
107
|
+
// Run constant folding on the specialized function
|
|
108
|
+
return (0, constant_fold_1.constantFold)(specialized);
|
|
109
|
+
}
|
|
110
|
+
function substituteBlock(block, sub) {
|
|
111
|
+
const instrs = block.instrs.map(instr => substituteInstr(instr, sub));
|
|
112
|
+
const term = substituteInstr(block.term, sub);
|
|
113
|
+
return { ...block, instrs, term };
|
|
114
|
+
}
|
|
115
|
+
function substituteOp(op, sub) {
|
|
116
|
+
if (op.kind === 'temp') {
|
|
117
|
+
const replacement = sub.get(op.name);
|
|
118
|
+
if (replacement !== undefined)
|
|
119
|
+
return replacement;
|
|
120
|
+
}
|
|
121
|
+
return op;
|
|
122
|
+
}
|
|
123
|
+
function substituteInstr(instr, sub) {
|
|
124
|
+
switch (instr.kind) {
|
|
125
|
+
case 'copy': return { ...instr, src: substituteOp(instr.src, sub) };
|
|
126
|
+
case 'neg':
|
|
127
|
+
case 'not': return { ...instr, src: substituteOp(instr.src, sub) };
|
|
128
|
+
case 'add':
|
|
129
|
+
case 'sub':
|
|
130
|
+
case 'mul':
|
|
131
|
+
case 'div':
|
|
132
|
+
case 'mod':
|
|
133
|
+
case 'and':
|
|
134
|
+
case 'or':
|
|
135
|
+
return { ...instr, a: substituteOp(instr.a, sub), b: substituteOp(instr.b, sub) };
|
|
136
|
+
case 'cmp':
|
|
137
|
+
return { ...instr, a: substituteOp(instr.a, sub), b: substituteOp(instr.b, sub) };
|
|
138
|
+
case 'nbt_write':
|
|
139
|
+
return { ...instr, src: substituteOp(instr.src, sub) };
|
|
140
|
+
case 'call':
|
|
141
|
+
return { ...instr, args: instr.args.map(a => substituteOp(a, sub)) };
|
|
142
|
+
case 'call_macro':
|
|
143
|
+
return { ...instr, args: instr.args.map(a => ({ ...a, value: substituteOp(a.value, sub) })) };
|
|
144
|
+
case 'branch':
|
|
145
|
+
return { ...instr, cond: substituteOp(instr.cond, sub) };
|
|
146
|
+
case 'return':
|
|
147
|
+
return { ...instr, value: instr.value ? substituteOp(instr.value, sub) : null };
|
|
148
|
+
default:
|
|
149
|
+
return instr;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
function rewriteCallSites(fn, fnMap) {
|
|
153
|
+
return {
|
|
154
|
+
...fn,
|
|
155
|
+
blocks: fn.blocks.map(block => ({
|
|
156
|
+
...block,
|
|
157
|
+
instrs: block.instrs.map(instr => {
|
|
158
|
+
if (instr.kind !== 'call')
|
|
159
|
+
return instr;
|
|
160
|
+
if (!instr.args.every(a => a.kind === 'const'))
|
|
161
|
+
return instr;
|
|
162
|
+
const callee = fnMap.get(instr.fn);
|
|
163
|
+
if (!callee)
|
|
164
|
+
return instr;
|
|
165
|
+
if (callee.isMacro)
|
|
166
|
+
return instr;
|
|
167
|
+
if (callee.name === fn.name)
|
|
168
|
+
return instr;
|
|
169
|
+
if (callee.params.length !== instr.args.length)
|
|
170
|
+
return instr;
|
|
171
|
+
const constArgs = instr.args;
|
|
172
|
+
const mangledName = mangleName(instr.fn, constArgs.map(a => a.value));
|
|
173
|
+
if (!fnMap.has(mangledName))
|
|
174
|
+
return instr;
|
|
175
|
+
return { ...instr, fn: mangledName, args: [] };
|
|
176
|
+
}),
|
|
177
|
+
term: (() => {
|
|
178
|
+
const term = block.term;
|
|
179
|
+
if (term.kind !== 'call')
|
|
180
|
+
return term;
|
|
181
|
+
return term;
|
|
182
|
+
})(),
|
|
183
|
+
})),
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=interprocedural.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constant Immediate Folding — LIR optimization pass.
|
|
3
|
+
*
|
|
4
|
+
* Peephole: finds score_set($__const_C, C) immediately followed by
|
|
5
|
+
* score_add/score_sub(dst, $__const_C), where $__const_C has no other
|
|
6
|
+
* uses in the function, and replaces the pair with a single
|
|
7
|
+
* `scoreboard players add/remove` raw command.
|
|
8
|
+
*
|
|
9
|
+
* This saves one command per arithmetic-with-constant operation.
|
|
10
|
+
*/
|
|
11
|
+
import type { LIRFunction } from '../../lir/types';
|
|
12
|
+
export declare function constImmFold(fn: LIRFunction): LIRFunction;
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Constant Immediate Folding — LIR optimization pass.
|
|
4
|
+
*
|
|
5
|
+
* Peephole: finds score_set($__const_C, C) immediately followed by
|
|
6
|
+
* score_add/score_sub(dst, $__const_C), where $__const_C has no other
|
|
7
|
+
* uses in the function, and replaces the pair with a single
|
|
8
|
+
* `scoreboard players add/remove` raw command.
|
|
9
|
+
*
|
|
10
|
+
* This saves one command per arithmetic-with-constant operation.
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.constImmFold = constImmFold;
|
|
14
|
+
function slotKey(s) {
|
|
15
|
+
return `${s.player}\0${s.obj}`;
|
|
16
|
+
}
|
|
17
|
+
/** Count how many times a slot is used as a source operand. */
|
|
18
|
+
function countSlotUses(instrs, target) {
|
|
19
|
+
let count = 0;
|
|
20
|
+
for (const instr of instrs) {
|
|
21
|
+
for (const s of getReadSlots(instr)) {
|
|
22
|
+
if (slotKey(s) === target)
|
|
23
|
+
count++;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return count;
|
|
27
|
+
}
|
|
28
|
+
function extractSlotsFromRaw(cmd) {
|
|
29
|
+
const slots = [];
|
|
30
|
+
const re = /(\$[\w.]+)\s+(\S+)/g;
|
|
31
|
+
let m;
|
|
32
|
+
while ((m = re.exec(cmd)) !== null) {
|
|
33
|
+
slots.push({ player: m[1], obj: m[2] });
|
|
34
|
+
}
|
|
35
|
+
return slots;
|
|
36
|
+
}
|
|
37
|
+
function getReadSlots(instr) {
|
|
38
|
+
switch (instr.kind) {
|
|
39
|
+
case 'score_copy': return [instr.src];
|
|
40
|
+
case 'score_add':
|
|
41
|
+
case 'score_sub':
|
|
42
|
+
case 'score_mul':
|
|
43
|
+
case 'score_div':
|
|
44
|
+
case 'score_mod':
|
|
45
|
+
case 'score_min':
|
|
46
|
+
case 'score_max':
|
|
47
|
+
return [instr.src];
|
|
48
|
+
case 'score_swap': return [instr.a, instr.b];
|
|
49
|
+
case 'store_cmd_to_score': return getReadSlots(instr.cmd);
|
|
50
|
+
case 'store_score_to_nbt': return [instr.src];
|
|
51
|
+
case 'return_value': return [instr.slot];
|
|
52
|
+
case 'call_if_matches':
|
|
53
|
+
case 'call_unless_matches':
|
|
54
|
+
return [instr.slot];
|
|
55
|
+
case 'call_if_score':
|
|
56
|
+
case 'call_unless_score':
|
|
57
|
+
return [instr.a, instr.b];
|
|
58
|
+
case 'raw': return extractSlotsFromRaw(instr.cmd);
|
|
59
|
+
case 'macro_line': return extractSlotsFromRaw(instr.template);
|
|
60
|
+
default: return [];
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function constImmFold(fn) {
|
|
64
|
+
const instrs = fn.instructions;
|
|
65
|
+
if (instrs.length < 2)
|
|
66
|
+
return fn;
|
|
67
|
+
// Pre-compute use counts for all const slots
|
|
68
|
+
const useCounts = new Map();
|
|
69
|
+
for (const instr of instrs) {
|
|
70
|
+
for (const s of getReadSlots(instr)) {
|
|
71
|
+
const key = slotKey(s);
|
|
72
|
+
useCounts.set(key, (useCounts.get(key) || 0) + 1);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const result = [];
|
|
76
|
+
let changed = false;
|
|
77
|
+
let i = 0;
|
|
78
|
+
while (i < instrs.length) {
|
|
79
|
+
const curr = instrs[i];
|
|
80
|
+
const next = instrs[i + 1];
|
|
81
|
+
// Pattern: score_set(constSlot, C) + score_add/sub(dst, constSlot)
|
|
82
|
+
if (next &&
|
|
83
|
+
curr.kind === 'score_set' &&
|
|
84
|
+
curr.dst.player.startsWith('$__const_') &&
|
|
85
|
+
(next.kind === 'score_add' || next.kind === 'score_sub') &&
|
|
86
|
+
slotKey(next.src) === slotKey(curr.dst) &&
|
|
87
|
+
(useCounts.get(slotKey(curr.dst)) || 0) === 1) {
|
|
88
|
+
const C = curr.value;
|
|
89
|
+
const dst = next.dst;
|
|
90
|
+
if (C === 0 && next.kind === 'score_add') {
|
|
91
|
+
// add 0 is a no-op — skip both
|
|
92
|
+
changed = true;
|
|
93
|
+
i += 2;
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (C === 0 && next.kind === 'score_sub') {
|
|
97
|
+
// sub 0 is a no-op — skip both
|
|
98
|
+
changed = true;
|
|
99
|
+
i += 2;
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
// Determine add vs remove
|
|
103
|
+
let op;
|
|
104
|
+
let val;
|
|
105
|
+
if (next.kind === 'score_add') {
|
|
106
|
+
if (C > 0) {
|
|
107
|
+
op = 'add';
|
|
108
|
+
val = C;
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
op = 'remove';
|
|
112
|
+
val = -C;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
// score_sub
|
|
117
|
+
if (C > 0) {
|
|
118
|
+
op = 'remove';
|
|
119
|
+
val = C;
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
op = 'add';
|
|
123
|
+
val = -C;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
result.push({
|
|
127
|
+
kind: 'raw',
|
|
128
|
+
cmd: `scoreboard players ${op} ${dst.player} ${dst.obj} ${val}`,
|
|
129
|
+
});
|
|
130
|
+
changed = true;
|
|
131
|
+
i += 2;
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
result.push(curr);
|
|
135
|
+
i++;
|
|
136
|
+
}
|
|
137
|
+
return changed ? { ...fn, instructions: result } : fn;
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=const_imm.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dead Slot Elimination — LIR optimization pass.
|
|
3
|
+
*
|
|
4
|
+
* Removes score_set / score_copy instructions where the destination slot
|
|
5
|
+
* is never read anywhere in the function.
|
|
6
|
+
*
|
|
7
|
+
* Preserves writes to:
|
|
8
|
+
* - $ret (return value)
|
|
9
|
+
* - $p0, $p1, … (parameter passing slots)
|
|
10
|
+
* - slots used in side-effectful instructions (calls, stores, nbt ops, raw)
|
|
11
|
+
*/
|
|
12
|
+
import type { LIRFunction, LIRModule } from '../../lir/types';
|
|
13
|
+
export declare function deadSlotElim(fn: LIRFunction): LIRFunction;
|
|
14
|
+
export declare function deadSlotElimModule(mod: LIRModule): LIRModule;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Dead Slot Elimination — LIR optimization pass.
|
|
4
|
+
*
|
|
5
|
+
* Removes score_set / score_copy instructions where the destination slot
|
|
6
|
+
* is never read anywhere in the function.
|
|
7
|
+
*
|
|
8
|
+
* Preserves writes to:
|
|
9
|
+
* - $ret (return value)
|
|
10
|
+
* - $p0, $p1, … (parameter passing slots)
|
|
11
|
+
* - slots used in side-effectful instructions (calls, stores, nbt ops, raw)
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.deadSlotElim = deadSlotElim;
|
|
15
|
+
exports.deadSlotElimModule = deadSlotElimModule;
|
|
16
|
+
/** Canonical key for a slot (player + obj). */
|
|
17
|
+
function slotKey(s) {
|
|
18
|
+
return `${s.player}\0${s.obj}`;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Extract slot references from a raw MC command string.
|
|
22
|
+
* Matches patterns like `$player_name objective_name` used in scoreboard commands.
|
|
23
|
+
*/
|
|
24
|
+
function extractSlotsFromRaw(cmd) {
|
|
25
|
+
const slots = [];
|
|
26
|
+
// Match $<player> <obj> patterns (scoreboard slot references)
|
|
27
|
+
const re = /(\$[\w.]+)\s+(\S+)/g;
|
|
28
|
+
let m;
|
|
29
|
+
while ((m = re.exec(cmd)) !== null) {
|
|
30
|
+
slots.push({ player: m[1], obj: m[2] });
|
|
31
|
+
}
|
|
32
|
+
return slots;
|
|
33
|
+
}
|
|
34
|
+
/** Collect all slots that are *read* (used as source) by an instruction. */
|
|
35
|
+
function getReadSlots(instr) {
|
|
36
|
+
switch (instr.kind) {
|
|
37
|
+
case 'score_copy': return [instr.src];
|
|
38
|
+
case 'score_add':
|
|
39
|
+
case 'score_sub':
|
|
40
|
+
case 'score_mul':
|
|
41
|
+
case 'score_div':
|
|
42
|
+
case 'score_mod':
|
|
43
|
+
case 'score_min':
|
|
44
|
+
case 'score_max':
|
|
45
|
+
return [instr.src];
|
|
46
|
+
case 'score_swap': return [instr.a, instr.b];
|
|
47
|
+
case 'store_cmd_to_score': return getReadSlots(instr.cmd);
|
|
48
|
+
case 'store_score_to_nbt': return [instr.src];
|
|
49
|
+
case 'store_nbt_to_score': return [];
|
|
50
|
+
case 'return_value': return [instr.slot];
|
|
51
|
+
case 'call_if_matches':
|
|
52
|
+
case 'call_unless_matches':
|
|
53
|
+
return [instr.slot];
|
|
54
|
+
case 'call_if_score':
|
|
55
|
+
case 'call_unless_score':
|
|
56
|
+
return [instr.a, instr.b];
|
|
57
|
+
case 'raw': return extractSlotsFromRaw(instr.cmd);
|
|
58
|
+
case 'macro_line': return extractSlotsFromRaw(instr.template);
|
|
59
|
+
default: return [];
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/** Returns the destination slot if the instruction is a pure write (no side effects). */
|
|
63
|
+
function getPureWriteDst(instr) {
|
|
64
|
+
switch (instr.kind) {
|
|
65
|
+
case 'score_set': return instr.dst;
|
|
66
|
+
case 'score_copy': return instr.dst;
|
|
67
|
+
default: return null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/** True if a slot should never be eliminated (externally visible). */
|
|
71
|
+
function isProtectedSlot(s) {
|
|
72
|
+
const p = s.player;
|
|
73
|
+
if (p === '$ret' || p.startsWith('$ret_') || /^\$p\d+$/.test(p))
|
|
74
|
+
return true;
|
|
75
|
+
// Option slots: __opt_ prefix ensures they're always written to scoreboard
|
|
76
|
+
// even when the variable appears unused locally
|
|
77
|
+
if (p.includes('__opt_'))
|
|
78
|
+
return true;
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
function deadSlotElim(fn) {
|
|
82
|
+
// 1. Collect all read slots across the function
|
|
83
|
+
const readSet = new Set();
|
|
84
|
+
for (const instr of fn.instructions) {
|
|
85
|
+
for (const s of getReadSlots(instr)) {
|
|
86
|
+
readSet.add(slotKey(s));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// 2. Filter out pure writes to slots that are never read
|
|
90
|
+
const filtered = fn.instructions.filter(instr => {
|
|
91
|
+
const dst = getPureWriteDst(instr);
|
|
92
|
+
if (dst === null)
|
|
93
|
+
return true; // not a pure write → keep
|
|
94
|
+
if (isProtectedSlot(dst))
|
|
95
|
+
return true;
|
|
96
|
+
return readSet.has(slotKey(dst));
|
|
97
|
+
});
|
|
98
|
+
if (filtered.length === fn.instructions.length)
|
|
99
|
+
return fn;
|
|
100
|
+
return { ...fn, instructions: filtered };
|
|
101
|
+
}
|
|
102
|
+
function deadSlotElimModule(mod) {
|
|
103
|
+
// Collect all slots read across ALL functions (cross-function visibility)
|
|
104
|
+
const globalReadSet = new Set();
|
|
105
|
+
for (const fn of mod.functions) {
|
|
106
|
+
for (const instr of fn.instructions) {
|
|
107
|
+
for (const s of getReadSlots(instr)) {
|
|
108
|
+
globalReadSet.add(slotKey(s));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
let changed = false;
|
|
113
|
+
const functions = mod.functions.map(fn => {
|
|
114
|
+
const filtered = fn.instructions.filter(instr => {
|
|
115
|
+
const dst = getPureWriteDst(instr);
|
|
116
|
+
if (dst === null)
|
|
117
|
+
return true;
|
|
118
|
+
if (isProtectedSlot(dst))
|
|
119
|
+
return true;
|
|
120
|
+
return globalReadSet.has(slotKey(dst));
|
|
121
|
+
});
|
|
122
|
+
if (filtered.length !== fn.instructions.length)
|
|
123
|
+
changed = true;
|
|
124
|
+
if (filtered.length === fn.instructions.length)
|
|
125
|
+
return fn;
|
|
126
|
+
return { ...fn, instructions: filtered };
|
|
127
|
+
});
|
|
128
|
+
return changed ? { ...mod, functions } : mod;
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=dead_slot.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Execute-Store Peephole Pass — LIR optimization pass.
|
|
3
|
+
*
|
|
4
|
+
* Merges a `call_context` immediately followed by `score_set(dst, value)`
|
|
5
|
+
* into a single `store_cmd_to_score` instruction:
|
|
6
|
+
*
|
|
7
|
+
* execute [subcommands] run function ns:fn ← call_context
|
|
8
|
+
* scoreboard players set $result __ns N ← score_set
|
|
9
|
+
*
|
|
10
|
+
* becomes:
|
|
11
|
+
*
|
|
12
|
+
* execute store result score $result __ns [subcommands] run function ns:fn
|
|
13
|
+
*
|
|
14
|
+
* This saves one command when the caller only needs to know whether the
|
|
15
|
+
* execute chain ran (success = 1) or to capture the function's return value.
|
|
16
|
+
*
|
|
17
|
+
* Safety: only merges when the two instructions are immediately adjacent
|
|
18
|
+
* (no instructions between them).
|
|
19
|
+
*/
|
|
20
|
+
import type { LIRFunction } from '../../lir/types';
|
|
21
|
+
export declare function execStorePeephole(fn: LIRFunction): LIRFunction;
|