redscript-mc 1.2.26 → 1.2.28
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 +78 -9
- package/README.zh.md +72 -4
- package/dist/__tests__/cli.test.js +13 -13
- package/dist/__tests__/optimizer-advanced.test.js +4 -4
- package/dist/__tests__/stdlib-advanced.test.js +114 -0
- package/dist/__tests__/stdlib-bigint.test.d.ts +7 -0
- package/dist/__tests__/stdlib-bigint.test.js +428 -0
- package/dist/cli.js +13 -5
- package/dist/codegen/mcfunction/index.d.ts +4 -0
- package/dist/codegen/mcfunction/index.js +9 -4
- package/dist/compile.d.ts +4 -0
- package/dist/compile.js +9 -1
- 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.d.ts +4 -0
- package/dist/index.js +11 -6
- package/dist/isqrttest.map.json +15 -0
- package/dist/lowering/index.d.ts +3 -0
- package/dist/lowering/index.js +161 -64
- package/dist/mathtest.map.json +6 -0
- package/dist/mypack.map.json +27 -0
- package/dist/optimizer/commands.d.ts +1 -0
- package/dist/optimizer/commands.js +18 -11
- package/dist/optimizer/structure.d.ts +1 -0
- package/dist/optimizer/structure.js +6 -1
- package/dist/pack.mcmeta +6 -0
- package/dist/reqtest.map.json +4 -0
- package/dist/reqtest2.map.json +4 -0
- package/dist/runtime/index.js +26 -5
- 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/math-showcase.mcrs +146 -0
- package/examples/readme-demo.mcrs +92 -0
- package/examples/showcase.mcrs +505 -0
- package/package.json +1 -1
- package/src/__tests__/cli.test.ts +13 -13
- package/src/__tests__/optimizer-advanced.test.ts +4 -4
- package/src/__tests__/stdlib-advanced.test.ts +120 -0
- package/src/__tests__/stdlib-bigint.test.ts +427 -0
- package/src/cli.ts +14 -5
- package/src/codegen/mcfunction/index.ts +14 -5
- package/src/compile.ts +15 -2
- package/src/index.ts +17 -7
- package/src/lowering/index.ts +165 -63
- package/src/optimizer/commands.ts +18 -12
- package/src/optimizer/structure.ts +6 -2
- package/src/runtime/index.ts +27 -5
- package/src/stdlib/advanced.mcrs +81 -0
- package/src/stdlib/bigint.mcrs +205 -0
- package/src/stdlib/math.mcrs +19 -6
package/dist/lowering/index.js
CHANGED
|
@@ -39,7 +39,8 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
39
39
|
};
|
|
40
40
|
})();
|
|
41
41
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
-
exports.Lowering = void 0;
|
|
42
|
+
exports.Lowering = exports.LOWERING_OBJ = void 0;
|
|
43
|
+
exports.setScoreboardObjective = setScoreboardObjective;
|
|
43
44
|
const builder_1 = require("../ir/builder");
|
|
44
45
|
const diagnostics_1 = require("../diagnostics");
|
|
45
46
|
const path = __importStar(require("path"));
|
|
@@ -54,6 +55,13 @@ const entity_hierarchy_1 = require("../types/entity-hierarchy");
|
|
|
54
55
|
// All builtins support macro parameters - any arg that's a function param
|
|
55
56
|
// will automatically use MC 1.20.2+ macro syntax when needed
|
|
56
57
|
// ---------------------------------------------------------------------------
|
|
58
|
+
// Scoreboard Objective
|
|
59
|
+
// Set per-compilation via setScoreboardObjective() — defaults to 'rs'.
|
|
60
|
+
// ---------------------------------------------------------------------------
|
|
61
|
+
/** Current scoreboard objective. Set once per compile() call. */
|
|
62
|
+
exports.LOWERING_OBJ = 'rs';
|
|
63
|
+
function setScoreboardObjective(obj) { exports.LOWERING_OBJ = obj; }
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
57
65
|
// Builtin Functions
|
|
58
66
|
// ---------------------------------------------------------------------------
|
|
59
67
|
const BUILTINS = {
|
|
@@ -73,9 +81,13 @@ const BUILTINS = {
|
|
|
73
81
|
const pos = [x ?? '~', y ?? '~', z ?? '~'].join(' ');
|
|
74
82
|
return nbt ? `summon ${type} ${pos} ${nbt}` : `summon ${type} ${pos}`;
|
|
75
83
|
},
|
|
76
|
-
particle: ([name, x, y, z]) => {
|
|
84
|
+
particle: ([name, x, y, z, dx, dy, dz, speed, count]) => {
|
|
77
85
|
const pos = [x ?? '~', y ?? '~', z ?? '~'].join(' ');
|
|
78
|
-
|
|
86
|
+
// dx/dy/dz/speed/count are optional; omit trailing undefineds
|
|
87
|
+
const extra = [dx, dy, dz, speed, count].filter(v => v !== undefined && v !== null);
|
|
88
|
+
return extra.length > 0
|
|
89
|
+
? `particle ${name} ${pos} ${extra.join(' ')}`
|
|
90
|
+
: `particle ${name} ${pos}`;
|
|
79
91
|
},
|
|
80
92
|
playsound: ([sound, source, sel, x, y, z, volume, pitch, minVolume]) => ['playsound', sound, source, sel, x, y, z, volume, pitch, minVolume].filter(Boolean).join(' '),
|
|
81
93
|
tp: () => null, // Special handling
|
|
@@ -130,6 +142,7 @@ const BUILTINS = {
|
|
|
130
142
|
clearInterval: () => null, // Special handling
|
|
131
143
|
storage_get_int: () => null, // Special handling (dynamic NBT array read via macro)
|
|
132
144
|
storage_set_array: () => null, // Special handling (write literal NBT array to storage)
|
|
145
|
+
storage_set_int: () => null, // Special handling (dynamic NBT array write via macro)
|
|
133
146
|
};
|
|
134
147
|
function getSpan(node) {
|
|
135
148
|
return node?.span;
|
|
@@ -339,12 +352,30 @@ class Lowering {
|
|
|
339
352
|
}
|
|
340
353
|
preScanExpr(expr, paramNames, macroParams) {
|
|
341
354
|
if (expr.kind === 'call' && BUILTINS[expr.fn] !== undefined) {
|
|
342
|
-
//
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
355
|
+
// Only trigger macro param detection for builtins that actually emit
|
|
356
|
+
// MC commands with $(param) inline in the current function body.
|
|
357
|
+
// Special-handled builtins (storage_get_int / storage_set_int / etc.) are
|
|
358
|
+
// declared as `() => null` — they create their own sub-functions for macro
|
|
359
|
+
// indirection and do NOT require the surrounding function to be a macro.
|
|
360
|
+
const handler = BUILTINS[expr.fn];
|
|
361
|
+
const isSpecialHandled = (() => {
|
|
362
|
+
try {
|
|
363
|
+
return handler() === null;
|
|
364
|
+
}
|
|
365
|
+
catch {
|
|
366
|
+
return false;
|
|
367
|
+
}
|
|
368
|
+
})();
|
|
369
|
+
if (!isSpecialHandled) {
|
|
370
|
+
for (const arg of expr.args) {
|
|
371
|
+
if (arg.kind === 'ident' && paramNames.has(arg.name)) {
|
|
372
|
+
macroParams.add(arg.name);
|
|
373
|
+
}
|
|
346
374
|
}
|
|
347
375
|
}
|
|
376
|
+
// Always recurse into args for nested calls/expressions
|
|
377
|
+
for (const arg of expr.args)
|
|
378
|
+
this.preScanExpr(arg, paramNames, macroParams);
|
|
348
379
|
return;
|
|
349
380
|
}
|
|
350
381
|
// Recurse into sub-expressions for other call types
|
|
@@ -434,6 +465,16 @@ class Lowering {
|
|
|
434
465
|
if (expr.kind === 'struct_lit' || expr.kind === 'array_lit') {
|
|
435
466
|
return { str: this.exprToSnbt(expr) };
|
|
436
467
|
}
|
|
468
|
+
// Float literals: preserve the float value for MC commands that accept floats
|
|
469
|
+
// (particle spread, playsound volume/pitch, etc.)
|
|
470
|
+
// We do NOT truncate here — that only applies to scoreboard/IR contexts.
|
|
471
|
+
if (expr.kind === 'float_lit') {
|
|
472
|
+
return { str: expr.value.toString() };
|
|
473
|
+
}
|
|
474
|
+
// Unary minus applied to a float literal (e.g. -0.5)
|
|
475
|
+
if (expr.kind === 'unary' && expr.op === '-' && expr.operand.kind === 'float_lit') {
|
|
476
|
+
return { str: (-expr.operand.value).toString() };
|
|
477
|
+
}
|
|
437
478
|
return { str: this.exprToString(expr) };
|
|
438
479
|
}
|
|
439
480
|
/**
|
|
@@ -447,10 +488,10 @@ class Lowering {
|
|
|
447
488
|
for (let i = 0; i < loweredArgs.length; i++) {
|
|
448
489
|
const operand = loweredArgs[i];
|
|
449
490
|
if (operand.kind === 'const') {
|
|
450
|
-
this.builder.emitRaw(`scoreboard players set $p${i}
|
|
491
|
+
this.builder.emitRaw(`scoreboard players set $p${i} ${exports.LOWERING_OBJ} ${operand.value}`);
|
|
451
492
|
}
|
|
452
493
|
else if (operand.kind === 'var') {
|
|
453
|
-
this.builder.emitRaw(`scoreboard players operation $p${i}
|
|
494
|
+
this.builder.emitRaw(`scoreboard players operation $p${i} ${exports.LOWERING_OBJ} = ${operand.name} ${exports.LOWERING_OBJ}`);
|
|
454
495
|
}
|
|
455
496
|
}
|
|
456
497
|
// Set up NBT storage for each macro param
|
|
@@ -463,14 +504,14 @@ class Lowering {
|
|
|
463
504
|
this.builder.emitRaw(`data modify storage rs:macro_args ${macroParam} set value ${operand.value}`);
|
|
464
505
|
}
|
|
465
506
|
else if (operand.kind === 'var') {
|
|
466
|
-
this.builder.emitRaw(`execute store result storage rs:macro_args ${macroParam} int 1 run scoreboard players get ${operand.name}
|
|
507
|
+
this.builder.emitRaw(`execute store result storage rs:macro_args ${macroParam} int 1 run scoreboard players get ${operand.name} ${exports.LOWERING_OBJ}`);
|
|
467
508
|
}
|
|
468
509
|
}
|
|
469
510
|
// Call with macro storage
|
|
470
511
|
this.builder.emitRaw(`function ${this.namespace}:${fnName} with storage rs:macro_args`);
|
|
471
512
|
// Copy return value (callers may use it)
|
|
472
513
|
const dst = this.builder.freshTemp();
|
|
473
|
-
this.builder.emitRaw(`scoreboard players operation ${dst}
|
|
514
|
+
this.builder.emitRaw(`scoreboard players operation ${dst} ${exports.LOWERING_OBJ} = $ret ${exports.LOWERING_OBJ}`);
|
|
474
515
|
return { kind: 'var', name: dst };
|
|
475
516
|
}
|
|
476
517
|
lower(program) {
|
|
@@ -704,7 +745,7 @@ class Lowering {
|
|
|
704
745
|
const originalInstrs = [...entry.instrs];
|
|
705
746
|
const originalTerm = entry.term;
|
|
706
747
|
entry.instrs = [
|
|
707
|
-
{ op: 'raw', cmd: `scoreboard players add ${counterVar}
|
|
748
|
+
{ op: 'raw', cmd: `scoreboard players add ${counterVar} ${exports.LOWERING_OBJ} 1` },
|
|
708
749
|
];
|
|
709
750
|
// Create conditional jump
|
|
710
751
|
const bodyLabel = 'tick_body';
|
|
@@ -718,13 +759,13 @@ class Lowering {
|
|
|
718
759
|
// Add check instruction
|
|
719
760
|
entry.instrs.push({
|
|
720
761
|
op: 'raw',
|
|
721
|
-
cmd: `execute store success score ${counterVar}_check
|
|
762
|
+
cmd: `execute store success score ${counterVar}_check ${exports.LOWERING_OBJ} if score ${counterVar} ${exports.LOWERING_OBJ} matches ${rate}..`,
|
|
722
763
|
});
|
|
723
764
|
// Body block (original logic + counter reset)
|
|
724
765
|
fn.blocks.push({
|
|
725
766
|
label: bodyLabel,
|
|
726
767
|
instrs: [
|
|
727
|
-
{ op: 'raw', cmd: `scoreboard players set ${counterVar}
|
|
768
|
+
{ op: 'raw', cmd: `scoreboard players set ${counterVar} ${exports.LOWERING_OBJ} 0` },
|
|
728
769
|
...originalInstrs,
|
|
729
770
|
],
|
|
730
771
|
term: originalTerm,
|
|
@@ -838,7 +879,7 @@ class Lowering {
|
|
|
838
879
|
}
|
|
839
880
|
else if (fieldValue.kind === 'var') {
|
|
840
881
|
// Copy from scoreboard to NBT
|
|
841
|
-
this.builder.emitRaw(`execute store result storage ${path} int 1 run scoreboard players get ${fieldValue.name}
|
|
882
|
+
this.builder.emitRaw(`execute store result storage ${path} int 1 run scoreboard players get ${fieldValue.name} ${exports.LOWERING_OBJ}`);
|
|
842
883
|
}
|
|
843
884
|
}
|
|
844
885
|
return;
|
|
@@ -871,7 +912,7 @@ class Lowering {
|
|
|
871
912
|
}
|
|
872
913
|
else if (elemValue.kind === 'var') {
|
|
873
914
|
this.builder.emitRaw(`data modify storage rs:heap ${stmt.name} append value 0`);
|
|
874
|
-
this.builder.emitRaw(`execute store result storage rs:heap ${stmt.name}[-1] int 1 run scoreboard players get ${elemValue.name}
|
|
915
|
+
this.builder.emitRaw(`execute store result storage rs:heap ${stmt.name}[-1] int 1 run scoreboard players get ${elemValue.name} ${exports.LOWERING_OBJ}`);
|
|
875
916
|
}
|
|
876
917
|
}
|
|
877
918
|
return;
|
|
@@ -917,7 +958,7 @@ class Lowering {
|
|
|
917
958
|
this.builder.emitRaw(`data modify storage ${path} set value ${fieldValue.value}`);
|
|
918
959
|
}
|
|
919
960
|
else if (fieldValue.kind === 'var') {
|
|
920
|
-
this.builder.emitRaw(`execute store result storage ${path} int 1 run scoreboard players get ${fieldValue.name}
|
|
961
|
+
this.builder.emitRaw(`execute store result storage ${path} int 1 run scoreboard players get ${fieldValue.name} ${exports.LOWERING_OBJ}`);
|
|
921
962
|
}
|
|
922
963
|
}
|
|
923
964
|
this.builder.emitReturn({ kind: 'const', value: 0 });
|
|
@@ -1084,10 +1125,10 @@ class Lowering {
|
|
|
1084
1125
|
this.varMap.set(stmt.varName, loopVar);
|
|
1085
1126
|
const startVal = this.lowerExpr(stmt.start);
|
|
1086
1127
|
if (startVal.kind === 'const') {
|
|
1087
|
-
this.builder.emitRaw(`scoreboard players set ${loopVar}
|
|
1128
|
+
this.builder.emitRaw(`scoreboard players set ${loopVar} ${exports.LOWERING_OBJ} ${startVal.value}`);
|
|
1088
1129
|
}
|
|
1089
1130
|
else if (startVal.kind === 'var') {
|
|
1090
|
-
this.builder.emitRaw(`scoreboard players operation ${loopVar}
|
|
1131
|
+
this.builder.emitRaw(`scoreboard players operation ${loopVar} ${exports.LOWERING_OBJ} = ${startVal.name} ${exports.LOWERING_OBJ}`);
|
|
1091
1132
|
}
|
|
1092
1133
|
// Call loop function
|
|
1093
1134
|
this.builder.emitRaw(`function ${this.namespace}:${subFnName}`);
|
|
@@ -1104,11 +1145,11 @@ class Lowering {
|
|
|
1104
1145
|
// Body
|
|
1105
1146
|
this.lowerBlock(stmt.body);
|
|
1106
1147
|
// Increment
|
|
1107
|
-
this.builder.emitRaw(`scoreboard players add ${loopVar}
|
|
1148
|
+
this.builder.emitRaw(`scoreboard players add ${loopVar} ${exports.LOWERING_OBJ} 1`);
|
|
1108
1149
|
// Loop condition: execute if score matches ..<end-1> run function
|
|
1109
1150
|
const endVal = this.lowerExpr(stmt.end);
|
|
1110
1151
|
const endNum = endVal.kind === 'const' ? endVal.value - 1 : '?';
|
|
1111
|
-
this.builder.emitRaw(`execute if score ${loopVar}
|
|
1152
|
+
this.builder.emitRaw(`execute if score ${loopVar} ${exports.LOWERING_OBJ} matches ..${endNum} run function ${this.namespace}:${subFnName}`);
|
|
1112
1153
|
if (!this.builder.isBlockSealed()) {
|
|
1113
1154
|
this.builder.emitReturn();
|
|
1114
1155
|
}
|
|
@@ -1198,12 +1239,12 @@ class Lowering {
|
|
|
1198
1239
|
matchCondition = String(patternValue.value);
|
|
1199
1240
|
}
|
|
1200
1241
|
const subFnName = `${this.currentFn}/match_${this.foreachCounter++}`;
|
|
1201
|
-
this.builder.emitRaw(`execute if score ${matchedVar}
|
|
1242
|
+
this.builder.emitRaw(`execute if score ${matchedVar} ${exports.LOWERING_OBJ} matches ..0 if score ${subject} ${exports.LOWERING_OBJ} matches ${matchCondition} run function ${this.namespace}:${subFnName}`);
|
|
1202
1243
|
this.emitMatchArmSubFunction(subFnName, matchedVar, arm.body, true);
|
|
1203
1244
|
}
|
|
1204
1245
|
if (defaultArm) {
|
|
1205
1246
|
const subFnName = `${this.currentFn}/match_${this.foreachCounter++}`;
|
|
1206
|
-
this.builder.emitRaw(`execute if score ${matchedVar}
|
|
1247
|
+
this.builder.emitRaw(`execute if score ${matchedVar} ${exports.LOWERING_OBJ} matches ..0 run function ${this.namespace}:${subFnName}`);
|
|
1207
1248
|
this.emitMatchArmSubFunction(subFnName, matchedVar, defaultArm.body, false);
|
|
1208
1249
|
}
|
|
1209
1250
|
}
|
|
@@ -1218,7 +1259,7 @@ class Lowering {
|
|
|
1218
1259
|
this.blockPosVars = new Map(savedBlockPosVars);
|
|
1219
1260
|
this.builder.startBlock('entry');
|
|
1220
1261
|
if (setMatched) {
|
|
1221
|
-
this.builder.emitRaw(`scoreboard players set ${matchedVar}
|
|
1262
|
+
this.builder.emitRaw(`scoreboard players set ${matchedVar} ${exports.LOWERING_OBJ} 1`);
|
|
1222
1263
|
}
|
|
1223
1264
|
this.lowerBlock(body);
|
|
1224
1265
|
if (!this.builder.isBlockSealed()) {
|
|
@@ -1250,7 +1291,7 @@ class Lowering {
|
|
|
1250
1291
|
}
|
|
1251
1292
|
this.builder.emitAssign(indexVar, { kind: 'const', value: 0 });
|
|
1252
1293
|
this.builder.emitAssign(oneVar, { kind: 'const', value: 1 });
|
|
1253
|
-
this.builder.emitRaw(`execute store result score ${lengthVar}
|
|
1294
|
+
this.builder.emitRaw(`execute store result score ${lengthVar} ${exports.LOWERING_OBJ} run data get storage rs:heap ${arrayName}`);
|
|
1254
1295
|
const checkLabel = this.builder.freshLabel('foreach_array_check');
|
|
1255
1296
|
const bodyLabel = this.builder.freshLabel('foreach_array_body');
|
|
1256
1297
|
const exitLabel = this.builder.freshLabel('foreach_array_exit');
|
|
@@ -1263,7 +1304,7 @@ class Lowering {
|
|
|
1263
1304
|
this.builder.emitAssign(bindingVar, element);
|
|
1264
1305
|
this.lowerBlock(stmt.body);
|
|
1265
1306
|
if (!this.builder.isBlockSealed()) {
|
|
1266
|
-
this.builder.emitRaw(`scoreboard players operation ${indexVar}
|
|
1307
|
+
this.builder.emitRaw(`scoreboard players operation ${indexVar} ${exports.LOWERING_OBJ} += ${oneVar} ${exports.LOWERING_OBJ}`);
|
|
1267
1308
|
this.builder.emitJump(checkLabel);
|
|
1268
1309
|
}
|
|
1269
1310
|
this.builder.startBlock(exitLabel);
|
|
@@ -1577,7 +1618,7 @@ class Lowering {
|
|
|
1577
1618
|
if (mapped && mapped.startsWith('@e[tag=__rs_obj_')) {
|
|
1578
1619
|
// World object field access → scoreboard get
|
|
1579
1620
|
const dst = this.builder.freshTemp();
|
|
1580
|
-
this.builder.emitRaw(`scoreboard players operation ${dst}
|
|
1621
|
+
this.builder.emitRaw(`scoreboard players operation ${dst} ${exports.LOWERING_OBJ} = ${mapped} ${exports.LOWERING_OBJ}`);
|
|
1581
1622
|
return { kind: 'var', name: dst };
|
|
1582
1623
|
}
|
|
1583
1624
|
if (varType?.kind === 'struct') {
|
|
@@ -1585,13 +1626,13 @@ class Lowering {
|
|
|
1585
1626
|
const path = `rs:heap ${structName}_${expr.obj.name}.${expr.field}`;
|
|
1586
1627
|
const dst = this.builder.freshTemp();
|
|
1587
1628
|
// Read from NBT storage into scoreboard
|
|
1588
|
-
this.builder.emitRaw(`execute store result score ${dst}
|
|
1629
|
+
this.builder.emitRaw(`execute store result score ${dst} ${exports.LOWERING_OBJ} run data get storage ${path}`);
|
|
1589
1630
|
return { kind: 'var', name: dst };
|
|
1590
1631
|
}
|
|
1591
1632
|
// Array length property
|
|
1592
1633
|
if (varType?.kind === 'array' && expr.field === 'len') {
|
|
1593
1634
|
const dst = this.builder.freshTemp();
|
|
1594
|
-
this.builder.emitRaw(`execute store result score ${dst}
|
|
1635
|
+
this.builder.emitRaw(`execute store result score ${dst} ${exports.LOWERING_OBJ} run data get storage rs:heap ${expr.obj.name}`);
|
|
1595
1636
|
return { kind: 'var', name: dst };
|
|
1596
1637
|
}
|
|
1597
1638
|
}
|
|
@@ -1607,10 +1648,10 @@ class Lowering {
|
|
|
1607
1648
|
const value = this.lowerExpr(expr.value);
|
|
1608
1649
|
if (expr.op === '=') {
|
|
1609
1650
|
if (value.kind === 'const') {
|
|
1610
|
-
this.builder.emitRaw(`scoreboard players set ${mapped}
|
|
1651
|
+
this.builder.emitRaw(`scoreboard players set ${mapped} ${exports.LOWERING_OBJ} ${value.value}`);
|
|
1611
1652
|
}
|
|
1612
1653
|
else if (value.kind === 'var') {
|
|
1613
|
-
this.builder.emitRaw(`scoreboard players operation ${mapped}
|
|
1654
|
+
this.builder.emitRaw(`scoreboard players operation ${mapped} ${exports.LOWERING_OBJ} = ${value.name} ${exports.LOWERING_OBJ}`);
|
|
1614
1655
|
}
|
|
1615
1656
|
}
|
|
1616
1657
|
else {
|
|
@@ -1620,10 +1661,10 @@ class Lowering {
|
|
|
1620
1661
|
if (value.kind === 'const') {
|
|
1621
1662
|
const constTemp = this.builder.freshTemp();
|
|
1622
1663
|
this.builder.emitAssign(constTemp, value);
|
|
1623
|
-
this.builder.emitRaw(`scoreboard players operation ${mapped}
|
|
1664
|
+
this.builder.emitRaw(`scoreboard players operation ${mapped} ${exports.LOWERING_OBJ} ${opMap[binOp]} ${constTemp} ${exports.LOWERING_OBJ}`);
|
|
1624
1665
|
}
|
|
1625
1666
|
else if (value.kind === 'var') {
|
|
1626
|
-
this.builder.emitRaw(`scoreboard players operation ${mapped}
|
|
1667
|
+
this.builder.emitRaw(`scoreboard players operation ${mapped} ${exports.LOWERING_OBJ} ${opMap[binOp]} ${value.name} ${exports.LOWERING_OBJ}`);
|
|
1627
1668
|
}
|
|
1628
1669
|
}
|
|
1629
1670
|
return { kind: 'const', value: 0 };
|
|
@@ -1637,16 +1678,16 @@ class Lowering {
|
|
|
1637
1678
|
this.builder.emitRaw(`data modify storage ${path} set value ${value.value}`);
|
|
1638
1679
|
}
|
|
1639
1680
|
else if (value.kind === 'var') {
|
|
1640
|
-
this.builder.emitRaw(`execute store result storage ${path} int 1 run scoreboard players get ${value.name}
|
|
1681
|
+
this.builder.emitRaw(`execute store result storage ${path} int 1 run scoreboard players get ${value.name} ${exports.LOWERING_OBJ}`);
|
|
1641
1682
|
}
|
|
1642
1683
|
}
|
|
1643
1684
|
else {
|
|
1644
1685
|
// Compound assignment: read, modify, write back
|
|
1645
1686
|
const dst = this.builder.freshTemp();
|
|
1646
|
-
this.builder.emitRaw(`execute store result score ${dst}
|
|
1687
|
+
this.builder.emitRaw(`execute store result score ${dst} ${exports.LOWERING_OBJ} run data get storage ${path}`);
|
|
1647
1688
|
const binOp = expr.op.slice(0, -1);
|
|
1648
1689
|
this.builder.emitBinop(dst, { kind: 'var', name: dst }, binOp, value);
|
|
1649
|
-
this.builder.emitRaw(`execute store result storage ${path} int 1 run scoreboard players get ${dst}
|
|
1690
|
+
this.builder.emitRaw(`execute store result storage ${path} int 1 run scoreboard players get ${dst} ${exports.LOWERING_OBJ}`);
|
|
1650
1691
|
}
|
|
1651
1692
|
return { kind: 'const', value: 0 };
|
|
1652
1693
|
}
|
|
@@ -1675,14 +1716,14 @@ class Lowering {
|
|
|
1675
1716
|
this.builder.emitAssign(dst, left);
|
|
1676
1717
|
const rightVar = this.operandToVar(right);
|
|
1677
1718
|
// dst = dst && right → if dst != 0 then dst = right
|
|
1678
|
-
this.builder.emitRaw(`execute if score ${dst}
|
|
1719
|
+
this.builder.emitRaw(`execute if score ${dst} ${exports.LOWERING_OBJ} matches 1.. run scoreboard players operation ${dst} ${exports.LOWERING_OBJ} = ${rightVar} ${exports.LOWERING_OBJ}`);
|
|
1679
1720
|
}
|
|
1680
1721
|
else {
|
|
1681
1722
|
// Short-circuit OR
|
|
1682
1723
|
this.builder.emitAssign(dst, left);
|
|
1683
1724
|
const rightVar = this.operandToVar(right);
|
|
1684
1725
|
// dst = dst || right → if dst == 0 then dst = right
|
|
1685
|
-
this.builder.emitRaw(`execute if score ${dst}
|
|
1726
|
+
this.builder.emitRaw(`execute if score ${dst} ${exports.LOWERING_OBJ} matches ..0 run scoreboard players operation ${dst} ${exports.LOWERING_OBJ} = ${rightVar} ${exports.LOWERING_OBJ}`);
|
|
1686
1727
|
}
|
|
1687
1728
|
return { kind: 'var', name: dst };
|
|
1688
1729
|
}
|
|
@@ -1700,16 +1741,16 @@ class Lowering {
|
|
|
1700
1741
|
// Divide by 1000 to correct for double scaling
|
|
1701
1742
|
const constDiv = this.builder.freshTemp();
|
|
1702
1743
|
this.builder.emitAssign(constDiv, { kind: 'const', value: 1000 });
|
|
1703
|
-
this.builder.emitRaw(`scoreboard players operation ${dst}
|
|
1744
|
+
this.builder.emitRaw(`scoreboard players operation ${dst} ${exports.LOWERING_OBJ} /= ${constDiv} ${exports.LOWERING_OBJ}`);
|
|
1704
1745
|
}
|
|
1705
1746
|
else {
|
|
1706
1747
|
// Division: a * 1000 / b
|
|
1707
1748
|
const constMul = this.builder.freshTemp();
|
|
1708
1749
|
this.builder.emitAssign(constMul, { kind: 'const', value: 1000 });
|
|
1709
1750
|
this.builder.emitAssign(dst, left);
|
|
1710
|
-
this.builder.emitRaw(`scoreboard players operation ${dst}
|
|
1751
|
+
this.builder.emitRaw(`scoreboard players operation ${dst} ${exports.LOWERING_OBJ} *= ${constMul} ${exports.LOWERING_OBJ}`);
|
|
1711
1752
|
const rightVar = this.operandToVar(right);
|
|
1712
|
-
this.builder.emitRaw(`scoreboard players operation ${dst}
|
|
1753
|
+
this.builder.emitRaw(`scoreboard players operation ${dst} ${exports.LOWERING_OBJ} /= ${rightVar} ${exports.LOWERING_OBJ}`);
|
|
1713
1754
|
}
|
|
1714
1755
|
return { kind: 'var', name: dst };
|
|
1715
1756
|
}
|
|
@@ -1779,7 +1820,7 @@ class Lowering {
|
|
|
1779
1820
|
const storagePath = this.getStringStoragePath(expr.args[0]);
|
|
1780
1821
|
if (storagePath) {
|
|
1781
1822
|
const dst = this.builder.freshTemp();
|
|
1782
|
-
this.builder.emitRaw(`execute store result score ${dst}
|
|
1823
|
+
this.builder.emitRaw(`execute store result score ${dst} ${exports.LOWERING_OBJ} run data get storage ${storagePath}`);
|
|
1783
1824
|
return { kind: 'var', name: dst };
|
|
1784
1825
|
}
|
|
1785
1826
|
const staticString = this.resolveStaticString(expr.args[0]);
|
|
@@ -1813,7 +1854,7 @@ class Lowering {
|
|
|
1813
1854
|
const entity = this.exprToString(expr.args[0]);
|
|
1814
1855
|
const tagName = this.exprToString(expr.args[1]);
|
|
1815
1856
|
const dst = this.builder.freshTemp();
|
|
1816
|
-
this.builder.emitRaw(`execute store result score ${dst}
|
|
1857
|
+
this.builder.emitRaw(`execute store result score ${dst} ${exports.LOWERING_OBJ} if entity ${entity}[tag=${tagName}]`);
|
|
1817
1858
|
return { kind: 'var', name: dst };
|
|
1818
1859
|
}
|
|
1819
1860
|
// Handle array push
|
|
@@ -1828,7 +1869,7 @@ class Lowering {
|
|
|
1828
1869
|
}
|
|
1829
1870
|
else if (value.kind === 'var') {
|
|
1830
1871
|
this.builder.emitRaw(`data modify storage rs:heap ${arrName} append value 0`);
|
|
1831
|
-
this.builder.emitRaw(`execute store result storage rs:heap ${arrName}[-1] int 1 run scoreboard players get ${value.name}
|
|
1872
|
+
this.builder.emitRaw(`execute store result storage rs:heap ${arrName}[-1] int 1 run scoreboard players get ${value.name} ${exports.LOWERING_OBJ}`);
|
|
1832
1873
|
}
|
|
1833
1874
|
}
|
|
1834
1875
|
return { kind: 'const', value: 0 };
|
|
@@ -1837,7 +1878,7 @@ class Lowering {
|
|
|
1837
1878
|
const arrName = this.getArrayStorageName(expr.args[0]);
|
|
1838
1879
|
const dst = this.builder.freshTemp();
|
|
1839
1880
|
if (arrName) {
|
|
1840
|
-
this.builder.emitRaw(`execute store result score ${dst}
|
|
1881
|
+
this.builder.emitRaw(`execute store result score ${dst} ${exports.LOWERING_OBJ} run data get storage rs:heap ${arrName}[-1]`);
|
|
1841
1882
|
this.builder.emitRaw(`data remove storage rs:heap ${arrName}[-1]`);
|
|
1842
1883
|
}
|
|
1843
1884
|
else {
|
|
@@ -2101,7 +2142,7 @@ class Lowering {
|
|
|
2101
2142
|
const dst = this.builder.freshTemp();
|
|
2102
2143
|
const min = args[0] ? this.exprToLiteral(args[0]) : '0';
|
|
2103
2144
|
const max = args[1] ? this.exprToLiteral(args[1]) : '100';
|
|
2104
|
-
this.builder.emitRaw(`scoreboard players random ${dst}
|
|
2145
|
+
this.builder.emitRaw(`scoreboard players random ${dst} ${exports.LOWERING_OBJ} ${min} ${max}`);
|
|
2105
2146
|
return { kind: 'var', name: dst };
|
|
2106
2147
|
}
|
|
2107
2148
|
// Special case: random_native - /random value (MC 1.20.3+)
|
|
@@ -2109,7 +2150,7 @@ class Lowering {
|
|
|
2109
2150
|
const dst = this.builder.freshTemp();
|
|
2110
2151
|
const min = args[0] ? this.exprToLiteral(args[0]) : '0';
|
|
2111
2152
|
const max = args[1] ? this.exprToLiteral(args[1]) : '100';
|
|
2112
|
-
this.builder.emitRaw(`execute store result score ${dst}
|
|
2153
|
+
this.builder.emitRaw(`execute store result score ${dst} ${exports.LOWERING_OBJ} run random value ${min} ${max}`);
|
|
2113
2154
|
return { kind: 'var', name: dst };
|
|
2114
2155
|
}
|
|
2115
2156
|
// Special case: random_sequence - /random reset (MC 1.20.3+)
|
|
@@ -2124,7 +2165,7 @@ class Lowering {
|
|
|
2124
2165
|
const dst = this.builder.freshTemp();
|
|
2125
2166
|
const player = this.exprToTargetString(args[0]);
|
|
2126
2167
|
const objective = this.resolveScoreboardObjective(args[0], args[1], callSpan);
|
|
2127
|
-
this.builder.emitRaw(`execute store result score ${dst}
|
|
2168
|
+
this.builder.emitRaw(`execute store result score ${dst} ${exports.LOWERING_OBJ} run scoreboard players get ${player} ${objective}`);
|
|
2128
2169
|
return { kind: 'var', name: dst };
|
|
2129
2170
|
}
|
|
2130
2171
|
// Special case: scoreboard_set — write to vanilla MC scoreboard
|
|
@@ -2138,7 +2179,7 @@ class Lowering {
|
|
|
2138
2179
|
else if (value.kind === 'var') {
|
|
2139
2180
|
// Read directly from the computed scoreboard temp. Routing through a fresh
|
|
2140
2181
|
// temp here breaks once optimization removes the apparently-dead assign.
|
|
2141
|
-
this.builder.emitRaw(`execute store result score ${player} ${objective} run scoreboard players get ${value.name}
|
|
2182
|
+
this.builder.emitRaw(`execute store result score ${player} ${objective} run scoreboard players get ${value.name} ${exports.LOWERING_OBJ}`);
|
|
2142
2183
|
}
|
|
2143
2184
|
return { kind: 'const', value: 0 };
|
|
2144
2185
|
}
|
|
@@ -2201,7 +2242,7 @@ class Lowering {
|
|
|
2201
2242
|
}
|
|
2202
2243
|
if (name === 'bossbar_get_value') {
|
|
2203
2244
|
const dst = this.builder.freshTemp();
|
|
2204
|
-
this.builder.emitRaw(`execute store result score ${dst}
|
|
2245
|
+
this.builder.emitRaw(`execute store result score ${dst} ${exports.LOWERING_OBJ} run bossbar get ${this.exprToString(args[0])} value`);
|
|
2205
2246
|
return { kind: 'var', name: dst };
|
|
2206
2247
|
}
|
|
2207
2248
|
if (name === 'team_add') {
|
|
@@ -2242,7 +2283,7 @@ class Lowering {
|
|
|
2242
2283
|
: this.exprToString(args[1]);
|
|
2243
2284
|
const path = this.exprToString(args[2]);
|
|
2244
2285
|
const scale = args[3] ? this.exprToString(args[3]) : '1';
|
|
2245
|
-
this.builder.emitRaw(`execute store result score ${dst}
|
|
2286
|
+
this.builder.emitRaw(`execute store result score ${dst} ${exports.LOWERING_OBJ} run data get ${targetType} ${target} ${path} ${scale}`);
|
|
2246
2287
|
return { kind: 'var', name: dst };
|
|
2247
2288
|
}
|
|
2248
2289
|
// storage_get_int(storage_ns, array_key, index) -> int
|
|
@@ -2251,7 +2292,7 @@ class Lowering {
|
|
|
2251
2292
|
// array_key : e.g. "sin"
|
|
2252
2293
|
// index : integer index (const or runtime)
|
|
2253
2294
|
//
|
|
2254
|
-
// Const index: execute store result score $dst
|
|
2295
|
+
// Const index: execute store result score $dst ${LOWERING_OBJ} run data get storage math:tables sin[N] 1
|
|
2255
2296
|
// Runtime index: macro sub-function via rs:heap, mirrors readArrayElement.
|
|
2256
2297
|
if (name === 'storage_get_int') {
|
|
2257
2298
|
const storageNs = this.exprToString(args[0]); // "math:tables"
|
|
@@ -2259,7 +2300,7 @@ class Lowering {
|
|
|
2259
2300
|
const indexOperand = this.lowerExpr(args[2]);
|
|
2260
2301
|
const dst = this.builder.freshTemp();
|
|
2261
2302
|
if (indexOperand.kind === 'const') {
|
|
2262
|
-
this.builder.emitRaw(`execute store result score ${dst}
|
|
2303
|
+
this.builder.emitRaw(`execute store result score ${dst} ${exports.LOWERING_OBJ} run data get storage ${storageNs} ${arrayKey}[${indexOperand.value}] 1`);
|
|
2263
2304
|
}
|
|
2264
2305
|
else {
|
|
2265
2306
|
// Runtime index: store the index into rs:heap under a unique key,
|
|
@@ -2269,13 +2310,13 @@ class Lowering {
|
|
|
2269
2310
|
const indexVar = indexOperand.kind === 'var'
|
|
2270
2311
|
? indexOperand.name
|
|
2271
2312
|
: this.operandToVar(indexOperand);
|
|
2272
|
-
this.builder.emitRaw(`execute store result storage rs:heap ${macroKey} int 1 run scoreboard players get ${indexVar}
|
|
2313
|
+
this.builder.emitRaw(`execute store result storage rs:heap ${macroKey} int 1 run scoreboard players get ${indexVar} ${exports.LOWERING_OBJ}`);
|
|
2273
2314
|
this.builder.emitRaw(`function ${this.namespace}:${subFnName} with storage rs:heap`);
|
|
2274
2315
|
// Prefix \x01 is a sentinel for the MC macro '$' line-start marker.
|
|
2275
2316
|
// We avoid using literal '$execute' here so the pre-alloc pass
|
|
2276
2317
|
// doesn't mistakenly register 'execute' as a scoreboard variable.
|
|
2277
2318
|
// Codegen replaces \x01 → '$' when emitting the mc function file.
|
|
2278
|
-
this.emitRawSubFunction(subFnName, `\x01execute store result score ${dst}
|
|
2319
|
+
this.emitRawSubFunction(subFnName, `\x01execute store result score ${dst} ${exports.LOWERING_OBJ} run data get storage ${storageNs} ${arrayKey}[$(${macroKey})] 1`);
|
|
2279
2320
|
}
|
|
2280
2321
|
return { kind: 'var', name: dst };
|
|
2281
2322
|
}
|
|
@@ -2289,6 +2330,54 @@ class Lowering {
|
|
|
2289
2330
|
this.builder.emitRaw(`data modify storage ${storageNs} ${arrayKey} set value ${nbtLiteral}`);
|
|
2290
2331
|
return { kind: 'const', value: 0 };
|
|
2291
2332
|
}
|
|
2333
|
+
// storage_set_int(storage_ns, array_key, index, value) -> void
|
|
2334
|
+
// Writes one integer element into an NBT int-array stored in data storage.
|
|
2335
|
+
// storage_ns : e.g. "rs:bigint"
|
|
2336
|
+
// array_key : e.g. "a"
|
|
2337
|
+
// index : element index (const or runtime)
|
|
2338
|
+
// value : integer value to write (const or runtime)
|
|
2339
|
+
//
|
|
2340
|
+
// Const index + const value:
|
|
2341
|
+
// execute store result storage <ns> <key>[N] int 1 run scoreboard players set $const_V ${LOWERING_OBJ} V
|
|
2342
|
+
// Runtime index or value: macro sub-function via rs:heap
|
|
2343
|
+
if (name === 'storage_set_int') {
|
|
2344
|
+
const storageNs = this.exprToString(args[0]);
|
|
2345
|
+
const arrayKey = this.exprToString(args[1]);
|
|
2346
|
+
const indexOperand = this.lowerExpr(args[2]);
|
|
2347
|
+
const valueOperand = this.lowerExpr(args[3]);
|
|
2348
|
+
if (indexOperand.kind === 'const') {
|
|
2349
|
+
// Static index — use execute store result to write to the fixed slot
|
|
2350
|
+
const valVar = valueOperand.kind === 'var'
|
|
2351
|
+
? valueOperand.name
|
|
2352
|
+
: this.operandToVar(valueOperand);
|
|
2353
|
+
this.builder.emitRaw(`execute store result storage ${storageNs} ${arrayKey}[${indexOperand.value}] int 1 run scoreboard players get ${valVar} ${exports.LOWERING_OBJ}`);
|
|
2354
|
+
}
|
|
2355
|
+
else {
|
|
2356
|
+
// Runtime index: we need a macro sub-function.
|
|
2357
|
+
// Store index + value into rs:heap, call macro that does:
|
|
2358
|
+
// $data modify storage <ns> <key>[$(idx_key)] set value $(val_key)
|
|
2359
|
+
const macroIdxKey = `__ssi_i_${this.foreachCounter++}`;
|
|
2360
|
+
const macroValKey = `__ssi_v_${this.foreachCounter++}`; // kept to pin valVar in optimizer
|
|
2361
|
+
const subFnName = `${this.currentFn}/__ssi_${this.foreachCounter++}`;
|
|
2362
|
+
const indexVar = indexOperand.kind === 'var'
|
|
2363
|
+
? indexOperand.name
|
|
2364
|
+
: this.operandToVar(indexOperand);
|
|
2365
|
+
const valVar = valueOperand.kind === 'var'
|
|
2366
|
+
? valueOperand.name
|
|
2367
|
+
: this.operandToVar(valueOperand);
|
|
2368
|
+
this.builder.emitRaw(`execute store result storage rs:heap ${macroIdxKey} int 1 run scoreboard players get ${indexVar} ${exports.LOWERING_OBJ}`);
|
|
2369
|
+
// Pin valVar in the optimizer's read-set so the assignment is not dead-code-eliminated.
|
|
2370
|
+
// The value is stored to rs:heap but NOT used by the macro (the macro reads the scoreboard
|
|
2371
|
+
// slot directly to avoid the MC 'data modify set value $(n)' macro substitution bug).
|
|
2372
|
+
this.builder.emitRaw(`execute store result storage rs:heap ${macroValKey} int 1 run scoreboard players get ${valVar} ${exports.LOWERING_OBJ}`);
|
|
2373
|
+
this.builder.emitRaw(`function ${this.namespace}:${subFnName} with storage rs:heap`);
|
|
2374
|
+
// Use execute store result (not 'data modify set value $(val)') to avoid MC macro
|
|
2375
|
+
// substitution bugs with numeric values. The scoreboard slot ${valVar} is hardcoded
|
|
2376
|
+
// into the macro sub-function at compile time — only the array index is macro-substituted.
|
|
2377
|
+
this.emitRawSubFunction(subFnName, `\x01execute store result storage ${storageNs} ${arrayKey}[$(${macroIdxKey})] int 1 run scoreboard players get ${valVar} ${exports.LOWERING_OBJ}`);
|
|
2378
|
+
}
|
|
2379
|
+
return { kind: 'const', value: 0 };
|
|
2380
|
+
}
|
|
2292
2381
|
// data_merge(target, nbt) — merge NBT into entity/block/storage
|
|
2293
2382
|
// data_merge(@s, { Invisible: 1b, Silent: 1b })
|
|
2294
2383
|
if (name === 'data_merge') {
|
|
@@ -2331,7 +2420,7 @@ class Lowering {
|
|
|
2331
2420
|
const dst = this.builder.freshTemp();
|
|
2332
2421
|
const setId = this.exprToString(args[0]);
|
|
2333
2422
|
const value = this.exprToString(args[1]);
|
|
2334
|
-
this.builder.emitRaw(`execute store result score ${dst}
|
|
2423
|
+
this.builder.emitRaw(`execute store result score ${dst} ${exports.LOWERING_OBJ} if data storage rs:sets ${setId}[{value:${value}}]`);
|
|
2335
2424
|
return { kind: 'var', name: dst };
|
|
2336
2425
|
}
|
|
2337
2426
|
if (name === 'set_remove') {
|
|
@@ -2596,7 +2685,7 @@ class Lowering {
|
|
|
2596
2685
|
components.push({ text: operand.value.toString() });
|
|
2597
2686
|
return;
|
|
2598
2687
|
}
|
|
2599
|
-
components.push({ score: { name: this.operandToVar(operand), objective:
|
|
2688
|
+
components.push({ score: { name: this.operandToVar(operand), objective: exports.LOWERING_OBJ } });
|
|
2600
2689
|
}
|
|
2601
2690
|
exprToString(expr) {
|
|
2602
2691
|
switch (expr.kind) {
|
|
@@ -2749,11 +2838,19 @@ class Lowering {
|
|
|
2749
2838
|
}
|
|
2750
2839
|
exprToScoreboardObjective(expr, span) {
|
|
2751
2840
|
if (expr.kind === 'mc_name') {
|
|
2752
|
-
|
|
2841
|
+
// 'rs' is the canonical token for the current RS scoreboard objective.
|
|
2842
|
+
// Resolve to LOWERING_OBJ so it respects --scoreboard / namespace default.
|
|
2843
|
+
return expr.value === 'rs' ? exports.LOWERING_OBJ : expr.value;
|
|
2753
2844
|
}
|
|
2754
2845
|
const objective = this.exprToString(expr);
|
|
2755
2846
|
if (objective.startsWith('#') || objective.includes('.')) {
|
|
2756
|
-
|
|
2847
|
+
if (objective.startsWith('#')) {
|
|
2848
|
+
const name = objective.slice(1);
|
|
2849
|
+
// '#rs' is the canonical way to reference the current RS scoreboard objective.
|
|
2850
|
+
// Resolve to LOWERING_OBJ so it tracks the --scoreboard option.
|
|
2851
|
+
return name === 'rs' ? exports.LOWERING_OBJ : name;
|
|
2852
|
+
}
|
|
2853
|
+
return objective;
|
|
2757
2854
|
}
|
|
2758
2855
|
return `${this.getObjectiveNamespace(span)}.${objective}`;
|
|
2759
2856
|
}
|
|
@@ -2769,7 +2866,7 @@ class Lowering {
|
|
|
2769
2866
|
if (!filePath) {
|
|
2770
2867
|
return this.namespace;
|
|
2771
2868
|
}
|
|
2772
|
-
return this.isStdlibFile(filePath) ?
|
|
2869
|
+
return this.isStdlibFile(filePath) ? exports.LOWERING_OBJ : this.namespace;
|
|
2773
2870
|
}
|
|
2774
2871
|
tryGetStdlibInternalObjective(playerExpr, objectiveExpr, span) {
|
|
2775
2872
|
if (!span || !this.currentStdlibCallSite || objectiveExpr.kind !== 'mc_name' || objectiveExpr.value !== 'rs') {
|
|
@@ -2784,7 +2881,7 @@ class Lowering {
|
|
|
2784
2881
|
return null;
|
|
2785
2882
|
}
|
|
2786
2883
|
const hash = this.shortHash(this.serializeCallSite(this.currentStdlibCallSite));
|
|
2787
|
-
return
|
|
2884
|
+
return `${exports.LOWERING_OBJ}._${resourceBase}_${hash}`;
|
|
2788
2885
|
}
|
|
2789
2886
|
getStdlibInternalResourceBase(playerExpr) {
|
|
2790
2887
|
if (!playerExpr || playerExpr.kind !== 'str_lit') {
|
|
@@ -3071,15 +3168,15 @@ class Lowering {
|
|
|
3071
3168
|
readArrayElement(arrayName, index) {
|
|
3072
3169
|
const dst = this.builder.freshTemp();
|
|
3073
3170
|
if (index.kind === 'const') {
|
|
3074
|
-
this.builder.emitRaw(`execute store result score ${dst}
|
|
3171
|
+
this.builder.emitRaw(`execute store result score ${dst} ${exports.LOWERING_OBJ} run data get storage rs:heap ${arrayName}[${index.value}]`);
|
|
3075
3172
|
return { kind: 'var', name: dst };
|
|
3076
3173
|
}
|
|
3077
3174
|
const macroKey = `__rs_index_${this.foreachCounter++}`;
|
|
3078
3175
|
const subFnName = `${this.currentFn}/array_get_${this.foreachCounter++}`;
|
|
3079
3176
|
const indexVar = index.kind === 'var' ? index.name : this.operandToVar(index);
|
|
3080
|
-
this.builder.emitRaw(`execute store result storage rs:heap ${macroKey} int 1 run scoreboard players get ${indexVar}
|
|
3177
|
+
this.builder.emitRaw(`execute store result storage rs:heap ${macroKey} int 1 run scoreboard players get ${indexVar} ${exports.LOWERING_OBJ}`);
|
|
3081
3178
|
this.builder.emitRaw(`function ${this.namespace}:${subFnName} with storage rs:heap`);
|
|
3082
|
-
this.emitRawSubFunction(subFnName, `\x01execute store result score ${dst}
|
|
3179
|
+
this.emitRawSubFunction(subFnName, `\x01execute store result score ${dst} ${exports.LOWERING_OBJ} run data get storage rs:heap ${arrayName}[$(${macroKey})]`);
|
|
3083
3180
|
return { kind: 'var', name: dst };
|
|
3084
3181
|
}
|
|
3085
3182
|
emitRawSubFunction(name, ...commands) {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$o": "x",
|
|
3
|
+
"$r": "execute",
|
|
4
|
+
"$u": "y",
|
|
5
|
+
"$aa": "ax",
|
|
6
|
+
"$ad": "ay",
|
|
7
|
+
"$ai": "swapped",
|
|
8
|
+
"$ak": "tmp",
|
|
9
|
+
"$al": "lo",
|
|
10
|
+
"$am": "hi",
|
|
11
|
+
"$ar": "mid",
|
|
12
|
+
"$as": "t",
|
|
13
|
+
"$ax": "theta",
|
|
14
|
+
"$a": "const:0",
|
|
15
|
+
"$b": "const:1",
|
|
16
|
+
"$c": "const:2",
|
|
17
|
+
"$d": "const:45",
|
|
18
|
+
"$e": "const:90",
|
|
19
|
+
"$f": "const:180",
|
|
20
|
+
"$g": "const:270",
|
|
21
|
+
"$h": "const:360",
|
|
22
|
+
"$i": "const:1000",
|
|
23
|
+
"$j": "const:46340",
|
|
24
|
+
"$k": "internal:ret",
|
|
25
|
+
"$n": "internal:p0",
|
|
26
|
+
"$t": "internal:p1"
|
|
27
|
+
}
|
|
@@ -17,6 +17,7 @@ export interface CommandFunction {
|
|
|
17
17
|
name: string;
|
|
18
18
|
commands: IRCommand[];
|
|
19
19
|
}
|
|
20
|
+
export declare function setOptimizerObjective(obj: string): void;
|
|
20
21
|
export declare function createEmptyOptimizationStats(): OptimizationStats;
|
|
21
22
|
export declare function mergeOptimizationStats(base: OptimizationStats, delta: Partial<OptimizationStats>): void;
|
|
22
23
|
export declare function applyLICM(functions: CommandFunction[]): {
|