redscript-mc 1.2.25 → 1.2.27
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/README.md +67 -9
- package/README.zh.md +61 -4
- package/dist/__tests__/cli.test.js +1 -1
- package/dist/__tests__/codegen.test.js +12 -6
- package/dist/__tests__/e2e.test.js +6 -6
- package/dist/__tests__/lowering.test.js +8 -8
- package/dist/__tests__/optimizer.test.js +31 -0
- package/dist/__tests__/stdlib-advanced.test.d.ts +4 -0
- package/dist/__tests__/stdlib-advanced.test.js +378 -0
- package/dist/__tests__/stdlib-bigint.test.d.ts +7 -0
- package/dist/__tests__/stdlib-bigint.test.js +428 -0
- package/dist/__tests__/stdlib-math.test.d.ts +7 -0
- package/dist/__tests__/stdlib-math.test.js +352 -0
- package/dist/__tests__/stdlib-vec.test.d.ts +4 -0
- package/dist/__tests__/stdlib-vec.test.js +264 -0
- package/dist/ast/types.d.ts +17 -1
- package/dist/codegen/mcfunction/index.js +154 -18
- package/dist/codegen/var-allocator.d.ts +17 -0
- package/dist/codegen/var-allocator.js +26 -0
- package/dist/compile.d.ts +14 -0
- package/dist/compile.js +62 -5
- package/dist/data/arena/function/__load.mcfunction +6 -0
- package/dist/data/arena/function/__tick.mcfunction +2 -0
- package/dist/data/arena/function/announce_leaders/else_1.mcfunction +3 -0
- package/dist/data/arena/function/announce_leaders/foreach_0/merge_2.mcfunction +1 -0
- package/dist/data/arena/function/announce_leaders/foreach_0/then_0.mcfunction +3 -0
- package/dist/data/arena/function/announce_leaders/foreach_0.mcfunction +7 -0
- package/dist/data/arena/function/announce_leaders/foreach_1/merge_2.mcfunction +1 -0
- package/dist/data/arena/function/announce_leaders/foreach_1/then_0.mcfunction +4 -0
- package/dist/data/arena/function/announce_leaders/foreach_1.mcfunction +6 -0
- package/dist/data/arena/function/announce_leaders/merge_2.mcfunction +1 -0
- package/dist/data/arena/function/announce_leaders/then_0.mcfunction +4 -0
- package/dist/data/arena/function/announce_leaders.mcfunction +6 -0
- package/dist/data/arena/function/arena_tick/merge_2.mcfunction +1 -0
- package/dist/data/arena/function/arena_tick/then_0.mcfunction +4 -0
- package/dist/data/arena/function/arena_tick.mcfunction +11 -0
- package/dist/data/counter/function/__load.mcfunction +5 -0
- package/dist/data/counter/function/__tick.mcfunction +2 -0
- package/dist/data/counter/function/counter_tick/merge_2.mcfunction +1 -0
- package/dist/data/counter/function/counter_tick/then_0.mcfunction +3 -0
- package/dist/data/counter/function/counter_tick.mcfunction +11 -0
- package/dist/data/gcd2/function/__load.mcfunction +3 -0
- package/dist/data/gcd2/function/abs/merge_2.mcfunction +3 -0
- package/dist/data/gcd2/function/abs/then_0.mcfunction +5 -0
- package/dist/data/gcd2/function/abs.mcfunction +7 -0
- package/dist/data/gcd2/function/gcd/loop_body_1.mcfunction +7 -0
- package/dist/data/gcd2/function/gcd/loop_check_0.mcfunction +5 -0
- package/dist/data/gcd2/function/gcd/loop_exit_2.mcfunction +3 -0
- package/dist/data/gcd2/function/gcd.mcfunction +14 -0
- package/dist/data/gcd3/function/__load.mcfunction +3 -0
- package/dist/data/gcd3/function/abs/merge_2.mcfunction +3 -0
- package/dist/data/gcd3/function/abs/then_0.mcfunction +5 -0
- package/dist/data/gcd3/function/abs.mcfunction +7 -0
- package/dist/data/gcd3/function/gcd/loop_body_1.mcfunction +7 -0
- package/dist/data/gcd3/function/gcd/loop_check_0.mcfunction +5 -0
- package/dist/data/gcd3/function/gcd/loop_exit_2.mcfunction +3 -0
- package/dist/data/gcd3/function/gcd.mcfunction +14 -0
- package/dist/data/gcd3/function/test.mcfunction +7 -0
- package/dist/data/gcd3nm/function/__load.mcfunction +3 -0
- package/dist/data/gcd3nm/function/abs/merge_2.mcfunction +3 -0
- package/dist/data/gcd3nm/function/abs/then_0.mcfunction +5 -0
- package/dist/data/gcd3nm/function/abs.mcfunction +7 -0
- package/dist/data/gcd3nm/function/gcd/loop_body_1.mcfunction +7 -0
- package/dist/data/gcd3nm/function/gcd/loop_check_0.mcfunction +5 -0
- package/dist/data/gcd3nm/function/gcd/loop_exit_2.mcfunction +3 -0
- package/dist/data/gcd3nm/function/gcd.mcfunction +14 -0
- package/dist/data/gcd3nm/function/test.mcfunction +7 -0
- package/dist/data/gcd_test/function/__load.mcfunction +3 -0
- package/dist/data/gcd_test/function/abs/merge_2.mcfunction +3 -0
- package/dist/data/gcd_test/function/abs/then_0.mcfunction +5 -0
- package/dist/data/gcd_test/function/abs.mcfunction +7 -0
- package/dist/data/gcd_test/function/gcd/loop_body_1.mcfunction +7 -0
- package/dist/data/gcd_test/function/gcd/loop_check_0.mcfunction +5 -0
- package/dist/data/gcd_test/function/gcd/loop_exit_2.mcfunction +3 -0
- package/dist/data/gcd_test/function/gcd.mcfunction +14 -0
- package/dist/data/isqrttest/function/__load.mcfunction +6 -0
- package/dist/data/isqrttest/function/isqrt/loop_body_4.mcfunction +12 -0
- package/dist/data/isqrttest/function/isqrt/loop_check_3.mcfunction +5 -0
- package/dist/data/isqrttest/function/isqrt/loop_exit_5.mcfunction +3 -0
- package/dist/data/isqrttest/function/isqrt/merge_2.mcfunction +4 -0
- package/dist/data/isqrttest/function/isqrt/merge_8.mcfunction +6 -0
- package/dist/data/isqrttest/function/isqrt/then_0.mcfunction +3 -0
- package/dist/data/isqrttest/function/isqrt/then_6.mcfunction +3 -0
- package/dist/data/isqrttest/function/isqrt.mcfunction +7 -0
- package/dist/data/isqrttest/function/test.mcfunction +6 -0
- package/dist/data/mathtest/function/__load.mcfunction +3 -0
- package/dist/data/mathtest/function/abs/merge_2.mcfunction +3 -0
- package/dist/data/mathtest/function/abs/then_0.mcfunction +5 -0
- package/dist/data/mathtest/function/abs.mcfunction +6 -0
- package/dist/data/mathtest/function/test.mcfunction +5 -0
- package/dist/data/minecraft/tags/function/load.json +5 -0
- package/dist/data/minecraft/tags/function/tick.json +5 -0
- package/dist/data/mypack/function/__load.mcfunction +13 -0
- package/dist/data/mypack/function/_atan_init.mcfunction +2 -0
- package/dist/data/mypack/function/abs/merge_2.mcfunction +3 -0
- package/dist/data/mypack/function/abs/then_0.mcfunction +5 -0
- package/dist/data/mypack/function/abs.mcfunction +6 -0
- package/dist/data/mypack/function/atan2_fixed/__sgi_1.mcfunction +2 -0
- package/dist/data/mypack/function/atan2_fixed/else_34.mcfunction +3 -0
- package/dist/data/mypack/function/atan2_fixed/loop_body_31.mcfunction +19 -0
- package/dist/data/mypack/function/atan2_fixed/loop_check_30.mcfunction +5 -0
- package/dist/data/mypack/function/atan2_fixed/loop_exit_32.mcfunction +6 -0
- package/dist/data/mypack/function/atan2_fixed/merge_11.mcfunction +6 -0
- package/dist/data/mypack/function/atan2_fixed/merge_14.mcfunction +3 -0
- package/dist/data/mypack/function/atan2_fixed/merge_17.mcfunction +6 -0
- package/dist/data/mypack/function/atan2_fixed/merge_2.mcfunction +5 -0
- package/dist/data/mypack/function/atan2_fixed/merge_20.mcfunction +5 -0
- package/dist/data/mypack/function/atan2_fixed/merge_23.mcfunction +5 -0
- package/dist/data/mypack/function/atan2_fixed/merge_26.mcfunction +6 -0
- package/dist/data/mypack/function/atan2_fixed/merge_29.mcfunction +4 -0
- package/dist/data/mypack/function/atan2_fixed/merge_38.mcfunction +5 -0
- package/dist/data/mypack/function/atan2_fixed/merge_41.mcfunction +5 -0
- package/dist/data/mypack/function/atan2_fixed/merge_44.mcfunction +5 -0
- package/dist/data/mypack/function/atan2_fixed/merge_47.mcfunction +5 -0
- package/dist/data/mypack/function/atan2_fixed/merge_5.mcfunction +5 -0
- package/dist/data/mypack/function/atan2_fixed/merge_8.mcfunction +3 -0
- package/dist/data/mypack/function/atan2_fixed/then_0.mcfunction +5 -0
- package/dist/data/mypack/function/atan2_fixed/then_12.mcfunction +3 -0
- package/dist/data/mypack/function/atan2_fixed/then_15.mcfunction +5 -0
- package/dist/data/mypack/function/atan2_fixed/then_18.mcfunction +5 -0
- package/dist/data/mypack/function/atan2_fixed/then_21.mcfunction +3 -0
- package/dist/data/mypack/function/atan2_fixed/then_24.mcfunction +3 -0
- package/dist/data/mypack/function/atan2_fixed/then_27.mcfunction +6 -0
- package/dist/data/mypack/function/atan2_fixed/then_3.mcfunction +3 -0
- package/dist/data/mypack/function/atan2_fixed/then_33.mcfunction +5 -0
- package/dist/data/mypack/function/atan2_fixed/then_36.mcfunction +5 -0
- package/dist/data/mypack/function/atan2_fixed/then_39.mcfunction +5 -0
- package/dist/data/mypack/function/atan2_fixed/then_42.mcfunction +3 -0
- package/dist/data/mypack/function/atan2_fixed/then_45.mcfunction +5 -0
- package/dist/data/mypack/function/atan2_fixed/then_6.mcfunction +3 -0
- package/dist/data/mypack/function/atan2_fixed/then_9.mcfunction +5 -0
- package/dist/data/mypack/function/atan2_fixed.mcfunction +7 -0
- package/dist/data/mypack/function/my_game.mcfunction +10 -0
- package/dist/data/quiz/function/__load.mcfunction +16 -0
- package/dist/data/quiz/function/__tick.mcfunction +6 -0
- package/dist/data/quiz/function/__trigger_quiz_a_dispatch.mcfunction +4 -0
- package/dist/data/quiz/function/__trigger_quiz_b_dispatch.mcfunction +4 -0
- package/dist/data/quiz/function/__trigger_quiz_c_dispatch.mcfunction +4 -0
- package/dist/data/quiz/function/__trigger_quiz_start_dispatch.mcfunction +4 -0
- package/dist/data/quiz/function/answer_a.mcfunction +4 -0
- package/dist/data/quiz/function/answer_b.mcfunction +4 -0
- package/dist/data/quiz/function/answer_c.mcfunction +4 -0
- package/dist/data/quiz/function/ask_question/else_1.mcfunction +5 -0
- package/dist/data/quiz/function/ask_question/else_4.mcfunction +5 -0
- package/dist/data/quiz/function/ask_question/else_7.mcfunction +4 -0
- package/dist/data/quiz/function/ask_question/merge_2.mcfunction +1 -0
- package/dist/data/quiz/function/ask_question/merge_5.mcfunction +2 -0
- package/dist/data/quiz/function/ask_question/merge_8.mcfunction +2 -0
- package/dist/data/quiz/function/ask_question/then_0.mcfunction +4 -0
- package/dist/data/quiz/function/ask_question/then_3.mcfunction +4 -0
- package/dist/data/quiz/function/ask_question/then_6.mcfunction +4 -0
- package/dist/data/quiz/function/ask_question.mcfunction +7 -0
- package/dist/data/quiz/function/finish_quiz.mcfunction +6 -0
- package/dist/data/quiz/function/handle_answer/else_1.mcfunction +5 -0
- package/dist/data/quiz/function/handle_answer/else_10.mcfunction +3 -0
- package/dist/data/quiz/function/handle_answer/else_16.mcfunction +3 -0
- package/dist/data/quiz/function/handle_answer/else_4.mcfunction +3 -0
- package/dist/data/quiz/function/handle_answer/else_7.mcfunction +5 -0
- package/dist/data/quiz/function/handle_answer/merge_11.mcfunction +2 -0
- package/dist/data/quiz/function/handle_answer/merge_14.mcfunction +2 -0
- package/dist/data/quiz/function/handle_answer/merge_17.mcfunction +2 -0
- package/dist/data/quiz/function/handle_answer/merge_2.mcfunction +8 -0
- package/dist/data/quiz/function/handle_answer/merge_5.mcfunction +2 -0
- package/dist/data/quiz/function/handle_answer/merge_8.mcfunction +2 -0
- package/dist/data/quiz/function/handle_answer/then_0.mcfunction +5 -0
- package/dist/data/quiz/function/handle_answer/then_12.mcfunction +5 -0
- package/dist/data/quiz/function/handle_answer/then_15.mcfunction +6 -0
- package/dist/data/quiz/function/handle_answer/then_3.mcfunction +6 -0
- package/dist/data/quiz/function/handle_answer/then_6.mcfunction +5 -0
- package/dist/data/quiz/function/handle_answer/then_9.mcfunction +6 -0
- package/dist/data/quiz/function/handle_answer.mcfunction +11 -0
- package/dist/data/quiz/function/start_quiz.mcfunction +5 -0
- package/dist/data/reqtest/function/__load.mcfunction +4 -0
- package/dist/data/reqtest/function/_table_init.mcfunction +2 -0
- package/dist/data/reqtest/function/no_trig.mcfunction +3 -0
- package/dist/data/reqtest/function/use_table.mcfunction +4 -0
- package/dist/data/reqtest2/function/__load.mcfunction +3 -0
- package/dist/data/reqtest2/function/no_trig.mcfunction +3 -0
- package/dist/data/runtime/function/__load.mcfunction +5 -0
- package/dist/data/runtime/function/__tick.mcfunction +2 -0
- package/dist/data/runtime/function/counter_tick/then_0.mcfunction +3 -0
- package/dist/data/runtime/function/counter_tick.mcfunction +13 -0
- package/dist/data/shop/function/__load.mcfunction +7 -0
- package/dist/data/shop/function/__tick.mcfunction +3 -0
- package/dist/data/shop/function/__trigger_shop_buy_dispatch.mcfunction +4 -0
- package/dist/data/shop/function/complete_purchase/else_1.mcfunction +5 -0
- package/dist/data/shop/function/complete_purchase/else_4.mcfunction +5 -0
- package/dist/data/shop/function/complete_purchase/else_7.mcfunction +3 -0
- package/dist/data/shop/function/complete_purchase/merge_2.mcfunction +2 -0
- package/dist/data/shop/function/complete_purchase/merge_5.mcfunction +2 -0
- package/dist/data/shop/function/complete_purchase/merge_8.mcfunction +2 -0
- package/dist/data/shop/function/complete_purchase/then_0.mcfunction +4 -0
- package/dist/data/shop/function/complete_purchase/then_3.mcfunction +4 -0
- package/dist/data/shop/function/complete_purchase/then_6.mcfunction +4 -0
- package/dist/data/shop/function/complete_purchase.mcfunction +7 -0
- package/dist/data/shop/function/handle_shop_trigger.mcfunction +3 -0
- package/dist/data/swap_test/function/__load.mcfunction +3 -0
- package/dist/data/swap_test/function/gcd_old/loop_body_1.mcfunction +7 -0
- package/dist/data/swap_test/function/gcd_old/loop_check_0.mcfunction +5 -0
- package/dist/data/swap_test/function/gcd_old/loop_exit_2.mcfunction +3 -0
- package/dist/data/swap_test/function/gcd_old.mcfunction +8 -0
- package/dist/data/turret/function/__load.mcfunction +5 -0
- package/dist/data/turret/function/__tick.mcfunction +4 -0
- package/dist/data/turret/function/__trigger_deploy_turret_dispatch.mcfunction +4 -0
- package/dist/data/turret/function/deploy_turret.mcfunction +8 -0
- package/dist/data/turret/function/turret_tick/at_1.mcfunction +2 -0
- package/dist/data/turret/function/turret_tick/foreach_0.mcfunction +2 -0
- package/dist/data/turret/function/turret_tick/foreach_2.mcfunction +2 -0
- package/dist/data/turret/function/turret_tick/tick_body.mcfunction +3 -0
- package/dist/data/turret/function/turret_tick/tick_skip.mcfunction +1 -0
- package/dist/data/turret/function/turret_tick.mcfunction +5 -0
- package/dist/gcd2.map.json +15 -0
- package/dist/gcd3.map.json +17 -0
- package/dist/gcd_test.map.json +15 -0
- package/dist/index.js +20 -1
- package/dist/ir/types.d.ts +4 -0
- package/dist/isqrttest.map.json +15 -0
- package/dist/lexer/index.d.ts +1 -1
- package/dist/lexer/index.js +1 -0
- package/dist/lowering/index.d.ts +5 -0
- package/dist/lowering/index.js +154 -14
- package/dist/mathtest.map.json +6 -0
- package/dist/mypack.map.json +27 -0
- package/dist/optimizer/dce.js +21 -5
- package/dist/optimizer/passes.js +18 -6
- package/dist/optimizer/structure.js +7 -0
- package/dist/pack.mcmeta +6 -0
- package/dist/parser/index.d.ts +5 -0
- package/dist/parser/index.js +43 -2
- package/dist/reqtest.map.json +4 -0
- package/dist/reqtest2.map.json +4 -0
- package/dist/runtime/index.d.ts +6 -0
- package/dist/runtime/index.js +130 -9
- package/dist/runtime.map.json +7 -0
- package/dist/swap_test.map.json +14 -0
- package/editors/vscode/package-lock.json +3 -3
- package/editors/vscode/package.json +1 -1
- package/examples/showcase.mcrs +505 -0
- package/package.json +1 -1
- package/src/__tests__/cli.test.ts +1 -1
- package/src/__tests__/codegen.test.ts +12 -6
- package/src/__tests__/e2e.test.ts +6 -6
- package/src/__tests__/lowering.test.ts +8 -8
- package/src/__tests__/optimizer.test.ts +33 -0
- package/src/__tests__/stdlib-advanced.test.ts +379 -0
- package/src/__tests__/stdlib-bigint.test.ts +427 -0
- package/src/__tests__/stdlib-math.test.ts +374 -0
- package/src/__tests__/stdlib-vec.test.ts +259 -0
- package/src/ast/types.ts +11 -1
- package/src/codegen/mcfunction/index.ts +143 -19
- package/src/codegen/var-allocator.ts +29 -0
- package/src/compile.ts +72 -5
- package/src/index.ts +21 -1
- package/src/ir/types.ts +2 -0
- package/src/lexer/index.ts +2 -1
- package/src/lowering/index.ts +171 -14
- package/src/optimizer/dce.ts +22 -5
- package/src/optimizer/passes.ts +18 -5
- package/src/optimizer/structure.ts +6 -1
- package/src/parser/index.ts +47 -2
- package/src/runtime/index.ts +130 -10
- package/src/stdlib/advanced.mcrs +330 -0
- package/src/stdlib/bigint.mcrs +205 -0
- package/src/stdlib/math.mcrs +274 -21
- package/src/stdlib/vec.mcrs +246 -0
|
@@ -32,6 +32,8 @@ function operandToScore(op, alloc) {
|
|
|
32
32
|
return `${alloc.alloc(op.name)} ${OBJ}`;
|
|
33
33
|
if (op.kind === 'const')
|
|
34
34
|
return `${alloc.constant(op.value)} ${OBJ}`;
|
|
35
|
+
if (op.kind === 'param')
|
|
36
|
+
return `${alloc.internal(`p${op.index}`)} ${OBJ}`;
|
|
35
37
|
throw new Error(`Cannot convert storage operand to score: ${op.path}`);
|
|
36
38
|
}
|
|
37
39
|
// Collect all constants used in a function for pre-setup
|
|
@@ -79,6 +81,9 @@ function emitInstr(instr, ns, alloc) {
|
|
|
79
81
|
else if (src.kind === 'var') {
|
|
80
82
|
lines.push(`scoreboard players operation ${dst} ${OBJ} = ${alloc.alloc(src.name)} ${OBJ}`);
|
|
81
83
|
}
|
|
84
|
+
else if (src.kind === 'param') {
|
|
85
|
+
lines.push(`scoreboard players operation ${dst} ${OBJ} = ${alloc.internal(`p${src.index}`)} ${OBJ}`);
|
|
86
|
+
}
|
|
82
87
|
else {
|
|
83
88
|
lines.push(`execute store result score ${dst} ${OBJ} run data get storage ${src.path}`);
|
|
84
89
|
}
|
|
@@ -121,21 +126,42 @@ function emitInstr(instr, ns, alloc) {
|
|
|
121
126
|
break;
|
|
122
127
|
}
|
|
123
128
|
case 'call': {
|
|
124
|
-
// Push args
|
|
129
|
+
// Push args into the internal parameter slots ($p0, $p1, ...).
|
|
130
|
+
// We emit the copy commands directly (not via emitInstr/alloc.alloc) to
|
|
131
|
+
// ensure the destination resolves to alloc.internal('p{i}') rather than
|
|
132
|
+
// alloc.alloc('p{i}') which would create a *different* user-var slot.
|
|
125
133
|
for (let i = 0; i < instr.args.length; i++) {
|
|
126
|
-
const
|
|
127
|
-
|
|
134
|
+
const paramSlot = alloc.internal(`p${i}`);
|
|
135
|
+
const arg = instr.args[i];
|
|
136
|
+
if (arg.kind === 'const') {
|
|
137
|
+
lines.push(`scoreboard players set ${paramSlot} ${OBJ} ${arg.value}`);
|
|
138
|
+
}
|
|
139
|
+
else if (arg.kind === 'var') {
|
|
140
|
+
lines.push(`scoreboard players operation ${paramSlot} ${OBJ} = ${alloc.alloc(arg.name)} ${OBJ}`);
|
|
141
|
+
}
|
|
142
|
+
else if (arg.kind === 'param') {
|
|
143
|
+
lines.push(`scoreboard players operation ${paramSlot} ${OBJ} = ${alloc.internal(`p${arg.index}`)} ${OBJ}`);
|
|
144
|
+
}
|
|
145
|
+
// storage args are rare for call sites; fall through to no-op
|
|
128
146
|
}
|
|
129
147
|
lines.push(`function ${ns}:${instr.fn}`);
|
|
130
148
|
if (instr.dst) {
|
|
131
|
-
const
|
|
132
|
-
lines.push(`scoreboard players operation ${alloc.alloc(instr.dst)} ${OBJ} = ${
|
|
149
|
+
const retSlot = alloc.internal('ret');
|
|
150
|
+
lines.push(`scoreboard players operation ${alloc.alloc(instr.dst)} ${OBJ} = ${retSlot} ${OBJ}`);
|
|
133
151
|
}
|
|
134
152
|
break;
|
|
135
153
|
}
|
|
136
|
-
case 'raw':
|
|
137
|
-
|
|
154
|
+
case 'raw': {
|
|
155
|
+
// resolveRaw rewrites $var tokens that are registered in the allocator
|
|
156
|
+
// so that mangle=true mode produces correct mangled names instead of
|
|
157
|
+
// the raw IR names embedded by the lowering phase.
|
|
158
|
+
// \x01 is a sentinel for the MC macro line-start '$' (used by
|
|
159
|
+
// storage_get_int sub-functions). Replace it last, after resolveRaw,
|
|
160
|
+
// so '$execute' is never treated as a variable reference.
|
|
161
|
+
const rawResolved = alloc.resolveRaw(instr.cmd).replace(/^\x01/, '$');
|
|
162
|
+
lines.push(rawResolved);
|
|
138
163
|
break;
|
|
164
|
+
}
|
|
139
165
|
}
|
|
140
166
|
return lines;
|
|
141
167
|
}
|
|
@@ -157,17 +183,32 @@ function emitTerm(term, ns, fnName, alloc) {
|
|
|
157
183
|
lines.push(`execute if score ${alloc.alloc(term.cond)} ${OBJ} matches 1.. run function ${ns}:${fnName}/${term.else_}`);
|
|
158
184
|
break;
|
|
159
185
|
case 'return': {
|
|
160
|
-
|
|
186
|
+
// Emit the copy to the shared return slot directly — do NOT go through
|
|
187
|
+
// emitInstr/alloc.alloc(retSlot) which would allocate a *user* var slot
|
|
188
|
+
// (different from the internal slot) and break mangle mode.
|
|
189
|
+
const retSlot = alloc.internal('ret');
|
|
161
190
|
if (term.value) {
|
|
162
|
-
|
|
191
|
+
if (term.value.kind === 'const') {
|
|
192
|
+
lines.push(`scoreboard players set ${retSlot} ${OBJ} ${term.value.value}`);
|
|
193
|
+
}
|
|
194
|
+
else if (term.value.kind === 'var') {
|
|
195
|
+
lines.push(`scoreboard players operation ${retSlot} ${OBJ} = ${alloc.alloc(term.value.name)} ${OBJ}`);
|
|
196
|
+
}
|
|
197
|
+
else if (term.value.kind === 'param') {
|
|
198
|
+
lines.push(`scoreboard players operation ${retSlot} ${OBJ} = ${alloc.internal(`p${term.value.index}`)} ${OBJ}`);
|
|
199
|
+
}
|
|
163
200
|
}
|
|
164
|
-
//
|
|
201
|
+
// MC 1.20+: use `return` to propagate the value back to the caller's
|
|
202
|
+
// `execute store result … run function …` without an extra scoreboard read.
|
|
165
203
|
if (term.value?.kind === 'const') {
|
|
166
204
|
lines.push(`return ${term.value.value}`);
|
|
167
205
|
}
|
|
168
206
|
else if (term.value?.kind === 'var') {
|
|
169
207
|
lines.push(`return run scoreboard players get ${alloc.alloc(term.value.name)} ${OBJ}`);
|
|
170
208
|
}
|
|
209
|
+
else if (term.value?.kind === 'param') {
|
|
210
|
+
lines.push(`return run scoreboard players get ${alloc.internal(`p${term.value.index}`)} ${OBJ}`);
|
|
211
|
+
}
|
|
171
212
|
break;
|
|
172
213
|
}
|
|
173
214
|
case 'tick_yield':
|
|
@@ -237,6 +278,62 @@ function countMcfunctionCommands(files) {
|
|
|
237
278
|
.length;
|
|
238
279
|
}, 0);
|
|
239
280
|
}
|
|
281
|
+
// ---------------------------------------------------------------------------
|
|
282
|
+
// Pre-allocation helpers for the two-pass mangle strategy
|
|
283
|
+
// ---------------------------------------------------------------------------
|
|
284
|
+
/** Register every variable referenced in an instruction with the allocator. */
|
|
285
|
+
function preAllocInstr(instr, alloc) {
|
|
286
|
+
switch (instr.op) {
|
|
287
|
+
case 'assign':
|
|
288
|
+
alloc.alloc(instr.dst);
|
|
289
|
+
if (instr.src.kind === 'var')
|
|
290
|
+
alloc.alloc(instr.src.name);
|
|
291
|
+
break;
|
|
292
|
+
case 'binop':
|
|
293
|
+
alloc.alloc(instr.dst);
|
|
294
|
+
if (instr.lhs.kind === 'var')
|
|
295
|
+
alloc.alloc(instr.lhs.name);
|
|
296
|
+
if (instr.rhs.kind === 'var')
|
|
297
|
+
alloc.alloc(instr.rhs.name);
|
|
298
|
+
break;
|
|
299
|
+
case 'cmp':
|
|
300
|
+
alloc.alloc(instr.dst);
|
|
301
|
+
if (instr.lhs.kind === 'var')
|
|
302
|
+
alloc.alloc(instr.lhs.name);
|
|
303
|
+
if (instr.rhs.kind === 'var')
|
|
304
|
+
alloc.alloc(instr.rhs.name);
|
|
305
|
+
break;
|
|
306
|
+
case 'call':
|
|
307
|
+
for (const arg of instr.args) {
|
|
308
|
+
if (arg.kind === 'var')
|
|
309
|
+
alloc.alloc(arg.name);
|
|
310
|
+
}
|
|
311
|
+
if (instr.dst)
|
|
312
|
+
alloc.alloc(instr.dst);
|
|
313
|
+
break;
|
|
314
|
+
case 'raw':
|
|
315
|
+
// Scan for $varname tokens and pre-register each one
|
|
316
|
+
;
|
|
317
|
+
instr.cmd.replace(/\$[A-Za-z_][A-Za-z0-9_]*/g, (tok) => {
|
|
318
|
+
alloc.alloc(tok);
|
|
319
|
+
return tok;
|
|
320
|
+
});
|
|
321
|
+
break;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
/** Register every variable referenced in a terminator with the allocator. */
|
|
325
|
+
function preAllocTerm(term, alloc) {
|
|
326
|
+
switch (term.op) {
|
|
327
|
+
case 'jump_if':
|
|
328
|
+
case 'jump_unless':
|
|
329
|
+
alloc.alloc(term.cond);
|
|
330
|
+
break;
|
|
331
|
+
case 'return':
|
|
332
|
+
if (term.value?.kind === 'var')
|
|
333
|
+
alloc.alloc(term.value.name);
|
|
334
|
+
break;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
240
337
|
function generateDatapackWithStats(module, options = {}) {
|
|
241
338
|
const { optimizeCommands = true, mangle = false } = options;
|
|
242
339
|
const alloc = new var_allocator_1.VarAllocator(mangle);
|
|
@@ -316,6 +413,39 @@ function generateDatapackWithStats(module, options = {}) {
|
|
|
316
413
|
if (allConsts.size > 0) {
|
|
317
414
|
loadLines.push(...Array.from(allConsts).sort((a, b) => a - b).map(value => `scoreboard players set ${alloc.constant(value)} ${OBJ} ${value}`));
|
|
318
415
|
}
|
|
416
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
417
|
+
// Pre-allocation pass (mangle mode only)
|
|
418
|
+
//
|
|
419
|
+
// When mangle=true, the codegen assigns sequential names ($a, $b, …) the
|
|
420
|
+
// FIRST time alloc.alloc() is called for a given variable. Raw IR commands
|
|
421
|
+
// embed variable names (e.g. "$_0") as plain strings; resolveRaw() can only
|
|
422
|
+
// substitute them if the name was already registered in the allocator.
|
|
423
|
+
//
|
|
424
|
+
// Problem: a freshTemp ($\_0) used in a `raw` instruction and then in the
|
|
425
|
+
// immediately following `assign` gets registered by the `assign` AFTER the
|
|
426
|
+
// `raw` has already been emitted — so resolveRaw sees an unknown name and
|
|
427
|
+
// passes it through verbatim ($\_0), while the assign emits a different
|
|
428
|
+
// mangled slot ($e). The two slots never meet and the value is lost.
|
|
429
|
+
//
|
|
430
|
+
// Fix: walk every instruction (and terminator) of every function in order
|
|
431
|
+
// and call alloc.alloc() for each variable reference. This registers all
|
|
432
|
+
// names — with the same sequential order the main emit pass will encounter
|
|
433
|
+
// them — so that resolveRaw() can always find the correct mangled name.
|
|
434
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
435
|
+
if (mangle) {
|
|
436
|
+
for (const fn of module.functions) {
|
|
437
|
+
// Register internals used by the calling convention
|
|
438
|
+
for (let i = 0; i < fn.params.length; i++)
|
|
439
|
+
alloc.internal(`p${i}`);
|
|
440
|
+
alloc.internal('ret');
|
|
441
|
+
for (const block of fn.blocks) {
|
|
442
|
+
for (const instr of block.instrs) {
|
|
443
|
+
preAllocInstr(instr, alloc);
|
|
444
|
+
}
|
|
445
|
+
preAllocTerm(block.term, alloc);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
319
449
|
// Generate each function
|
|
320
450
|
for (const fn of module.functions) {
|
|
321
451
|
// Entry block → <fn_name>.mcfunction
|
|
@@ -323,12 +453,9 @@ function generateDatapackWithStats(module, options = {}) {
|
|
|
323
453
|
for (let i = 0; i < fn.blocks.length; i++) {
|
|
324
454
|
const block = fn.blocks[i];
|
|
325
455
|
const lines = [`# block: ${block.label}`];
|
|
326
|
-
// Param setup
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
lines.push(`scoreboard players operation ${alloc.alloc(fn.params[j])} ${OBJ} = ${alloc.internal(`p${j}`)} ${OBJ}`);
|
|
330
|
-
}
|
|
331
|
-
}
|
|
456
|
+
// Param setup is now handled by the lowering IR itself via { kind: 'param' }
|
|
457
|
+
// operands, so we no longer need a separate codegen param-copy loop here.
|
|
458
|
+
// (Removing it prevents the double-assignment that caused mangle-mode collisions.)
|
|
332
459
|
for (const instr of block.instrs) {
|
|
333
460
|
lines.push(...emitInstr(instr, ns, alloc));
|
|
334
461
|
}
|
|
@@ -344,11 +471,20 @@ function generateDatapackWithStats(module, options = {}) {
|
|
|
344
471
|
files.push({ path: filePath, content: lines.join('\n') });
|
|
345
472
|
}
|
|
346
473
|
}
|
|
347
|
-
// Call @load functions from __load
|
|
474
|
+
// Call @load functions and @requires-referenced load helpers from __load.
|
|
475
|
+
// We collect them in a set to deduplicate (multiple fns might @requires the same dep).
|
|
476
|
+
const loadCalls = new Set();
|
|
348
477
|
for (const fn of module.functions) {
|
|
349
478
|
if (fn.isLoadInit) {
|
|
350
|
-
|
|
479
|
+
loadCalls.add(fn.name);
|
|
351
480
|
}
|
|
481
|
+
// @requires: if this fn is compiled in, its required load-helpers must also run
|
|
482
|
+
for (const dep of fn.requiredLoads ?? []) {
|
|
483
|
+
loadCalls.add(dep);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
for (const name of loadCalls) {
|
|
487
|
+
loadLines.push(`function ${ns}:${name}`);
|
|
352
488
|
}
|
|
353
489
|
// Write __load.mcfunction
|
|
354
490
|
files.push({
|
|
@@ -15,6 +15,23 @@ export declare class VarAllocator {
|
|
|
15
15
|
alloc(originalName: string): string;
|
|
16
16
|
/** Allocate a name for a constant value (content-addressed). */
|
|
17
17
|
constant(value: number): string;
|
|
18
|
+
/**
|
|
19
|
+
* Look up the allocated name for a raw scoreboard fake-player name such as
|
|
20
|
+
* "$_2", "$x", "$p0", or "$ret". Returns the mangled name when mangle=true,
|
|
21
|
+
* or the original name when mangle=false or the name is not yet known.
|
|
22
|
+
*
|
|
23
|
+
* Unlike alloc/internal/constant this does NOT create a new slot — it only
|
|
24
|
+
* resolves names that were already registered. Used by the codegen to
|
|
25
|
+
* rewrite variable references inside `raw` IR instructions.
|
|
26
|
+
*/
|
|
27
|
+
resolve(rawName: string): string;
|
|
28
|
+
/**
|
|
29
|
+
* Rewrite all $varname tokens in a raw mcfunction command string so that
|
|
30
|
+
* IR variable names are replaced by their allocated (possibly mangled) names.
|
|
31
|
+
* Tokens that are not registered in the allocator are left untouched (they
|
|
32
|
+
* are literal scoreboard fake-player names like "out" or "#rs").
|
|
33
|
+
*/
|
|
34
|
+
resolveRaw(cmd: string): string;
|
|
18
35
|
/** Allocate a name for a compiler internal (e.g. "ret", "p0"). */
|
|
19
36
|
internal(suffix: string): string;
|
|
20
37
|
/** Generate the next sequential name: a, b, ..., z, aa, ab, ..., az, ba, ... */
|
|
@@ -34,6 +34,32 @@ class VarAllocator {
|
|
|
34
34
|
this.constCache.set(value, name);
|
|
35
35
|
return name;
|
|
36
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Look up the allocated name for a raw scoreboard fake-player name such as
|
|
39
|
+
* "$_2", "$x", "$p0", or "$ret". Returns the mangled name when mangle=true,
|
|
40
|
+
* or the original name when mangle=false or the name is not yet known.
|
|
41
|
+
*
|
|
42
|
+
* Unlike alloc/internal/constant this does NOT create a new slot — it only
|
|
43
|
+
* resolves names that were already registered. Used by the codegen to
|
|
44
|
+
* rewrite variable references inside `raw` IR instructions.
|
|
45
|
+
*/
|
|
46
|
+
resolve(rawName) {
|
|
47
|
+
const clean = rawName.startsWith('$') ? rawName.slice(1) : rawName;
|
|
48
|
+
// Check every cache in priority order: vars, internals, consts
|
|
49
|
+
return (this.varCache.get(clean) ??
|
|
50
|
+
this.internalCache.get(clean) ??
|
|
51
|
+
rawName // not registered → return as-is (literal fake player, not a var)
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Rewrite all $varname tokens in a raw mcfunction command string so that
|
|
56
|
+
* IR variable names are replaced by their allocated (possibly mangled) names.
|
|
57
|
+
* Tokens that are not registered in the allocator are left untouched (they
|
|
58
|
+
* are literal scoreboard fake-player names like "out" or "#rs").
|
|
59
|
+
*/
|
|
60
|
+
resolveRaw(cmd) {
|
|
61
|
+
return cmd.replace(/\$[A-Za-z_][A-Za-z0-9_]*/g, (tok) => this.resolve(tok));
|
|
62
|
+
}
|
|
37
63
|
/** Allocate a name for a compiler internal (e.g. "ret", "p0"). */
|
|
38
64
|
internal(suffix) {
|
|
39
65
|
const cached = this.internalCache.get(suffix);
|
package/dist/compile.d.ts
CHANGED
|
@@ -12,6 +12,13 @@ export interface CompileOptions {
|
|
|
12
12
|
filePath?: string;
|
|
13
13
|
optimize?: boolean;
|
|
14
14
|
dce?: boolean;
|
|
15
|
+
mangle?: boolean;
|
|
16
|
+
/** Additional source files that should be treated as *library* code.
|
|
17
|
+
* Functions in these files are DCE-eligible: they are only compiled into
|
|
18
|
+
* the datapack when actually called from user code. Each string is parsed
|
|
19
|
+
* independently (as if it had `module library;` at the top), so library
|
|
20
|
+
* mode never bleeds into the main `source`. */
|
|
21
|
+
librarySources?: string[];
|
|
15
22
|
}
|
|
16
23
|
export interface CompileResult {
|
|
17
24
|
success: boolean;
|
|
@@ -29,6 +36,13 @@ export interface SourceRange {
|
|
|
29
36
|
export interface PreprocessedSource {
|
|
30
37
|
source: string;
|
|
31
38
|
ranges: SourceRange[];
|
|
39
|
+
/** Imported files that declared `module library;` — parsed separately
|
|
40
|
+
* in library mode so their functions are DCE-eligible. Never concatenated
|
|
41
|
+
* into `source`. */
|
|
42
|
+
libraryImports?: Array<{
|
|
43
|
+
source: string;
|
|
44
|
+
filePath: string;
|
|
45
|
+
}>;
|
|
32
46
|
}
|
|
33
47
|
/**
|
|
34
48
|
* Resolve a combined-source line number back to the original file and line.
|
package/dist/compile.js
CHANGED
|
@@ -66,6 +66,17 @@ function resolveSourceLine(combinedLine, ranges, fallbackFile) {
|
|
|
66
66
|
return { filePath: fallbackFile, line: combinedLine };
|
|
67
67
|
}
|
|
68
68
|
const IMPORT_RE = /^\s*import\s+"([^"]+)"\s*;?\s*$/;
|
|
69
|
+
/** Returns true if the source file declares `module library;` at its top
|
|
70
|
+
* (before any non-comment/non-blank lines). */
|
|
71
|
+
function isLibrarySource(source) {
|
|
72
|
+
for (const line of source.split('\n')) {
|
|
73
|
+
const trimmed = line.trim();
|
|
74
|
+
if (!trimmed || trimmed.startsWith('//'))
|
|
75
|
+
continue;
|
|
76
|
+
return /^module\s+library\s*;/.test(trimmed);
|
|
77
|
+
}
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
69
80
|
function countLines(source) {
|
|
70
81
|
return source === '' ? 0 : source.split('\n').length;
|
|
71
82
|
}
|
|
@@ -84,6 +95,8 @@ function preprocessSourceWithMetadata(source, options = {}) {
|
|
|
84
95
|
}
|
|
85
96
|
const lines = source.split('\n');
|
|
86
97
|
const imports = [];
|
|
98
|
+
/** Library imports: `module library;` files routed here instead of concatenated. */
|
|
99
|
+
const libraryImports = [];
|
|
87
100
|
const bodyLines = [];
|
|
88
101
|
let parsingHeader = true;
|
|
89
102
|
for (let i = 0; i < lines.length; i++) {
|
|
@@ -104,7 +117,18 @@ function preprocessSourceWithMetadata(source, options = {}) {
|
|
|
104
117
|
catch {
|
|
105
118
|
throw new diagnostics_1.DiagnosticError('ParseError', `Cannot import '${match[1]}'`, { file: filePath, line: i + 1, col: 1 }, lines);
|
|
106
119
|
}
|
|
107
|
-
|
|
120
|
+
if (isLibrarySource(importedSource)) {
|
|
121
|
+
// Library file: parse separately so its functions are DCE-eligible.
|
|
122
|
+
// Also collect any transitive library imports inside it.
|
|
123
|
+
const nested = preprocessSourceWithMetadata(importedSource, { filePath: importPath, seen });
|
|
124
|
+
libraryImports.push({ source: importedSource, filePath: importPath });
|
|
125
|
+
// Propagate transitive library imports (e.g. math.mcrs imports vec.mcrs)
|
|
126
|
+
if (nested.libraryImports)
|
|
127
|
+
libraryImports.push(...nested.libraryImports);
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
imports.push(preprocessSourceWithMetadata(importedSource, { filePath: importPath, seen }));
|
|
131
|
+
}
|
|
108
132
|
}
|
|
109
133
|
continue;
|
|
110
134
|
}
|
|
@@ -131,7 +155,11 @@ function preprocessSourceWithMetadata(source, options = {}) {
|
|
|
131
155
|
filePath: path.resolve(filePath),
|
|
132
156
|
});
|
|
133
157
|
}
|
|
134
|
-
return {
|
|
158
|
+
return {
|
|
159
|
+
source: combined,
|
|
160
|
+
ranges,
|
|
161
|
+
libraryImports: libraryImports.length > 0 ? libraryImports : undefined,
|
|
162
|
+
};
|
|
135
163
|
}
|
|
136
164
|
function preprocessSource(source, options = {}) {
|
|
137
165
|
return preprocessSourceWithMetadata(source, options).source;
|
|
@@ -149,8 +177,36 @@ function compile(source, options = {}) {
|
|
|
149
177
|
sourceLines = preprocessedSource.split('\n');
|
|
150
178
|
// Lexing
|
|
151
179
|
const tokens = new lexer_1.Lexer(preprocessedSource, filePath).tokenize();
|
|
152
|
-
// Parsing
|
|
180
|
+
// Parsing — user source
|
|
153
181
|
const parsedAst = new parser_1.Parser(tokens, preprocessedSource, filePath).parse(namespace);
|
|
182
|
+
// Collect all library sources: explicit `librarySources` option +
|
|
183
|
+
// auto-detected imports (files with `module library;` pulled out by the
|
|
184
|
+
// preprocessor rather than concatenated).
|
|
185
|
+
const allLibrarySources = [];
|
|
186
|
+
for (const libSrc of options.librarySources ?? []) {
|
|
187
|
+
allLibrarySources.push({ src: libSrc });
|
|
188
|
+
}
|
|
189
|
+
for (const li of preprocessed.libraryImports ?? []) {
|
|
190
|
+
allLibrarySources.push({ src: li.source, fp: li.filePath });
|
|
191
|
+
}
|
|
192
|
+
// Parse library sources independently (fresh Parser per source) so that
|
|
193
|
+
// `inLibraryMode` never bleeds into user code. All resulting functions get
|
|
194
|
+
// isLibraryFn=true (either via `module library;` in the source, or forced below).
|
|
195
|
+
for (const { src, fp } of allLibrarySources) {
|
|
196
|
+
const libPreprocessed = preprocessSourceWithMetadata(src, fp ? { filePath: fp } : {});
|
|
197
|
+
const libTokens = new lexer_1.Lexer(libPreprocessed.source, fp).tokenize();
|
|
198
|
+
const libAst = new parser_1.Parser(libTokens, libPreprocessed.source, fp).parse(namespace);
|
|
199
|
+
// Force all functions to library mode (even if source lacks `module library;`)
|
|
200
|
+
for (const fn of libAst.declarations)
|
|
201
|
+
fn.isLibraryFn = true;
|
|
202
|
+
// Merge into main AST
|
|
203
|
+
parsedAst.declarations.push(...libAst.declarations);
|
|
204
|
+
parsedAst.structs.push(...libAst.structs);
|
|
205
|
+
parsedAst.implBlocks.push(...libAst.implBlocks);
|
|
206
|
+
parsedAst.enums.push(...libAst.enums);
|
|
207
|
+
parsedAst.consts.push(...libAst.consts);
|
|
208
|
+
parsedAst.globals.push(...libAst.globals);
|
|
209
|
+
}
|
|
154
210
|
const dceResult = shouldRunDce ? (0, dce_1.eliminateDeadCode)(parsedAst) : { program: parsedAst, warnings: [] };
|
|
155
211
|
const ast = dceResult.program;
|
|
156
212
|
// Lowering
|
|
@@ -159,8 +215,9 @@ function compile(source, options = {}) {
|
|
|
159
215
|
const optimized = shouldOptimize
|
|
160
216
|
? { ...ir, functions: ir.functions.map(fn => (0, passes_1.optimize)(fn)) }
|
|
161
217
|
: ir;
|
|
162
|
-
// Code generation
|
|
163
|
-
|
|
218
|
+
// Code generation — mangle=true by default to prevent cross-function
|
|
219
|
+
// scoreboard variable collisions in the global MC scoreboard namespace.
|
|
220
|
+
const generated = (0, mcfunction_1.generateDatapackWithStats)(optimized, { mangle: options.mangle ?? true });
|
|
164
221
|
return {
|
|
165
222
|
success: true,
|
|
166
223
|
files: [...generated.files, ...generated.advancements],
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# block: merge_2
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# block: entry
|
|
2
|
+
execute store result score $t0 rs run scoreboard players get @s kills
|
|
3
|
+
scoreboard players operation $kills rs = $t0 rs
|
|
4
|
+
scoreboard players set $t1 rs 0
|
|
5
|
+
execute if score $t0 rs > $top_kills rs run scoreboard players set $t1 rs 1
|
|
6
|
+
execute if score $t1 rs matches 1.. run function arena:announce_leaders/foreach_0/then_0
|
|
7
|
+
execute if score $t1 rs matches ..0 run function arena:announce_leaders/foreach_0/merge_2
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# block: merge_2
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# block: entry
|
|
2
|
+
execute store result score $t0 rs run scoreboard players get @s kills
|
|
3
|
+
scoreboard players set $t1 rs 0
|
|
4
|
+
execute if score $t0 rs = $top_kills rs run scoreboard players set $t1 rs 1
|
|
5
|
+
execute if score $t1 rs matches 1.. run function arena:announce_leaders/foreach_1/then_0
|
|
6
|
+
execute if score $t1 rs matches ..0 run function arena:announce_leaders/foreach_1/merge_2
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# block: merge_2
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# block: entry
|
|
2
|
+
execute as @a run function arena:announce_leaders/foreach_0
|
|
3
|
+
scoreboard players set $t0 rs 0
|
|
4
|
+
execute if score $const_0 rs > $const_0 rs run scoreboard players set $t0 rs 1
|
|
5
|
+
execute if score $t0 rs matches 1.. run function arena:announce_leaders/then_0
|
|
6
|
+
execute if score $t0 rs matches ..0 run function arena:announce_leaders/else_1
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# block: merge_2
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# block: entry
|
|
2
|
+
execute store result score $t0 rs run scoreboard players get arena ticks
|
|
3
|
+
scoreboard players operation $t1 rs = $t0 rs
|
|
4
|
+
scoreboard players operation $t1 rs += $const_1 rs
|
|
5
|
+
execute store result score arena ticks run scoreboard players get $t2 rs
|
|
6
|
+
scoreboard players operation $t3 rs = $t1 rs
|
|
7
|
+
scoreboard players operation $t3 rs %= $const_200 rs
|
|
8
|
+
scoreboard players set $t4 rs 0
|
|
9
|
+
execute if score $t3 rs = $const_0 rs run scoreboard players set $t4 rs 1
|
|
10
|
+
execute if score $t4 rs matches 1.. run function arena:arena_tick/then_0
|
|
11
|
+
execute if score $t4 rs matches ..0 run function arena:arena_tick/merge_2
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# block: merge_2
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# block: entry
|
|
2
|
+
execute store result score $t0 rs run scoreboard players get counter ticks
|
|
3
|
+
scoreboard players operation $t1 rs = $t0 rs
|
|
4
|
+
scoreboard players operation $t1 rs += $const_1 rs
|
|
5
|
+
execute store result score counter ticks run scoreboard players get $t2 rs
|
|
6
|
+
scoreboard players operation $t3 rs = $t1 rs
|
|
7
|
+
scoreboard players operation $t3 rs %= $const_100 rs
|
|
8
|
+
scoreboard players set $t4 rs 0
|
|
9
|
+
execute if score $t3 rs = $const_0 rs run scoreboard players set $t4 rs 1
|
|
10
|
+
execute if score $t4 rs matches 1.. run function counter:counter_tick/then_0
|
|
11
|
+
execute if score $t4 rs matches ..0 run function counter:counter_tick/merge_2
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# block: entry
|
|
2
|
+
scoreboard players operation $b rs = $c rs
|
|
3
|
+
scoreboard players operation $b rs = $d rs
|
|
4
|
+
scoreboard players set $e rs 0
|
|
5
|
+
execute if score $d rs < $a rs run scoreboard players set $e rs 1
|
|
6
|
+
execute if score $e rs matches 1.. run function gcd2:abs/then_0
|
|
7
|
+
execute if score $e rs matches ..0 run function gcd2:abs/merge_2
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# block: loop_body_1
|
|
2
|
+
scoreboard players operation $r rs = $b rs
|
|
3
|
+
scoreboard players operation $r rs %= $p rs
|
|
4
|
+
scoreboard players operation $s rs = $r rs
|
|
5
|
+
scoreboard players operation $b rs = $p rs
|
|
6
|
+
scoreboard players operation $p rs = $r rs
|
|
7
|
+
function gcd2:gcd/loop_check_0
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# block: entry
|
|
2
|
+
scoreboard players operation $i rs = $c rs
|
|
3
|
+
scoreboard players operation $j rs = $k rs
|
|
4
|
+
scoreboard players operation $i rs = $d rs
|
|
5
|
+
scoreboard players operation $j rs = $l rs
|
|
6
|
+
scoreboard players operation $m rs = $d rs
|
|
7
|
+
function gcd2:abs
|
|
8
|
+
scoreboard players operation $n rs = $g rs
|
|
9
|
+
scoreboard players operation $b rs = $n rs
|
|
10
|
+
scoreboard players operation $m rs = $l rs
|
|
11
|
+
function gcd2:abs
|
|
12
|
+
scoreboard players operation $o rs = $g rs
|
|
13
|
+
scoreboard players operation $p rs = $o rs
|
|
14
|
+
function gcd2:gcd/loop_check_0
|