redscript-mc 1.2.27 → 1.2.29
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 +24 -13
- package/README.zh.md +16 -5
- package/dist/__tests__/cli.test.js +13 -13
- package/dist/__tests__/optimizer-advanced.test.js +4 -4
- 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 +5 -0
- package/dist/compile.js +9 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.js +11 -6
- package/dist/lowering/index.d.ts +3 -0
- package/dist/lowering/index.js +95 -65
- 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/editors/vscode/out/extension.js +1797 -1157
- package/editors/vscode/package-lock.json +3 -3
- package/editors/vscode/package.json +1 -1
- package/editors/vscode/src/hover.ts +18 -0
- package/editors/vscode/syntaxes/redscript.tmLanguage.json +12 -3
- package/examples/math-showcase.mcrs +146 -0
- package/examples/readme-demo.mcrs +92 -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/cli.ts +14 -5
- package/src/codegen/mcfunction/index.ts +14 -5
- package/src/compile.ts +16 -2
- package/src/index.ts +18 -7
- package/src/lowering/index.ts +95 -64
- package/src/optimizer/commands.ts +18 -12
- package/src/optimizer/structure.ts +6 -2
|
@@ -183,6 +183,7 @@ var require_lexer = __commonJS({
|
|
|
183
183
|
enum: "enum",
|
|
184
184
|
trigger: "trigger",
|
|
185
185
|
namespace: "namespace",
|
|
186
|
+
module: "module",
|
|
186
187
|
execute: "execute",
|
|
187
188
|
run: "run",
|
|
188
189
|
unless: "unless",
|
|
@@ -716,11 +717,21 @@ var require_parser = __commonJS({
|
|
|
716
717
|
"Creeper",
|
|
717
718
|
"Spider",
|
|
718
719
|
"Enderman",
|
|
720
|
+
"Blaze",
|
|
721
|
+
"Witch",
|
|
722
|
+
"Slime",
|
|
723
|
+
"ZombieVillager",
|
|
724
|
+
"Husk",
|
|
725
|
+
"Drowned",
|
|
726
|
+
"Stray",
|
|
727
|
+
"WitherSkeleton",
|
|
728
|
+
"CaveSpider",
|
|
719
729
|
"Pig",
|
|
720
730
|
"Cow",
|
|
721
731
|
"Sheep",
|
|
722
732
|
"Chicken",
|
|
723
733
|
"Villager",
|
|
734
|
+
"WanderingTrader",
|
|
724
735
|
"ArmorStand",
|
|
725
736
|
"Item",
|
|
726
737
|
"Arrow"
|
|
@@ -735,6 +746,7 @@ var require_parser = __commonJS({
|
|
|
735
746
|
var Parser = class _Parser {
|
|
736
747
|
constructor(tokens, source, filePath) {
|
|
737
748
|
this.pos = 0;
|
|
749
|
+
this.inLibraryMode = false;
|
|
738
750
|
this.tokens = tokens;
|
|
739
751
|
this.sourceLines = source?.split("\n") ?? [];
|
|
740
752
|
this.filePath = filePath;
|
|
@@ -806,12 +818,22 @@ var require_parser = __commonJS({
|
|
|
806
818
|
const implBlocks = [];
|
|
807
819
|
const enums = [];
|
|
808
820
|
const consts = [];
|
|
821
|
+
let isLibrary = false;
|
|
809
822
|
if (this.check("namespace")) {
|
|
810
823
|
this.advance();
|
|
811
824
|
const name = this.expect("ident");
|
|
812
825
|
namespace = name.value;
|
|
813
826
|
this.expect(";");
|
|
814
827
|
}
|
|
828
|
+
if (this.check("module")) {
|
|
829
|
+
this.advance();
|
|
830
|
+
const modKind = this.expect("ident");
|
|
831
|
+
if (modKind.value === "library") {
|
|
832
|
+
isLibrary = true;
|
|
833
|
+
this.inLibraryMode = true;
|
|
834
|
+
}
|
|
835
|
+
this.expect(";");
|
|
836
|
+
}
|
|
815
837
|
while (!this.check("eof")) {
|
|
816
838
|
if (this.check("let")) {
|
|
817
839
|
globals.push(this.parseGlobalDecl(true));
|
|
@@ -830,7 +852,7 @@ var require_parser = __commonJS({
|
|
|
830
852
|
declarations.push(this.parseFnDecl());
|
|
831
853
|
}
|
|
832
854
|
}
|
|
833
|
-
return { namespace, globals, declarations, structs, implBlocks, enums, consts };
|
|
855
|
+
return { namespace, globals, declarations, structs, implBlocks, enums, consts, isLibrary };
|
|
834
856
|
}
|
|
835
857
|
// -------------------------------------------------------------------------
|
|
836
858
|
// Struct Declaration
|
|
@@ -923,7 +945,8 @@ var require_parser = __commonJS({
|
|
|
923
945
|
returnType = this.parseType();
|
|
924
946
|
}
|
|
925
947
|
const body = this.parseBlock();
|
|
926
|
-
|
|
948
|
+
const fn = this.withLoc({ name, params, returnType, decorators, body, isLibraryFn: this.inLibraryMode || void 0 }, fnToken);
|
|
949
|
+
return fn;
|
|
927
950
|
}
|
|
928
951
|
/** Parse a `declare fn name(params): returnType;` stub — no body, just discard. */
|
|
929
952
|
parseDeclareStub() {
|
|
@@ -985,6 +1008,22 @@ var require_parser = __commonJS({
|
|
|
985
1008
|
return { name, args };
|
|
986
1009
|
}
|
|
987
1010
|
}
|
|
1011
|
+
if (name === "require_on_load") {
|
|
1012
|
+
const rawArgs = [];
|
|
1013
|
+
for (const part of argsStr.split(",")) {
|
|
1014
|
+
const trimmed = part.trim();
|
|
1015
|
+
const identMatch = trimmed.match(/^([A-Za-z_][A-Za-z0-9_]*)$/);
|
|
1016
|
+
if (identMatch) {
|
|
1017
|
+
rawArgs.push({ kind: "string", value: identMatch[1] });
|
|
1018
|
+
} else {
|
|
1019
|
+
const strMatch = trimmed.match(/^"([^"]*)"$/);
|
|
1020
|
+
if (strMatch) {
|
|
1021
|
+
rawArgs.push({ kind: "string", value: strMatch[1] });
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
return { name, rawArgs };
|
|
1026
|
+
}
|
|
988
1027
|
for (const part of argsStr.split(",")) {
|
|
989
1028
|
const [key, val] = part.split("=").map((s) => s.trim());
|
|
990
1029
|
if (key === "rate") {
|
|
@@ -1034,7 +1073,16 @@ var require_parser = __commonJS({
|
|
|
1034
1073
|
type = { kind: "named", name: token.kind };
|
|
1035
1074
|
} else if (token.kind === "ident") {
|
|
1036
1075
|
this.advance();
|
|
1037
|
-
|
|
1076
|
+
if (token.value === "selector" && this.check("<")) {
|
|
1077
|
+
this.advance();
|
|
1078
|
+
const entityType = this.expect("ident").value;
|
|
1079
|
+
this.expect(">");
|
|
1080
|
+
type = { kind: "selector", entityType };
|
|
1081
|
+
} else if (token.value === "selector") {
|
|
1082
|
+
type = { kind: "selector" };
|
|
1083
|
+
} else {
|
|
1084
|
+
type = { kind: "struct", name: token.value };
|
|
1085
|
+
}
|
|
1038
1086
|
} else {
|
|
1039
1087
|
this.error(`Expected type, got '${token.kind}'`);
|
|
1040
1088
|
}
|
|
@@ -2248,11 +2296,21 @@ var require_typechecker = __commonJS({
|
|
|
2248
2296
|
"Creeper": "HostileMob",
|
|
2249
2297
|
"Spider": "HostileMob",
|
|
2250
2298
|
"Enderman": "HostileMob",
|
|
2299
|
+
"Blaze": "HostileMob",
|
|
2300
|
+
"Witch": "HostileMob",
|
|
2301
|
+
"Slime": "HostileMob",
|
|
2302
|
+
"ZombieVillager": "HostileMob",
|
|
2303
|
+
"Husk": "HostileMob",
|
|
2304
|
+
"Drowned": "HostileMob",
|
|
2305
|
+
"Stray": "HostileMob",
|
|
2306
|
+
"WitherSkeleton": "HostileMob",
|
|
2307
|
+
"CaveSpider": "HostileMob",
|
|
2251
2308
|
"Pig": "PassiveMob",
|
|
2252
2309
|
"Cow": "PassiveMob",
|
|
2253
2310
|
"Sheep": "PassiveMob",
|
|
2254
2311
|
"Chicken": "PassiveMob",
|
|
2255
2312
|
"Villager": "PassiveMob",
|
|
2313
|
+
"WanderingTrader": "PassiveMob",
|
|
2256
2314
|
"ArmorStand": "entity",
|
|
2257
2315
|
"Item": "entity",
|
|
2258
2316
|
"Arrow": "entity"
|
|
@@ -2268,6 +2326,24 @@ var require_typechecker = __commonJS({
|
|
|
2268
2326
|
"minecraft:spider": "Spider",
|
|
2269
2327
|
"enderman": "Enderman",
|
|
2270
2328
|
"minecraft:enderman": "Enderman",
|
|
2329
|
+
"blaze": "Blaze",
|
|
2330
|
+
"minecraft:blaze": "Blaze",
|
|
2331
|
+
"witch": "Witch",
|
|
2332
|
+
"minecraft:witch": "Witch",
|
|
2333
|
+
"slime": "Slime",
|
|
2334
|
+
"minecraft:slime": "Slime",
|
|
2335
|
+
"zombie_villager": "ZombieVillager",
|
|
2336
|
+
"minecraft:zombie_villager": "ZombieVillager",
|
|
2337
|
+
"husk": "Husk",
|
|
2338
|
+
"minecraft:husk": "Husk",
|
|
2339
|
+
"drowned": "Drowned",
|
|
2340
|
+
"minecraft:drowned": "Drowned",
|
|
2341
|
+
"stray": "Stray",
|
|
2342
|
+
"minecraft:stray": "Stray",
|
|
2343
|
+
"wither_skeleton": "WitherSkeleton",
|
|
2344
|
+
"minecraft:wither_skeleton": "WitherSkeleton",
|
|
2345
|
+
"cave_spider": "CaveSpider",
|
|
2346
|
+
"minecraft:cave_spider": "CaveSpider",
|
|
2271
2347
|
"pig": "Pig",
|
|
2272
2348
|
"minecraft:pig": "Pig",
|
|
2273
2349
|
"cow": "Cow",
|
|
@@ -2278,6 +2354,8 @@ var require_typechecker = __commonJS({
|
|
|
2278
2354
|
"minecraft:chicken": "Chicken",
|
|
2279
2355
|
"villager": "Villager",
|
|
2280
2356
|
"minecraft:villager": "Villager",
|
|
2357
|
+
"wandering_trader": "WanderingTrader",
|
|
2358
|
+
"minecraft:wandering_trader": "WanderingTrader",
|
|
2281
2359
|
"armor_stand": "ArmorStand",
|
|
2282
2360
|
"minecraft:armor_stand": "ArmorStand",
|
|
2283
2361
|
"item": "Item",
|
|
@@ -3275,6 +3353,99 @@ var require_builder = __commonJS({
|
|
|
3275
3353
|
}
|
|
3276
3354
|
});
|
|
3277
3355
|
|
|
3356
|
+
// ../../dist/types/entity-hierarchy.js
|
|
3357
|
+
var require_entity_hierarchy = __commonJS({
|
|
3358
|
+
"../../dist/types/entity-hierarchy.js"(exports2) {
|
|
3359
|
+
"use strict";
|
|
3360
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
3361
|
+
exports2.ENTITY_TYPE_BY_MCID = exports2.ENTITY_TYPE_MAP = exports2.ENTITY_TYPES = void 0;
|
|
3362
|
+
exports2.isSubtype = isSubtype;
|
|
3363
|
+
exports2.areCompatibleTypes = areCompatibleTypes;
|
|
3364
|
+
exports2.getConcreteSubtypes = getConcreteSubtypes;
|
|
3365
|
+
exports2.getSelectorEntityType = getSelectorEntityType;
|
|
3366
|
+
exports2.getBaseSelectorType = getBaseSelectorType;
|
|
3367
|
+
exports2.ENTITY_TYPES = [
|
|
3368
|
+
// Root
|
|
3369
|
+
{ name: "Entity", mcId: null, abstract: true, parent: null },
|
|
3370
|
+
// Direct children of Entity
|
|
3371
|
+
{ name: "Player", mcId: "minecraft:player", abstract: false, parent: "Entity" },
|
|
3372
|
+
{ name: "ArmorStand", mcId: "minecraft:armor_stand", abstract: false, parent: "Entity" },
|
|
3373
|
+
{ name: "Item", mcId: "minecraft:item", abstract: false, parent: "Entity" },
|
|
3374
|
+
{ name: "Arrow", mcId: "minecraft:arrow", abstract: false, parent: "Entity" },
|
|
3375
|
+
// Mob hierarchy
|
|
3376
|
+
{ name: "Mob", mcId: null, abstract: true, parent: "Entity" },
|
|
3377
|
+
// Hostile mobs
|
|
3378
|
+
{ name: "HostileMob", mcId: null, abstract: true, parent: "Mob" },
|
|
3379
|
+
{ name: "Zombie", mcId: "minecraft:zombie", abstract: false, parent: "HostileMob" },
|
|
3380
|
+
{ name: "Skeleton", mcId: "minecraft:skeleton", abstract: false, parent: "HostileMob" },
|
|
3381
|
+
{ name: "Creeper", mcId: "minecraft:creeper", abstract: false, parent: "HostileMob" },
|
|
3382
|
+
{ name: "Spider", mcId: "minecraft:spider", abstract: false, parent: "HostileMob" },
|
|
3383
|
+
{ name: "Enderman", mcId: "minecraft:enderman", abstract: false, parent: "HostileMob" },
|
|
3384
|
+
{ name: "Blaze", mcId: "minecraft:blaze", abstract: false, parent: "HostileMob" },
|
|
3385
|
+
{ name: "Witch", mcId: "minecraft:witch", abstract: false, parent: "HostileMob" },
|
|
3386
|
+
{ name: "Slime", mcId: "minecraft:slime", abstract: false, parent: "HostileMob" },
|
|
3387
|
+
{ name: "ZombieVillager", mcId: "minecraft:zombie_villager", abstract: false, parent: "HostileMob" },
|
|
3388
|
+
{ name: "Husk", mcId: "minecraft:husk", abstract: false, parent: "HostileMob" },
|
|
3389
|
+
{ name: "Drowned", mcId: "minecraft:drowned", abstract: false, parent: "HostileMob" },
|
|
3390
|
+
{ name: "Stray", mcId: "minecraft:stray", abstract: false, parent: "HostileMob" },
|
|
3391
|
+
{ name: "WitherSkeleton", mcId: "minecraft:wither_skeleton", abstract: false, parent: "HostileMob" },
|
|
3392
|
+
{ name: "CaveSpider", mcId: "minecraft:cave_spider", abstract: false, parent: "HostileMob" },
|
|
3393
|
+
// Passive mobs
|
|
3394
|
+
{ name: "PassiveMob", mcId: null, abstract: true, parent: "Mob" },
|
|
3395
|
+
{ name: "Pig", mcId: "minecraft:pig", abstract: false, parent: "PassiveMob" },
|
|
3396
|
+
{ name: "Cow", mcId: "minecraft:cow", abstract: false, parent: "PassiveMob" },
|
|
3397
|
+
{ name: "Sheep", mcId: "minecraft:sheep", abstract: false, parent: "PassiveMob" },
|
|
3398
|
+
{ name: "Chicken", mcId: "minecraft:chicken", abstract: false, parent: "PassiveMob" },
|
|
3399
|
+
{ name: "Villager", mcId: "minecraft:villager", abstract: false, parent: "PassiveMob" },
|
|
3400
|
+
{ name: "WanderingTrader", mcId: "minecraft:wandering_trader", abstract: false, parent: "PassiveMob" }
|
|
3401
|
+
];
|
|
3402
|
+
exports2.ENTITY_TYPE_MAP = new Map(exports2.ENTITY_TYPES.map((t) => [t.name.toLowerCase(), t]));
|
|
3403
|
+
exports2.ENTITY_TYPE_BY_MCID = new Map(exports2.ENTITY_TYPES.filter((t) => t.mcId !== null).map((t) => [t.mcId.replace("minecraft:", ""), t]));
|
|
3404
|
+
function isSubtype(typeA, typeB) {
|
|
3405
|
+
if (typeA === typeB)
|
|
3406
|
+
return true;
|
|
3407
|
+
const node = exports2.ENTITY_TYPE_MAP.get(typeA.toLowerCase());
|
|
3408
|
+
if (!node || !node.parent)
|
|
3409
|
+
return false;
|
|
3410
|
+
return isSubtype(node.parent, typeB);
|
|
3411
|
+
}
|
|
3412
|
+
function areCompatibleTypes(outerType, innerType) {
|
|
3413
|
+
return isSubtype(outerType, innerType) || isSubtype(innerType, outerType);
|
|
3414
|
+
}
|
|
3415
|
+
function getConcreteSubtypes(typeName) {
|
|
3416
|
+
const results = [];
|
|
3417
|
+
for (const node of exports2.ENTITY_TYPES) {
|
|
3418
|
+
if (!node.abstract && isSubtype(node.name, typeName)) {
|
|
3419
|
+
results.push(node);
|
|
3420
|
+
}
|
|
3421
|
+
}
|
|
3422
|
+
return results;
|
|
3423
|
+
}
|
|
3424
|
+
function getSelectorEntityType(selector) {
|
|
3425
|
+
const match = selector.match(/type=(?:minecraft:)?([a-z_]+)/);
|
|
3426
|
+
if (!match)
|
|
3427
|
+
return null;
|
|
3428
|
+
const mcId = match[1];
|
|
3429
|
+
const node = exports2.ENTITY_TYPE_BY_MCID.get(mcId);
|
|
3430
|
+
return node ? node.name : null;
|
|
3431
|
+
}
|
|
3432
|
+
function getBaseSelectorType(selector) {
|
|
3433
|
+
const trimmed = selector.trim();
|
|
3434
|
+
const typeFromFilter = getSelectorEntityType(trimmed);
|
|
3435
|
+
if (trimmed.startsWith("@a") || trimmed.startsWith("@p") || trimmed.startsWith("@r")) {
|
|
3436
|
+
return typeFromFilter ?? "Player";
|
|
3437
|
+
}
|
|
3438
|
+
if (trimmed.startsWith("@e")) {
|
|
3439
|
+
return typeFromFilter ?? "Entity";
|
|
3440
|
+
}
|
|
3441
|
+
if (trimmed.startsWith("@s")) {
|
|
3442
|
+
return typeFromFilter ?? null;
|
|
3443
|
+
}
|
|
3444
|
+
return null;
|
|
3445
|
+
}
|
|
3446
|
+
}
|
|
3447
|
+
});
|
|
3448
|
+
|
|
3278
3449
|
// ../../dist/lowering/index.js
|
|
3279
3450
|
var require_lowering = __commonJS({
|
|
3280
3451
|
"../../dist/lowering/index.js"(exports2) {
|
|
@@ -3317,11 +3488,17 @@ var require_lowering = __commonJS({
|
|
|
3317
3488
|
};
|
|
3318
3489
|
})();
|
|
3319
3490
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
3320
|
-
exports2.Lowering = void 0;
|
|
3491
|
+
exports2.Lowering = exports2.LOWERING_OBJ = void 0;
|
|
3492
|
+
exports2.setScoreboardObjective = setScoreboardObjective;
|
|
3321
3493
|
var builder_1 = require_builder();
|
|
3322
3494
|
var diagnostics_1 = require_diagnostics();
|
|
3323
3495
|
var path2 = __importStar(require("path"));
|
|
3324
3496
|
var types_1 = require_types();
|
|
3497
|
+
var entity_hierarchy_1 = require_entity_hierarchy();
|
|
3498
|
+
exports2.LOWERING_OBJ = "rs";
|
|
3499
|
+
function setScoreboardObjective(obj) {
|
|
3500
|
+
exports2.LOWERING_OBJ = obj;
|
|
3501
|
+
}
|
|
3325
3502
|
var BUILTINS2 = {
|
|
3326
3503
|
say: ([msg]) => `say ${msg}`,
|
|
3327
3504
|
tell: ([sel, msg]) => `tellraw ${sel} {"text":"${msg}"}`,
|
|
@@ -3339,9 +3516,10 @@ var require_lowering = __commonJS({
|
|
|
3339
3516
|
const pos = [x ?? "~", y ?? "~", z ?? "~"].join(" ");
|
|
3340
3517
|
return nbt ? `summon ${type} ${pos} ${nbt}` : `summon ${type} ${pos}`;
|
|
3341
3518
|
},
|
|
3342
|
-
particle: ([name, x, y, z]) => {
|
|
3519
|
+
particle: ([name, x, y, z, dx, dy, dz, speed, count]) => {
|
|
3343
3520
|
const pos = [x ?? "~", y ?? "~", z ?? "~"].join(" ");
|
|
3344
|
-
|
|
3521
|
+
const extra = [dx, dy, dz, speed, count].filter((v) => v !== void 0 && v !== null);
|
|
3522
|
+
return extra.length > 0 ? `particle ${name} ${pos} ${extra.join(" ")}` : `particle ${name} ${pos}`;
|
|
3345
3523
|
},
|
|
3346
3524
|
playsound: ([sound, source, sel, x, y, z, volume, pitch, minVolume]) => ["playsound", sound, source, sel, x, y, z, volume, pitch, minVolume].filter(Boolean).join(" "),
|
|
3347
3525
|
tp: () => null,
|
|
@@ -3428,8 +3606,14 @@ var require_lowering = __commonJS({
|
|
|
3428
3606
|
// Special handling
|
|
3429
3607
|
setInterval: () => null,
|
|
3430
3608
|
// Special handling
|
|
3431
|
-
clearInterval: () => null
|
|
3609
|
+
clearInterval: () => null,
|
|
3432
3610
|
// Special handling
|
|
3611
|
+
storage_get_int: () => null,
|
|
3612
|
+
// Special handling (dynamic NBT array read via macro)
|
|
3613
|
+
storage_set_array: () => null,
|
|
3614
|
+
// Special handling (write literal NBT array to storage)
|
|
3615
|
+
storage_set_int: () => null
|
|
3616
|
+
// Special handling (dynamic NBT array write via macro)
|
|
3433
3617
|
};
|
|
3434
3618
|
function getSpan(node) {
|
|
3435
3619
|
return node?.span;
|
|
@@ -3443,11 +3627,21 @@ var require_lowering = __commonJS({
|
|
|
3443
3627
|
Creeper: "minecraft:creeper",
|
|
3444
3628
|
Spider: "minecraft:spider",
|
|
3445
3629
|
Enderman: "minecraft:enderman",
|
|
3630
|
+
Blaze: "minecraft:blaze",
|
|
3631
|
+
Witch: "minecraft:witch",
|
|
3632
|
+
Slime: "minecraft:slime",
|
|
3633
|
+
ZombieVillager: "minecraft:zombie_villager",
|
|
3634
|
+
Husk: "minecraft:husk",
|
|
3635
|
+
Drowned: "minecraft:drowned",
|
|
3636
|
+
Stray: "minecraft:stray",
|
|
3637
|
+
WitherSkeleton: "minecraft:wither_skeleton",
|
|
3638
|
+
CaveSpider: "minecraft:cave_spider",
|
|
3446
3639
|
Pig: "minecraft:pig",
|
|
3447
3640
|
Cow: "minecraft:cow",
|
|
3448
3641
|
Sheep: "minecraft:sheep",
|
|
3449
3642
|
Chicken: "minecraft:chicken",
|
|
3450
3643
|
Villager: "minecraft:villager",
|
|
3644
|
+
WanderingTrader: "minecraft:wandering_trader",
|
|
3451
3645
|
ArmorStand: "minecraft:armor_stand",
|
|
3452
3646
|
Item: "minecraft:item",
|
|
3453
3647
|
Arrow: "minecraft:arrow"
|
|
@@ -3485,6 +3679,16 @@ var require_lowering = __commonJS({
|
|
|
3485
3679
|
return `${emitCoord(pos.x)} ${emitCoord(pos.y)} ${emitCoord(pos.z)}`;
|
|
3486
3680
|
}
|
|
3487
3681
|
var Lowering = class {
|
|
3682
|
+
/** Unique IR variable name for a local variable, scoped to the current function.
|
|
3683
|
+
* Prevents cross-function scoreboard slot collisions: $fn_x ≠ $gn_x.
|
|
3684
|
+
* Only applies to user-defined locals/params; internal slots ($p0, $ret) are
|
|
3685
|
+
* intentionally global (calling convention). */
|
|
3686
|
+
fnVar(name) {
|
|
3687
|
+
return `$${this.currentFn}_${name}`;
|
|
3688
|
+
}
|
|
3689
|
+
currentEntityContext() {
|
|
3690
|
+
return this.entityContextStack.length > 0 ? this.entityContextStack[this.entityContextStack.length - 1] : "Entity";
|
|
3691
|
+
}
|
|
3488
3692
|
constructor(namespace, sourceRanges = []) {
|
|
3489
3693
|
this.functions = [];
|
|
3490
3694
|
this.globals = [];
|
|
@@ -3498,6 +3702,7 @@ var require_lowering = __commonJS({
|
|
|
3498
3702
|
this.timeoutCounter = 0;
|
|
3499
3703
|
this.intervalCounter = 0;
|
|
3500
3704
|
this.warnings = [];
|
|
3705
|
+
this.entityContextStack = [];
|
|
3501
3706
|
this.varMap = /* @__PURE__ */ new Map();
|
|
3502
3707
|
this.lambdaBindings = /* @__PURE__ */ new Map();
|
|
3503
3708
|
this.intervalBindings = /* @__PURE__ */ new Map();
|
|
@@ -3601,11 +3806,23 @@ var require_lowering = __commonJS({
|
|
|
3601
3806
|
}
|
|
3602
3807
|
preScanExpr(expr, paramNames, macroParams) {
|
|
3603
3808
|
if (expr.kind === "call" && BUILTINS2[expr.fn] !== void 0) {
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3809
|
+
const handler = BUILTINS2[expr.fn];
|
|
3810
|
+
const isSpecialHandled = (() => {
|
|
3811
|
+
try {
|
|
3812
|
+
return handler() === null;
|
|
3813
|
+
} catch {
|
|
3814
|
+
return false;
|
|
3815
|
+
}
|
|
3816
|
+
})();
|
|
3817
|
+
if (!isSpecialHandled) {
|
|
3818
|
+
for (const arg of expr.args) {
|
|
3819
|
+
if (arg.kind === "ident" && paramNames.has(arg.name)) {
|
|
3820
|
+
macroParams.add(arg.name);
|
|
3821
|
+
}
|
|
3607
3822
|
}
|
|
3608
3823
|
}
|
|
3824
|
+
for (const arg of expr.args)
|
|
3825
|
+
this.preScanExpr(arg, paramNames, macroParams);
|
|
3609
3826
|
return;
|
|
3610
3827
|
}
|
|
3611
3828
|
if (expr.kind === "call") {
|
|
@@ -3670,6 +3887,12 @@ var require_lowering = __commonJS({
|
|
|
3670
3887
|
if (expr.kind === "struct_lit" || expr.kind === "array_lit") {
|
|
3671
3888
|
return { str: this.exprToSnbt(expr) };
|
|
3672
3889
|
}
|
|
3890
|
+
if (expr.kind === "float_lit") {
|
|
3891
|
+
return { str: expr.value.toString() };
|
|
3892
|
+
}
|
|
3893
|
+
if (expr.kind === "unary" && expr.op === "-" && expr.operand.kind === "float_lit") {
|
|
3894
|
+
return { str: (-expr.operand.value).toString() };
|
|
3895
|
+
}
|
|
3673
3896
|
return { str: this.exprToString(expr) };
|
|
3674
3897
|
}
|
|
3675
3898
|
/**
|
|
@@ -3682,9 +3905,9 @@ var require_lowering = __commonJS({
|
|
|
3682
3905
|
for (let i = 0; i < loweredArgs.length; i++) {
|
|
3683
3906
|
const operand = loweredArgs[i];
|
|
3684
3907
|
if (operand.kind === "const") {
|
|
3685
|
-
this.builder.emitRaw(`scoreboard players set $p${i}
|
|
3908
|
+
this.builder.emitRaw(`scoreboard players set $p${i} ${exports2.LOWERING_OBJ} ${operand.value}`);
|
|
3686
3909
|
} else if (operand.kind === "var") {
|
|
3687
|
-
this.builder.emitRaw(`scoreboard players operation $p${i}
|
|
3910
|
+
this.builder.emitRaw(`scoreboard players operation $p${i} ${exports2.LOWERING_OBJ} = ${operand.name} ${exports2.LOWERING_OBJ}`);
|
|
3688
3911
|
}
|
|
3689
3912
|
}
|
|
3690
3913
|
for (const macroParam of macroParamNames) {
|
|
@@ -3695,12 +3918,12 @@ var require_lowering = __commonJS({
|
|
|
3695
3918
|
if (operand.kind === "const") {
|
|
3696
3919
|
this.builder.emitRaw(`data modify storage rs:macro_args ${macroParam} set value ${operand.value}`);
|
|
3697
3920
|
} else if (operand.kind === "var") {
|
|
3698
|
-
this.builder.emitRaw(`execute store result storage rs:macro_args ${macroParam} int 1 run scoreboard players get ${operand.name}
|
|
3921
|
+
this.builder.emitRaw(`execute store result storage rs:macro_args ${macroParam} int 1 run scoreboard players get ${operand.name} ${exports2.LOWERING_OBJ}`);
|
|
3699
3922
|
}
|
|
3700
3923
|
}
|
|
3701
3924
|
this.builder.emitRaw(`function ${this.namespace}:${fnName} with storage rs:macro_args`);
|
|
3702
3925
|
const dst = this.builder.freshTemp();
|
|
3703
|
-
this.builder.emitRaw(`scoreboard players operation ${dst}
|
|
3926
|
+
this.builder.emitRaw(`scoreboard players operation ${dst} ${exports2.LOWERING_OBJ} = $ret ${exports2.LOWERING_OBJ}`);
|
|
3704
3927
|
return { kind: "var", name: dst };
|
|
3705
3928
|
}
|
|
3706
3929
|
lower(program) {
|
|
@@ -3796,12 +4019,12 @@ var require_lowering = __commonJS({
|
|
|
3796
4019
|
this.stringValues.set(param.name, "");
|
|
3797
4020
|
continue;
|
|
3798
4021
|
}
|
|
3799
|
-
this.varMap.set(param.name,
|
|
4022
|
+
this.varMap.set(param.name, this.fnVar(param.name));
|
|
3800
4023
|
}
|
|
3801
4024
|
} else {
|
|
3802
4025
|
for (const param of runtimeParams) {
|
|
3803
4026
|
const paramName = param.name;
|
|
3804
|
-
this.varMap.set(paramName,
|
|
4027
|
+
this.varMap.set(paramName, this.fnVar(paramName));
|
|
3805
4028
|
this.varTypes.set(paramName, this.normalizeType(param.type));
|
|
3806
4029
|
}
|
|
3807
4030
|
}
|
|
@@ -3813,15 +4036,15 @@ var require_lowering = __commonJS({
|
|
|
3813
4036
|
this.builder.startBlock("entry");
|
|
3814
4037
|
for (let i = 0; i < runtimeParams.length; i++) {
|
|
3815
4038
|
const paramName = runtimeParams[i].name;
|
|
3816
|
-
const varName =
|
|
3817
|
-
this.builder.emitAssign(varName, { kind: "
|
|
4039
|
+
const varName = this.fnVar(paramName);
|
|
4040
|
+
this.builder.emitAssign(varName, { kind: "param", index: i });
|
|
3818
4041
|
}
|
|
3819
4042
|
if (staticEventDec) {
|
|
3820
4043
|
for (let i = 0; i < fn.params.length; i++) {
|
|
3821
4044
|
const param = fn.params[i];
|
|
3822
4045
|
const expected = eventParamSpecs[i];
|
|
3823
4046
|
if (expected?.type.kind === "named" && expected.type.name !== "string") {
|
|
3824
|
-
this.builder.emitAssign(
|
|
4047
|
+
this.builder.emitAssign(this.fnVar(param.name), { kind: "const", value: 0 });
|
|
3825
4048
|
}
|
|
3826
4049
|
}
|
|
3827
4050
|
}
|
|
@@ -3868,6 +4091,19 @@ var require_lowering = __commonJS({
|
|
|
3868
4091
|
if (fn.decorators.some((d) => d.name === "load")) {
|
|
3869
4092
|
irFn.isLoadInit = true;
|
|
3870
4093
|
}
|
|
4094
|
+
const requiredLoads = [];
|
|
4095
|
+
for (const d of fn.decorators) {
|
|
4096
|
+
if (d.name === "require_on_load") {
|
|
4097
|
+
for (const arg of d.rawArgs ?? []) {
|
|
4098
|
+
if (arg.kind === "string") {
|
|
4099
|
+
requiredLoads.push(arg.value);
|
|
4100
|
+
}
|
|
4101
|
+
}
|
|
4102
|
+
}
|
|
4103
|
+
}
|
|
4104
|
+
if (requiredLoads.length > 0) {
|
|
4105
|
+
irFn.requiredLoads = requiredLoads;
|
|
4106
|
+
}
|
|
3871
4107
|
if (tickRate && tickRate > 1) {
|
|
3872
4108
|
this.wrapWithTickRate(irFn, tickRate);
|
|
3873
4109
|
}
|
|
@@ -3889,7 +4125,7 @@ var require_lowering = __commonJS({
|
|
|
3889
4125
|
const originalInstrs = [...entry.instrs];
|
|
3890
4126
|
const originalTerm = entry.term;
|
|
3891
4127
|
entry.instrs = [
|
|
3892
|
-
{ op: "raw", cmd: `scoreboard players add ${counterVar}
|
|
4128
|
+
{ op: "raw", cmd: `scoreboard players add ${counterVar} ${exports2.LOWERING_OBJ} 1` }
|
|
3893
4129
|
];
|
|
3894
4130
|
const bodyLabel = "tick_body";
|
|
3895
4131
|
const skipLabel = "tick_skip";
|
|
@@ -3901,12 +4137,12 @@ var require_lowering = __commonJS({
|
|
|
3901
4137
|
};
|
|
3902
4138
|
entry.instrs.push({
|
|
3903
4139
|
op: "raw",
|
|
3904
|
-
cmd: `execute store success score ${counterVar}_check
|
|
4140
|
+
cmd: `execute store success score ${counterVar}_check ${exports2.LOWERING_OBJ} if score ${counterVar} ${exports2.LOWERING_OBJ} matches ${rate}..`
|
|
3905
4141
|
});
|
|
3906
4142
|
fn.blocks.push({
|
|
3907
4143
|
label: bodyLabel,
|
|
3908
4144
|
instrs: [
|
|
3909
|
-
{ op: "raw", cmd: `scoreboard players set ${counterVar}
|
|
4145
|
+
{ op: "raw", cmd: `scoreboard players set ${counterVar} ${exports2.LOWERING_OBJ} 0` },
|
|
3910
4146
|
...originalInstrs
|
|
3911
4147
|
],
|
|
3912
4148
|
term: originalTerm
|
|
@@ -3982,7 +4218,7 @@ var require_lowering = __commonJS({
|
|
|
3982
4218
|
if (this.currentContext.binding === stmt.name) {
|
|
3983
4219
|
throw new diagnostics_1.DiagnosticError("LoweringError", `Cannot redeclare foreach binding '${stmt.name}'`, stmt.span ?? { line: 0, col: 0 });
|
|
3984
4220
|
}
|
|
3985
|
-
const varName =
|
|
4221
|
+
const varName = this.fnVar(stmt.name);
|
|
3986
4222
|
this.varMap.set(stmt.name, varName);
|
|
3987
4223
|
const declaredType = stmt.type ? this.normalizeType(stmt.type) : this.inferExprType(stmt.init);
|
|
3988
4224
|
if (declaredType) {
|
|
@@ -4013,7 +4249,7 @@ var require_lowering = __commonJS({
|
|
|
4013
4249
|
if (fieldValue.kind === "const") {
|
|
4014
4250
|
this.builder.emitRaw(`data modify storage ${path3} set value ${fieldValue.value}`);
|
|
4015
4251
|
} else if (fieldValue.kind === "var") {
|
|
4016
|
-
this.builder.emitRaw(`execute store result storage ${path3} int 1 run scoreboard players get ${fieldValue.name}
|
|
4252
|
+
this.builder.emitRaw(`execute store result storage ${path3} int 1 run scoreboard players get ${fieldValue.name} ${exports2.LOWERING_OBJ}`);
|
|
4017
4253
|
}
|
|
4018
4254
|
}
|
|
4019
4255
|
return;
|
|
@@ -4039,7 +4275,7 @@ var require_lowering = __commonJS({
|
|
|
4039
4275
|
this.builder.emitRaw(`data modify storage rs:heap ${stmt.name} append value ${elemValue.value}`);
|
|
4040
4276
|
} else if (elemValue.kind === "var") {
|
|
4041
4277
|
this.builder.emitRaw(`data modify storage rs:heap ${stmt.name} append value 0`);
|
|
4042
|
-
this.builder.emitRaw(`execute store result storage rs:heap ${stmt.name}[-1] int 1 run scoreboard players get ${elemValue.name}
|
|
4278
|
+
this.builder.emitRaw(`execute store result storage rs:heap ${stmt.name}[-1] int 1 run scoreboard players get ${elemValue.name} ${exports2.LOWERING_OBJ}`);
|
|
4043
4279
|
}
|
|
4044
4280
|
}
|
|
4045
4281
|
return;
|
|
@@ -4079,7 +4315,7 @@ var require_lowering = __commonJS({
|
|
|
4079
4315
|
if (fieldValue.kind === "const") {
|
|
4080
4316
|
this.builder.emitRaw(`data modify storage ${path3} set value ${fieldValue.value}`);
|
|
4081
4317
|
} else if (fieldValue.kind === "var") {
|
|
4082
|
-
this.builder.emitRaw(`execute store result storage ${path3} int 1 run scoreboard players get ${fieldValue.name}
|
|
4318
|
+
this.builder.emitRaw(`execute store result storage ${path3} int 1 run scoreboard players get ${fieldValue.name} ${exports2.LOWERING_OBJ}`);
|
|
4083
4319
|
}
|
|
4084
4320
|
}
|
|
4085
4321
|
this.builder.emitReturn({ kind: "const", value: 0 });
|
|
@@ -4143,11 +4379,22 @@ var require_lowering = __commonJS({
|
|
|
4143
4379
|
throw new diagnostics_1.DiagnosticError("LoweringError", "'is' checks require an entity selector or entity binding", cond.span ?? stmt.span ?? { line: 0, col: 0 });
|
|
4144
4380
|
}
|
|
4145
4381
|
const mcType = ENTITY_TO_MC_TYPE[cond.entityType];
|
|
4382
|
+
const thenFnName = `${this.currentFn}/then_${this.foreachCounter++}`;
|
|
4146
4383
|
if (!mcType) {
|
|
4147
|
-
|
|
4384
|
+
const subtypes = (0, entity_hierarchy_1.getConcreteSubtypes)(cond.entityType);
|
|
4385
|
+
if (subtypes.length === 0) {
|
|
4386
|
+
throw new diagnostics_1.DiagnosticError("LoweringError", `Cannot lower entity type check for '${cond.entityType}'`, cond.span ?? stmt.span ?? { line: 0, col: 0 });
|
|
4387
|
+
}
|
|
4388
|
+
this.builder.emitRaw(`scoreboard players set __is_result rs:temp 0`);
|
|
4389
|
+
for (const subtype of subtypes) {
|
|
4390
|
+
if (subtype.mcId) {
|
|
4391
|
+
this.builder.emitRaw(`execute if entity ${this.appendTypeFilter(selector, subtype.mcId)} run scoreboard players set __is_result rs:temp 1`);
|
|
4392
|
+
}
|
|
4393
|
+
}
|
|
4394
|
+
this.builder.emitRaw(`execute if score __is_result rs:temp matches 1 run function ${this.namespace}:${thenFnName}`);
|
|
4395
|
+
} else {
|
|
4396
|
+
this.builder.emitRaw(`execute if entity ${this.appendTypeFilter(selector, mcType)} run function ${this.namespace}:${thenFnName}`);
|
|
4148
4397
|
}
|
|
4149
|
-
const thenFnName = `${this.currentFn}/then_${this.foreachCounter++}`;
|
|
4150
|
-
this.builder.emitRaw(`execute if entity ${this.appendTypeFilter(selector, mcType)} run function ${this.namespace}:${thenFnName}`);
|
|
4151
4398
|
const savedBuilder = this.builder;
|
|
4152
4399
|
const savedVarMap = new Map(this.varMap);
|
|
4153
4400
|
const savedBlockPosVars = new Map(this.blockPosVars);
|
|
@@ -4208,14 +4455,14 @@ var require_lowering = __commonJS({
|
|
|
4208
4455
|
this.builder.startBlock(exitLabel);
|
|
4209
4456
|
}
|
|
4210
4457
|
lowerForRangeStmt(stmt) {
|
|
4211
|
-
const loopVar =
|
|
4458
|
+
const loopVar = this.fnVar(stmt.varName);
|
|
4212
4459
|
const subFnName = `${this.currentFn}/__for_${this.foreachCounter++}`;
|
|
4213
4460
|
this.varMap.set(stmt.varName, loopVar);
|
|
4214
4461
|
const startVal = this.lowerExpr(stmt.start);
|
|
4215
4462
|
if (startVal.kind === "const") {
|
|
4216
|
-
this.builder.emitRaw(`scoreboard players set ${loopVar}
|
|
4463
|
+
this.builder.emitRaw(`scoreboard players set ${loopVar} ${exports2.LOWERING_OBJ} ${startVal.value}`);
|
|
4217
4464
|
} else if (startVal.kind === "var") {
|
|
4218
|
-
this.builder.emitRaw(`scoreboard players operation ${loopVar}
|
|
4465
|
+
this.builder.emitRaw(`scoreboard players operation ${loopVar} ${exports2.LOWERING_OBJ} = ${startVal.name} ${exports2.LOWERING_OBJ}`);
|
|
4219
4466
|
}
|
|
4220
4467
|
this.builder.emitRaw(`function ${this.namespace}:${subFnName}`);
|
|
4221
4468
|
const savedBuilder = this.builder;
|
|
@@ -4228,10 +4475,10 @@ var require_lowering = __commonJS({
|
|
|
4228
4475
|
this.blockPosVars = new Map(savedBlockPosVars);
|
|
4229
4476
|
this.builder.startBlock("entry");
|
|
4230
4477
|
this.lowerBlock(stmt.body);
|
|
4231
|
-
this.builder.emitRaw(`scoreboard players add ${loopVar}
|
|
4478
|
+
this.builder.emitRaw(`scoreboard players add ${loopVar} ${exports2.LOWERING_OBJ} 1`);
|
|
4232
4479
|
const endVal = this.lowerExpr(stmt.end);
|
|
4233
4480
|
const endNum = endVal.kind === "const" ? endVal.value - 1 : "?";
|
|
4234
|
-
this.builder.emitRaw(`execute if score ${loopVar}
|
|
4481
|
+
this.builder.emitRaw(`execute if score ${loopVar} ${exports2.LOWERING_OBJ} matches ..${endNum} run function ${this.namespace}:${subFnName}`);
|
|
4235
4482
|
if (!this.builder.isBlockSealed()) {
|
|
4236
4483
|
this.builder.emitReturn();
|
|
4237
4484
|
}
|
|
@@ -4260,11 +4507,18 @@ var require_lowering = __commonJS({
|
|
|
4260
4507
|
this.currentContext = { binding: stmt.binding };
|
|
4261
4508
|
this.blockPosVars = new Map(savedBlockPosVars);
|
|
4262
4509
|
this.varMap.set(stmt.binding, "@s");
|
|
4510
|
+
const selectorEntityType = (0, entity_hierarchy_1.getBaseSelectorType)(selector);
|
|
4511
|
+
if (selectorEntityType) {
|
|
4512
|
+
this.entityContextStack.push(selectorEntityType);
|
|
4513
|
+
}
|
|
4263
4514
|
this.builder.startBlock("entry");
|
|
4264
4515
|
this.lowerBlock(stmt.body);
|
|
4265
4516
|
if (!this.builder.isBlockSealed()) {
|
|
4266
4517
|
this.builder.emitReturn();
|
|
4267
4518
|
}
|
|
4519
|
+
if (selectorEntityType) {
|
|
4520
|
+
this.entityContextStack.pop();
|
|
4521
|
+
}
|
|
4268
4522
|
const subFn = this.builder.build(subFnName, [], false);
|
|
4269
4523
|
this.functions.push(subFn);
|
|
4270
4524
|
this.builder = savedBuilder;
|
|
@@ -4302,12 +4556,12 @@ var require_lowering = __commonJS({
|
|
|
4302
4556
|
matchCondition = String(patternValue.value);
|
|
4303
4557
|
}
|
|
4304
4558
|
const subFnName = `${this.currentFn}/match_${this.foreachCounter++}`;
|
|
4305
|
-
this.builder.emitRaw(`execute if score ${matchedVar}
|
|
4559
|
+
this.builder.emitRaw(`execute if score ${matchedVar} ${exports2.LOWERING_OBJ} matches ..0 if score ${subject} ${exports2.LOWERING_OBJ} matches ${matchCondition} run function ${this.namespace}:${subFnName}`);
|
|
4306
4560
|
this.emitMatchArmSubFunction(subFnName, matchedVar, arm.body, true);
|
|
4307
4561
|
}
|
|
4308
4562
|
if (defaultArm) {
|
|
4309
4563
|
const subFnName = `${this.currentFn}/match_${this.foreachCounter++}`;
|
|
4310
|
-
this.builder.emitRaw(`execute if score ${matchedVar}
|
|
4564
|
+
this.builder.emitRaw(`execute if score ${matchedVar} ${exports2.LOWERING_OBJ} matches ..0 run function ${this.namespace}:${subFnName}`);
|
|
4311
4565
|
this.emitMatchArmSubFunction(subFnName, matchedVar, defaultArm.body, false);
|
|
4312
4566
|
}
|
|
4313
4567
|
}
|
|
@@ -4322,7 +4576,7 @@ var require_lowering = __commonJS({
|
|
|
4322
4576
|
this.blockPosVars = new Map(savedBlockPosVars);
|
|
4323
4577
|
this.builder.startBlock("entry");
|
|
4324
4578
|
if (setMatched) {
|
|
4325
|
-
this.builder.emitRaw(`scoreboard players set ${matchedVar}
|
|
4579
|
+
this.builder.emitRaw(`scoreboard players set ${matchedVar} ${exports2.LOWERING_OBJ} 1`);
|
|
4326
4580
|
}
|
|
4327
4581
|
this.lowerBlock(body);
|
|
4328
4582
|
if (!this.builder.isBlockSealed()) {
|
|
@@ -4341,7 +4595,7 @@ var require_lowering = __commonJS({
|
|
|
4341
4595
|
return;
|
|
4342
4596
|
}
|
|
4343
4597
|
const arrayType = this.inferExprType(stmt.iterable);
|
|
4344
|
-
const bindingVar =
|
|
4598
|
+
const bindingVar = this.fnVar(stmt.binding);
|
|
4345
4599
|
const indexVar = this.builder.freshTemp();
|
|
4346
4600
|
const lengthVar = this.builder.freshTemp();
|
|
4347
4601
|
const condVar = this.builder.freshTemp();
|
|
@@ -4354,7 +4608,7 @@ var require_lowering = __commonJS({
|
|
|
4354
4608
|
}
|
|
4355
4609
|
this.builder.emitAssign(indexVar, { kind: "const", value: 0 });
|
|
4356
4610
|
this.builder.emitAssign(oneVar, { kind: "const", value: 1 });
|
|
4357
|
-
this.builder.emitRaw(`execute store result score ${lengthVar}
|
|
4611
|
+
this.builder.emitRaw(`execute store result score ${lengthVar} ${exports2.LOWERING_OBJ} run data get storage rs:heap ${arrayName}`);
|
|
4358
4612
|
const checkLabel = this.builder.freshLabel("foreach_array_check");
|
|
4359
4613
|
const bodyLabel = this.builder.freshLabel("foreach_array_body");
|
|
4360
4614
|
const exitLabel = this.builder.freshLabel("foreach_array_exit");
|
|
@@ -4367,7 +4621,7 @@ var require_lowering = __commonJS({
|
|
|
4367
4621
|
this.builder.emitAssign(bindingVar, element);
|
|
4368
4622
|
this.lowerBlock(stmt.body);
|
|
4369
4623
|
if (!this.builder.isBlockSealed()) {
|
|
4370
|
-
this.builder.emitRaw(`scoreboard players operation ${indexVar}
|
|
4624
|
+
this.builder.emitRaw(`scoreboard players operation ${indexVar} ${exports2.LOWERING_OBJ} += ${oneVar} ${exports2.LOWERING_OBJ}`);
|
|
4371
4625
|
this.builder.emitJump(checkLabel);
|
|
4372
4626
|
}
|
|
4373
4627
|
this.builder.startBlock(exitLabel);
|
|
@@ -4385,6 +4639,16 @@ var require_lowering = __commonJS({
|
|
|
4385
4639
|
lowerAsBlockStmt(stmt) {
|
|
4386
4640
|
const selector = this.selectorToString(stmt.selector);
|
|
4387
4641
|
const subFnName = `${this.currentFn}/as_${this.foreachCounter++}`;
|
|
4642
|
+
const innerType = (0, entity_hierarchy_1.getBaseSelectorType)(selector);
|
|
4643
|
+
const outerType = this.currentEntityContext();
|
|
4644
|
+
if (innerType && outerType !== "Entity" && innerType !== "Entity" && !(0, entity_hierarchy_1.areCompatibleTypes)(outerType, innerType)) {
|
|
4645
|
+
this.warnings.push({
|
|
4646
|
+
message: `Impossible type assertion: @s is ${outerType} but as-block targets ${innerType}`,
|
|
4647
|
+
code: "W_IMPOSSIBLE_AS",
|
|
4648
|
+
line: stmt.span?.line,
|
|
4649
|
+
col: stmt.span?.col
|
|
4650
|
+
});
|
|
4651
|
+
}
|
|
4388
4652
|
this.builder.emitRaw(`execute as ${selector} run function ${this.namespace}:${subFnName}`);
|
|
4389
4653
|
const savedBuilder = this.builder;
|
|
4390
4654
|
const savedVarMap = new Map(this.varMap);
|
|
@@ -4392,11 +4656,17 @@ var require_lowering = __commonJS({
|
|
|
4392
4656
|
this.builder = new LoweringBuilder();
|
|
4393
4657
|
this.varMap = new Map(savedVarMap);
|
|
4394
4658
|
this.blockPosVars = new Map(savedBlockPosVars);
|
|
4659
|
+
if (innerType) {
|
|
4660
|
+
this.entityContextStack.push(innerType);
|
|
4661
|
+
}
|
|
4395
4662
|
this.builder.startBlock("entry");
|
|
4396
4663
|
this.lowerBlock(stmt.body);
|
|
4397
4664
|
if (!this.builder.isBlockSealed()) {
|
|
4398
4665
|
this.builder.emitReturn();
|
|
4399
4666
|
}
|
|
4667
|
+
if (innerType) {
|
|
4668
|
+
this.entityContextStack.pop();
|
|
4669
|
+
}
|
|
4400
4670
|
const subFn = this.builder.build(subFnName, [], false);
|
|
4401
4671
|
this.functions.push(subFn);
|
|
4402
4672
|
this.builder = savedBuilder;
|
|
@@ -4644,19 +4914,19 @@ var require_lowering = __commonJS({
|
|
|
4644
4914
|
const mapped = this.varMap.get(expr.obj.name);
|
|
4645
4915
|
if (mapped && mapped.startsWith("@e[tag=__rs_obj_")) {
|
|
4646
4916
|
const dst = this.builder.freshTemp();
|
|
4647
|
-
this.builder.emitRaw(`scoreboard players operation ${dst}
|
|
4917
|
+
this.builder.emitRaw(`scoreboard players operation ${dst} ${exports2.LOWERING_OBJ} = ${mapped} ${exports2.LOWERING_OBJ}`);
|
|
4648
4918
|
return { kind: "var", name: dst };
|
|
4649
4919
|
}
|
|
4650
4920
|
if (varType?.kind === "struct") {
|
|
4651
4921
|
const structName = varType.name.toLowerCase();
|
|
4652
4922
|
const path3 = `rs:heap ${structName}_${expr.obj.name}.${expr.field}`;
|
|
4653
4923
|
const dst = this.builder.freshTemp();
|
|
4654
|
-
this.builder.emitRaw(`execute store result score ${dst}
|
|
4924
|
+
this.builder.emitRaw(`execute store result score ${dst} ${exports2.LOWERING_OBJ} run data get storage ${path3}`);
|
|
4655
4925
|
return { kind: "var", name: dst };
|
|
4656
4926
|
}
|
|
4657
4927
|
if (varType?.kind === "array" && expr.field === "len") {
|
|
4658
4928
|
const dst = this.builder.freshTemp();
|
|
4659
|
-
this.builder.emitRaw(`execute store result score ${dst}
|
|
4929
|
+
this.builder.emitRaw(`execute store result score ${dst} ${exports2.LOWERING_OBJ} run data get storage rs:heap ${expr.obj.name}`);
|
|
4660
4930
|
return { kind: "var", name: dst };
|
|
4661
4931
|
}
|
|
4662
4932
|
}
|
|
@@ -4670,9 +4940,9 @@ var require_lowering = __commonJS({
|
|
|
4670
4940
|
const value2 = this.lowerExpr(expr.value);
|
|
4671
4941
|
if (expr.op === "=") {
|
|
4672
4942
|
if (value2.kind === "const") {
|
|
4673
|
-
this.builder.emitRaw(`scoreboard players set ${mapped}
|
|
4943
|
+
this.builder.emitRaw(`scoreboard players set ${mapped} ${exports2.LOWERING_OBJ} ${value2.value}`);
|
|
4674
4944
|
} else if (value2.kind === "var") {
|
|
4675
|
-
this.builder.emitRaw(`scoreboard players operation ${mapped}
|
|
4945
|
+
this.builder.emitRaw(`scoreboard players operation ${mapped} ${exports2.LOWERING_OBJ} = ${value2.name} ${exports2.LOWERING_OBJ}`);
|
|
4676
4946
|
}
|
|
4677
4947
|
} else {
|
|
4678
4948
|
const binOp = expr.op.slice(0, -1);
|
|
@@ -4680,9 +4950,9 @@ var require_lowering = __commonJS({
|
|
|
4680
4950
|
if (value2.kind === "const") {
|
|
4681
4951
|
const constTemp = this.builder.freshTemp();
|
|
4682
4952
|
this.builder.emitAssign(constTemp, value2);
|
|
4683
|
-
this.builder.emitRaw(`scoreboard players operation ${mapped}
|
|
4953
|
+
this.builder.emitRaw(`scoreboard players operation ${mapped} ${exports2.LOWERING_OBJ} ${opMap[binOp]} ${constTemp} ${exports2.LOWERING_OBJ}`);
|
|
4684
4954
|
} else if (value2.kind === "var") {
|
|
4685
|
-
this.builder.emitRaw(`scoreboard players operation ${mapped}
|
|
4955
|
+
this.builder.emitRaw(`scoreboard players operation ${mapped} ${exports2.LOWERING_OBJ} ${opMap[binOp]} ${value2.name} ${exports2.LOWERING_OBJ}`);
|
|
4686
4956
|
}
|
|
4687
4957
|
}
|
|
4688
4958
|
return { kind: "const", value: 0 };
|
|
@@ -4695,14 +4965,14 @@ var require_lowering = __commonJS({
|
|
|
4695
4965
|
if (value2.kind === "const") {
|
|
4696
4966
|
this.builder.emitRaw(`data modify storage ${path3} set value ${value2.value}`);
|
|
4697
4967
|
} else if (value2.kind === "var") {
|
|
4698
|
-
this.builder.emitRaw(`execute store result storage ${path3} int 1 run scoreboard players get ${value2.name}
|
|
4968
|
+
this.builder.emitRaw(`execute store result storage ${path3} int 1 run scoreboard players get ${value2.name} ${exports2.LOWERING_OBJ}`);
|
|
4699
4969
|
}
|
|
4700
4970
|
} else {
|
|
4701
4971
|
const dst = this.builder.freshTemp();
|
|
4702
|
-
this.builder.emitRaw(`execute store result score ${dst}
|
|
4972
|
+
this.builder.emitRaw(`execute store result score ${dst} ${exports2.LOWERING_OBJ} run data get storage ${path3}`);
|
|
4703
4973
|
const binOp = expr.op.slice(0, -1);
|
|
4704
4974
|
this.builder.emitBinop(dst, { kind: "var", name: dst }, binOp, value2);
|
|
4705
|
-
this.builder.emitRaw(`execute store result storage ${path3} int 1 run scoreboard players get ${dst}
|
|
4975
|
+
this.builder.emitRaw(`execute store result storage ${path3} int 1 run scoreboard players get ${dst} ${exports2.LOWERING_OBJ}`);
|
|
4706
4976
|
}
|
|
4707
4977
|
return { kind: "const", value: 0 };
|
|
4708
4978
|
}
|
|
@@ -4727,11 +4997,11 @@ var require_lowering = __commonJS({
|
|
|
4727
4997
|
if (expr.op === "&&") {
|
|
4728
4998
|
this.builder.emitAssign(dst, left);
|
|
4729
4999
|
const rightVar = this.operandToVar(right);
|
|
4730
|
-
this.builder.emitRaw(`execute if score ${dst}
|
|
5000
|
+
this.builder.emitRaw(`execute if score ${dst} ${exports2.LOWERING_OBJ} matches 1.. run scoreboard players operation ${dst} ${exports2.LOWERING_OBJ} = ${rightVar} ${exports2.LOWERING_OBJ}`);
|
|
4731
5001
|
} else {
|
|
4732
5002
|
this.builder.emitAssign(dst, left);
|
|
4733
5003
|
const rightVar = this.operandToVar(right);
|
|
4734
|
-
this.builder.emitRaw(`execute if score ${dst}
|
|
5004
|
+
this.builder.emitRaw(`execute if score ${dst} ${exports2.LOWERING_OBJ} matches ..0 run scoreboard players operation ${dst} ${exports2.LOWERING_OBJ} = ${rightVar} ${exports2.LOWERING_OBJ}`);
|
|
4735
5005
|
}
|
|
4736
5006
|
return { kind: "var", name: dst };
|
|
4737
5007
|
}
|
|
@@ -4744,14 +5014,14 @@ var require_lowering = __commonJS({
|
|
|
4744
5014
|
this.builder.emitBinop(dst, left, "*", right);
|
|
4745
5015
|
const constDiv = this.builder.freshTemp();
|
|
4746
5016
|
this.builder.emitAssign(constDiv, { kind: "const", value: 1e3 });
|
|
4747
|
-
this.builder.emitRaw(`scoreboard players operation ${dst}
|
|
5017
|
+
this.builder.emitRaw(`scoreboard players operation ${dst} ${exports2.LOWERING_OBJ} /= ${constDiv} ${exports2.LOWERING_OBJ}`);
|
|
4748
5018
|
} else {
|
|
4749
5019
|
const constMul = this.builder.freshTemp();
|
|
4750
5020
|
this.builder.emitAssign(constMul, { kind: "const", value: 1e3 });
|
|
4751
5021
|
this.builder.emitAssign(dst, left);
|
|
4752
|
-
this.builder.emitRaw(`scoreboard players operation ${dst}
|
|
5022
|
+
this.builder.emitRaw(`scoreboard players operation ${dst} ${exports2.LOWERING_OBJ} *= ${constMul} ${exports2.LOWERING_OBJ}`);
|
|
4753
5023
|
const rightVar = this.operandToVar(right);
|
|
4754
|
-
this.builder.emitRaw(`scoreboard players operation ${dst}
|
|
5024
|
+
this.builder.emitRaw(`scoreboard players operation ${dst} ${exports2.LOWERING_OBJ} /= ${rightVar} ${exports2.LOWERING_OBJ}`);
|
|
4755
5025
|
}
|
|
4756
5026
|
return { kind: "var", name: dst };
|
|
4757
5027
|
}
|
|
@@ -4815,7 +5085,7 @@ var require_lowering = __commonJS({
|
|
|
4815
5085
|
const storagePath = this.getStringStoragePath(expr.args[0]);
|
|
4816
5086
|
if (storagePath) {
|
|
4817
5087
|
const dst = this.builder.freshTemp();
|
|
4818
|
-
this.builder.emitRaw(`execute store result score ${dst}
|
|
5088
|
+
this.builder.emitRaw(`execute store result score ${dst} ${exports2.LOWERING_OBJ} run data get storage ${storagePath}`);
|
|
4819
5089
|
return { kind: "var", name: dst };
|
|
4820
5090
|
}
|
|
4821
5091
|
const staticString = this.resolveStaticString(expr.args[0]);
|
|
@@ -4846,7 +5116,7 @@ var require_lowering = __commonJS({
|
|
|
4846
5116
|
const entity = this.exprToString(expr.args[0]);
|
|
4847
5117
|
const tagName = this.exprToString(expr.args[1]);
|
|
4848
5118
|
const dst = this.builder.freshTemp();
|
|
4849
|
-
this.builder.emitRaw(`execute store result score ${dst}
|
|
5119
|
+
this.builder.emitRaw(`execute store result score ${dst} ${exports2.LOWERING_OBJ} if entity ${entity}[tag=${tagName}]`);
|
|
4850
5120
|
return { kind: "var", name: dst };
|
|
4851
5121
|
}
|
|
4852
5122
|
if (expr.fn === "__array_push") {
|
|
@@ -4859,7 +5129,7 @@ var require_lowering = __commonJS({
|
|
|
4859
5129
|
this.builder.emitRaw(`data modify storage rs:heap ${arrName} append value ${value.value}`);
|
|
4860
5130
|
} else if (value.kind === "var") {
|
|
4861
5131
|
this.builder.emitRaw(`data modify storage rs:heap ${arrName} append value 0`);
|
|
4862
|
-
this.builder.emitRaw(`execute store result storage rs:heap ${arrName}[-1] int 1 run scoreboard players get ${value.name}
|
|
5132
|
+
this.builder.emitRaw(`execute store result storage rs:heap ${arrName}[-1] int 1 run scoreboard players get ${value.name} ${exports2.LOWERING_OBJ}`);
|
|
4863
5133
|
}
|
|
4864
5134
|
}
|
|
4865
5135
|
return { kind: "const", value: 0 };
|
|
@@ -4868,7 +5138,7 @@ var require_lowering = __commonJS({
|
|
|
4868
5138
|
const arrName = this.getArrayStorageName(expr.args[0]);
|
|
4869
5139
|
const dst = this.builder.freshTemp();
|
|
4870
5140
|
if (arrName) {
|
|
4871
|
-
this.builder.emitRaw(`execute store result score ${dst}
|
|
5141
|
+
this.builder.emitRaw(`execute store result score ${dst} ${exports2.LOWERING_OBJ} run data get storage rs:heap ${arrName}[-1]`);
|
|
4872
5142
|
this.builder.emitRaw(`data remove storage rs:heap ${arrName}[-1]`);
|
|
4873
5143
|
} else {
|
|
4874
5144
|
this.builder.emitAssign(dst, { kind: "const", value: 0 });
|
|
@@ -5117,14 +5387,14 @@ var require_lowering = __commonJS({
|
|
|
5117
5387
|
const dst = this.builder.freshTemp();
|
|
5118
5388
|
const min = args[0] ? this.exprToLiteral(args[0]) : "0";
|
|
5119
5389
|
const max = args[1] ? this.exprToLiteral(args[1]) : "100";
|
|
5120
|
-
this.builder.emitRaw(`scoreboard players random ${dst}
|
|
5390
|
+
this.builder.emitRaw(`scoreboard players random ${dst} ${exports2.LOWERING_OBJ} ${min} ${max}`);
|
|
5121
5391
|
return { kind: "var", name: dst };
|
|
5122
5392
|
}
|
|
5123
5393
|
if (name === "random_native") {
|
|
5124
5394
|
const dst = this.builder.freshTemp();
|
|
5125
5395
|
const min = args[0] ? this.exprToLiteral(args[0]) : "0";
|
|
5126
5396
|
const max = args[1] ? this.exprToLiteral(args[1]) : "100";
|
|
5127
|
-
this.builder.emitRaw(`execute store result score ${dst}
|
|
5397
|
+
this.builder.emitRaw(`execute store result score ${dst} ${exports2.LOWERING_OBJ} run random value ${min} ${max}`);
|
|
5128
5398
|
return { kind: "var", name: dst };
|
|
5129
5399
|
}
|
|
5130
5400
|
if (name === "random_sequence") {
|
|
@@ -5137,7 +5407,7 @@ var require_lowering = __commonJS({
|
|
|
5137
5407
|
const dst = this.builder.freshTemp();
|
|
5138
5408
|
const player = this.exprToTargetString(args[0]);
|
|
5139
5409
|
const objective = this.resolveScoreboardObjective(args[0], args[1], callSpan);
|
|
5140
|
-
this.builder.emitRaw(`execute store result score ${dst}
|
|
5410
|
+
this.builder.emitRaw(`execute store result score ${dst} ${exports2.LOWERING_OBJ} run scoreboard players get ${player} ${objective}`);
|
|
5141
5411
|
return { kind: "var", name: dst };
|
|
5142
5412
|
}
|
|
5143
5413
|
if (name === "scoreboard_set") {
|
|
@@ -5147,7 +5417,7 @@ var require_lowering = __commonJS({
|
|
|
5147
5417
|
if (value.kind === "const") {
|
|
5148
5418
|
this.builder.emitRaw(`scoreboard players set ${player} ${objective} ${value.value}`);
|
|
5149
5419
|
} else if (value.kind === "var") {
|
|
5150
|
-
this.builder.emitRaw(`execute store result score ${player} ${objective} run scoreboard players get ${value.name}
|
|
5420
|
+
this.builder.emitRaw(`execute store result score ${player} ${objective} run scoreboard players get ${value.name} ${exports2.LOWERING_OBJ}`);
|
|
5151
5421
|
}
|
|
5152
5422
|
return { kind: "const", value: 0 };
|
|
5153
5423
|
}
|
|
@@ -5210,7 +5480,7 @@ var require_lowering = __commonJS({
|
|
|
5210
5480
|
}
|
|
5211
5481
|
if (name === "bossbar_get_value") {
|
|
5212
5482
|
const dst = this.builder.freshTemp();
|
|
5213
|
-
this.builder.emitRaw(`execute store result score ${dst}
|
|
5483
|
+
this.builder.emitRaw(`execute store result score ${dst} ${exports2.LOWERING_OBJ} run bossbar get ${this.exprToString(args[0])} value`);
|
|
5214
5484
|
return { kind: "var", name: dst };
|
|
5215
5485
|
}
|
|
5216
5486
|
if (name === "team_add") {
|
|
@@ -5244,9 +5514,54 @@ var require_lowering = __commonJS({
|
|
|
5244
5514
|
const target = targetType === "entity" ? this.exprToTargetString(args[1]) : this.exprToString(args[1]);
|
|
5245
5515
|
const path3 = this.exprToString(args[2]);
|
|
5246
5516
|
const scale = args[3] ? this.exprToString(args[3]) : "1";
|
|
5247
|
-
this.builder.emitRaw(`execute store result score ${dst}
|
|
5517
|
+
this.builder.emitRaw(`execute store result score ${dst} ${exports2.LOWERING_OBJ} run data get ${targetType} ${target} ${path3} ${scale}`);
|
|
5518
|
+
return { kind: "var", name: dst };
|
|
5519
|
+
}
|
|
5520
|
+
if (name === "storage_get_int") {
|
|
5521
|
+
const storageNs = this.exprToString(args[0]);
|
|
5522
|
+
const arrayKey = this.exprToString(args[1]);
|
|
5523
|
+
const indexOperand = this.lowerExpr(args[2]);
|
|
5524
|
+
const dst = this.builder.freshTemp();
|
|
5525
|
+
if (indexOperand.kind === "const") {
|
|
5526
|
+
this.builder.emitRaw(`execute store result score ${dst} ${exports2.LOWERING_OBJ} run data get storage ${storageNs} ${arrayKey}[${indexOperand.value}] 1`);
|
|
5527
|
+
} else {
|
|
5528
|
+
const macroKey = `__sgi_${this.foreachCounter++}`;
|
|
5529
|
+
const subFnName = `${this.currentFn}/__sgi_${this.foreachCounter++}`;
|
|
5530
|
+
const indexVar = indexOperand.kind === "var" ? indexOperand.name : this.operandToVar(indexOperand);
|
|
5531
|
+
this.builder.emitRaw(`execute store result storage rs:heap ${macroKey} int 1 run scoreboard players get ${indexVar} ${exports2.LOWERING_OBJ}`);
|
|
5532
|
+
this.builder.emitRaw(`function ${this.namespace}:${subFnName} with storage rs:heap`);
|
|
5533
|
+
this.emitRawSubFunction(subFnName, `execute store result score ${dst} ${exports2.LOWERING_OBJ} run data get storage ${storageNs} ${arrayKey}[$(${macroKey})] 1`);
|
|
5534
|
+
}
|
|
5248
5535
|
return { kind: "var", name: dst };
|
|
5249
5536
|
}
|
|
5537
|
+
if (name === "storage_set_array") {
|
|
5538
|
+
const storageNs = this.exprToString(args[0]);
|
|
5539
|
+
const arrayKey = this.exprToString(args[1]);
|
|
5540
|
+
const nbtLiteral = this.exprToString(args[2]);
|
|
5541
|
+
this.builder.emitRaw(`data modify storage ${storageNs} ${arrayKey} set value ${nbtLiteral}`);
|
|
5542
|
+
return { kind: "const", value: 0 };
|
|
5543
|
+
}
|
|
5544
|
+
if (name === "storage_set_int") {
|
|
5545
|
+
const storageNs = this.exprToString(args[0]);
|
|
5546
|
+
const arrayKey = this.exprToString(args[1]);
|
|
5547
|
+
const indexOperand = this.lowerExpr(args[2]);
|
|
5548
|
+
const valueOperand = this.lowerExpr(args[3]);
|
|
5549
|
+
if (indexOperand.kind === "const") {
|
|
5550
|
+
const valVar = valueOperand.kind === "var" ? valueOperand.name : this.operandToVar(valueOperand);
|
|
5551
|
+
this.builder.emitRaw(`execute store result storage ${storageNs} ${arrayKey}[${indexOperand.value}] int 1 run scoreboard players get ${valVar} ${exports2.LOWERING_OBJ}`);
|
|
5552
|
+
} else {
|
|
5553
|
+
const macroIdxKey = `__ssi_i_${this.foreachCounter++}`;
|
|
5554
|
+
const macroValKey = `__ssi_v_${this.foreachCounter++}`;
|
|
5555
|
+
const subFnName = `${this.currentFn}/__ssi_${this.foreachCounter++}`;
|
|
5556
|
+
const indexVar = indexOperand.kind === "var" ? indexOperand.name : this.operandToVar(indexOperand);
|
|
5557
|
+
const valVar = valueOperand.kind === "var" ? valueOperand.name : this.operandToVar(valueOperand);
|
|
5558
|
+
this.builder.emitRaw(`execute store result storage rs:heap ${macroIdxKey} int 1 run scoreboard players get ${indexVar} ${exports2.LOWERING_OBJ}`);
|
|
5559
|
+
this.builder.emitRaw(`execute store result storage rs:heap ${macroValKey} int 1 run scoreboard players get ${valVar} ${exports2.LOWERING_OBJ}`);
|
|
5560
|
+
this.builder.emitRaw(`function ${this.namespace}:${subFnName} with storage rs:heap`);
|
|
5561
|
+
this.emitRawSubFunction(subFnName, `execute store result storage ${storageNs} ${arrayKey}[$(${macroIdxKey})] int 1 run scoreboard players get ${valVar} ${exports2.LOWERING_OBJ}`);
|
|
5562
|
+
}
|
|
5563
|
+
return { kind: "const", value: 0 };
|
|
5564
|
+
}
|
|
5250
5565
|
if (name === "data_merge") {
|
|
5251
5566
|
const target = args[0];
|
|
5252
5567
|
const nbt = args[1];
|
|
@@ -5279,7 +5594,7 @@ var require_lowering = __commonJS({
|
|
|
5279
5594
|
const dst = this.builder.freshTemp();
|
|
5280
5595
|
const setId = this.exprToString(args[0]);
|
|
5281
5596
|
const value = this.exprToString(args[1]);
|
|
5282
|
-
this.builder.emitRaw(`execute store result score ${dst}
|
|
5597
|
+
this.builder.emitRaw(`execute store result score ${dst} ${exports2.LOWERING_OBJ} if data storage rs:sets ${setId}[{value:${value}}]`);
|
|
5283
5598
|
return { kind: "var", name: dst };
|
|
5284
5599
|
}
|
|
5285
5600
|
if (name === "set_remove") {
|
|
@@ -5543,7 +5858,7 @@ var require_lowering = __commonJS({
|
|
|
5543
5858
|
components.push({ text: operand.value.toString() });
|
|
5544
5859
|
return;
|
|
5545
5860
|
}
|
|
5546
|
-
components.push({ score: { name: this.operandToVar(operand), objective:
|
|
5861
|
+
components.push({ score: { name: this.operandToVar(operand), objective: exports2.LOWERING_OBJ } });
|
|
5547
5862
|
}
|
|
5548
5863
|
exprToString(expr) {
|
|
5549
5864
|
switch (expr.kind) {
|
|
@@ -5696,11 +6011,15 @@ var require_lowering = __commonJS({
|
|
|
5696
6011
|
}
|
|
5697
6012
|
exprToScoreboardObjective(expr, span) {
|
|
5698
6013
|
if (expr.kind === "mc_name") {
|
|
5699
|
-
return expr.value;
|
|
6014
|
+
return expr.value === "rs" ? exports2.LOWERING_OBJ : expr.value;
|
|
5700
6015
|
}
|
|
5701
6016
|
const objective = this.exprToString(expr);
|
|
5702
6017
|
if (objective.startsWith("#") || objective.includes(".")) {
|
|
5703
|
-
|
|
6018
|
+
if (objective.startsWith("#")) {
|
|
6019
|
+
const name = objective.slice(1);
|
|
6020
|
+
return name === "rs" ? exports2.LOWERING_OBJ : name;
|
|
6021
|
+
}
|
|
6022
|
+
return objective;
|
|
5704
6023
|
}
|
|
5705
6024
|
return `${this.getObjectiveNamespace(span)}.${objective}`;
|
|
5706
6025
|
}
|
|
@@ -5716,7 +6035,7 @@ var require_lowering = __commonJS({
|
|
|
5716
6035
|
if (!filePath) {
|
|
5717
6036
|
return this.namespace;
|
|
5718
6037
|
}
|
|
5719
|
-
return this.isStdlibFile(filePath) ?
|
|
6038
|
+
return this.isStdlibFile(filePath) ? exports2.LOWERING_OBJ : this.namespace;
|
|
5720
6039
|
}
|
|
5721
6040
|
tryGetStdlibInternalObjective(playerExpr, objectiveExpr, span) {
|
|
5722
6041
|
if (!span || !this.currentStdlibCallSite || objectiveExpr.kind !== "mc_name" || objectiveExpr.value !== "rs") {
|
|
@@ -5731,7 +6050,7 @@ var require_lowering = __commonJS({
|
|
|
5731
6050
|
return null;
|
|
5732
6051
|
}
|
|
5733
6052
|
const hash = this.shortHash(this.serializeCallSite(this.currentStdlibCallSite));
|
|
5734
|
-
return
|
|
6053
|
+
return `${exports2.LOWERING_OBJ}._${resourceBase}_${hash}`;
|
|
5735
6054
|
}
|
|
5736
6055
|
getStdlibInternalResourceBase(playerExpr) {
|
|
5737
6056
|
if (!playerExpr || playerExpr.kind !== "str_lit") {
|
|
@@ -6011,15 +6330,15 @@ var require_lowering = __commonJS({
|
|
|
6011
6330
|
readArrayElement(arrayName, index) {
|
|
6012
6331
|
const dst = this.builder.freshTemp();
|
|
6013
6332
|
if (index.kind === "const") {
|
|
6014
|
-
this.builder.emitRaw(`execute store result score ${dst}
|
|
6333
|
+
this.builder.emitRaw(`execute store result score ${dst} ${exports2.LOWERING_OBJ} run data get storage rs:heap ${arrayName}[${index.value}]`);
|
|
6015
6334
|
return { kind: "var", name: dst };
|
|
6016
6335
|
}
|
|
6017
6336
|
const macroKey = `__rs_index_${this.foreachCounter++}`;
|
|
6018
6337
|
const subFnName = `${this.currentFn}/array_get_${this.foreachCounter++}`;
|
|
6019
6338
|
const indexVar = index.kind === "var" ? index.name : this.operandToVar(index);
|
|
6020
|
-
this.builder.emitRaw(`execute store result storage rs:heap ${macroKey} int 1 run scoreboard players get ${indexVar}
|
|
6339
|
+
this.builder.emitRaw(`execute store result storage rs:heap ${macroKey} int 1 run scoreboard players get ${indexVar} ${exports2.LOWERING_OBJ}`);
|
|
6021
6340
|
this.builder.emitRaw(`function ${this.namespace}:${subFnName} with storage rs:heap`);
|
|
6022
|
-
this.emitRawSubFunction(subFnName,
|
|
6341
|
+
this.emitRawSubFunction(subFnName, `execute store result score ${dst} ${exports2.LOWERING_OBJ} run data get storage rs:heap ${arrayName}[$(${macroKey})]`);
|
|
6023
6342
|
return { kind: "var", name: dst };
|
|
6024
6343
|
}
|
|
6025
6344
|
emitRawSubFunction(name, ...commands) {
|
|
@@ -6228,13 +6547,20 @@ var require_commands = __commonJS({
|
|
|
6228
6547
|
"../../dist/optimizer/commands.js"(exports2) {
|
|
6229
6548
|
"use strict";
|
|
6230
6549
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
6550
|
+
exports2.setOptimizerObjective = setOptimizerObjective;
|
|
6231
6551
|
exports2.createEmptyOptimizationStats = createEmptyOptimizationStats;
|
|
6232
6552
|
exports2.mergeOptimizationStats = mergeOptimizationStats;
|
|
6233
6553
|
exports2.applyLICM = applyLICM;
|
|
6234
6554
|
exports2.applyCSE = applyCSE;
|
|
6235
6555
|
exports2.batchSetblocks = batchSetblocks;
|
|
6236
6556
|
exports2.optimizeCommandFunctions = optimizeCommandFunctions;
|
|
6237
|
-
var
|
|
6557
|
+
var _OBJ_PATTERN = "rs";
|
|
6558
|
+
function setOptimizerObjective(obj) {
|
|
6559
|
+
_OBJ_PATTERN = obj;
|
|
6560
|
+
}
|
|
6561
|
+
function scoreboardReadRe() {
|
|
6562
|
+
return new RegExp(`^execute store result score (\\$[A-Za-z0-9_]+) ${_OBJ_PATTERN} run scoreboard players get (\\S+) (\\S+)$`);
|
|
6563
|
+
}
|
|
6238
6564
|
var SCOREBOARD_WRITE_RE = /^(?:scoreboard players (?:set|add|remove|reset)\s+(\S+)\s+(\S+)|scoreboard players operation\s+(\S+)\s+(\S+)\s+[+\-*/%]?= )/;
|
|
6239
6565
|
var EXECUTE_STORE_SCORE_RE = /^execute store result score (\S+) (\S+) run /;
|
|
6240
6566
|
var FUNCTION_CALL_RE = /^execute as (.+) run function ([^:]+):(.+)$/;
|
|
@@ -6319,7 +6645,7 @@ var require_commands = __commonJS({
|
|
|
6319
6645
|
const readInfo = /* @__PURE__ */ new Map();
|
|
6320
6646
|
const scoreboardWrites = /* @__PURE__ */ new Set();
|
|
6321
6647
|
for (const inner of loopFn.commands) {
|
|
6322
|
-
const readMatch = inner.cmd.match(
|
|
6648
|
+
const readMatch = inner.cmd.match(scoreboardReadRe());
|
|
6323
6649
|
if (readMatch) {
|
|
6324
6650
|
const [, temp, player, objective] = readMatch;
|
|
6325
6651
|
const key = `${player} ${objective}`;
|
|
@@ -6334,7 +6660,7 @@ var require_commands = __commonJS({
|
|
|
6334
6660
|
for (const info of readInfo.values()) {
|
|
6335
6661
|
const matches = inner.cmd.match(TEMP_RE) ?? [];
|
|
6336
6662
|
const usageCount = matches.filter((name) => name === info.temp).length;
|
|
6337
|
-
const isDef = inner.cmd.startsWith(`execute store result score ${info.temp}
|
|
6663
|
+
const isDef = inner.cmd.startsWith(`execute store result score ${info.temp} ${_OBJ_PATTERN} run scoreboard players get `);
|
|
6338
6664
|
if (!isDef) {
|
|
6339
6665
|
info.uses += usageCount;
|
|
6340
6666
|
}
|
|
@@ -6356,7 +6682,7 @@ var require_commands = __commonJS({
|
|
|
6356
6682
|
const hoistedTemps = new Set(hoistable.map((item) => item.temp));
|
|
6357
6683
|
const rewrittenLoopCommands = [];
|
|
6358
6684
|
for (const inner of loopFn.commands) {
|
|
6359
|
-
const readMatch = inner.cmd.match(
|
|
6685
|
+
const readMatch = inner.cmd.match(scoreboardReadRe());
|
|
6360
6686
|
if (readMatch && hoistedTemps.has(readMatch[1])) {
|
|
6361
6687
|
continue;
|
|
6362
6688
|
}
|
|
@@ -6364,7 +6690,7 @@ var require_commands = __commonJS({
|
|
|
6364
6690
|
}
|
|
6365
6691
|
loopFn.commands = rewrittenLoopCommands;
|
|
6366
6692
|
nextCommands.push(...hoistable.map((item) => ({
|
|
6367
|
-
cmd: `execute store result score ${item.temp}
|
|
6693
|
+
cmd: `execute store result score ${item.temp} ${_OBJ_PATTERN} run scoreboard players get ${item.player} ${item.objective}`
|
|
6368
6694
|
})), command);
|
|
6369
6695
|
stats.licmHoists = (stats.licmHoists ?? 0) + hoistable.length;
|
|
6370
6696
|
stats.licmLoopBodies = (stats.licmLoopBodies ?? 0) + 1;
|
|
@@ -6374,8 +6700,8 @@ var require_commands = __commonJS({
|
|
|
6374
6700
|
return stats;
|
|
6375
6701
|
}
|
|
6376
6702
|
function extractArithmeticExpression(commands, index) {
|
|
6377
|
-
const assign = commands[index]?.cmd.match(
|
|
6378
|
-
const op = commands[index + 1]?.cmd.match(
|
|
6703
|
+
const assign = commands[index]?.cmd.match(new RegExp(`^scoreboard players operation (\\$[A-Za-z0-9_]+) ${_OBJ_PATTERN} = (\\$[A-Za-z0-9_]+|\\$const_-?\\d+) ${_OBJ_PATTERN}$`)) ?? commands[index]?.cmd.match(new RegExp(`^scoreboard players set (\\$[A-Za-z0-9_]+) ${_OBJ_PATTERN} (-?\\d+)$`));
|
|
6704
|
+
const op = commands[index + 1]?.cmd.match(new RegExp(`^scoreboard players operation (\\$[A-Za-z0-9_]+) ${_OBJ_PATTERN} ([+\\-*/%]=) (\\$[A-Za-z0-9_]+|\\$const_-?\\d+) ${_OBJ_PATTERN}$`));
|
|
6379
6705
|
if (!assign || !op || assign[1] !== op[1]) {
|
|
6380
6706
|
return null;
|
|
6381
6707
|
}
|
|
@@ -6405,14 +6731,14 @@ var require_commands = __commonJS({
|
|
|
6405
6731
|
const rewritten = [];
|
|
6406
6732
|
for (let i = 0; i < commands.length; i++) {
|
|
6407
6733
|
const command = commands[i];
|
|
6408
|
-
const readMatch = command.cmd.match(
|
|
6734
|
+
const readMatch = command.cmd.match(scoreboardReadRe());
|
|
6409
6735
|
if (readMatch) {
|
|
6410
6736
|
const [, dst, player, objective] = readMatch;
|
|
6411
6737
|
const key = `${player} ${objective}`;
|
|
6412
6738
|
const cached = readCache.get(key);
|
|
6413
6739
|
if (cached) {
|
|
6414
6740
|
stats.cseRedundantReads = (stats.cseRedundantReads ?? 0) + 1;
|
|
6415
|
-
rewritten.push({ ...command, cmd: `scoreboard players operation ${dst}
|
|
6741
|
+
rewritten.push({ ...command, cmd: `scoreboard players operation ${dst} ${_OBJ_PATTERN} = ${cached} ${_OBJ_PATTERN}` });
|
|
6416
6742
|
} else {
|
|
6417
6743
|
readCache.set(key, dst);
|
|
6418
6744
|
rewritten.push(command);
|
|
@@ -6425,7 +6751,7 @@ var require_commands = __commonJS({
|
|
|
6425
6751
|
if (expr) {
|
|
6426
6752
|
const cached = exprCache.get(expr.key);
|
|
6427
6753
|
if (cached) {
|
|
6428
|
-
rewritten.push({ ...commands[i], cmd: `scoreboard players operation ${expr.dst}
|
|
6754
|
+
rewritten.push({ ...commands[i], cmd: `scoreboard players operation ${expr.dst} ${_OBJ_PATTERN} = ${cached} ${_OBJ_PATTERN}` });
|
|
6429
6755
|
stats.cseArithmetic = (stats.cseArithmetic ?? 0) + 1;
|
|
6430
6756
|
i += 1;
|
|
6431
6757
|
} else {
|
|
@@ -6725,30 +7051,36 @@ var require_passes = __commonJS({
|
|
|
6725
7051
|
return op;
|
|
6726
7052
|
return copies.get(op.name) ?? op;
|
|
6727
7053
|
}
|
|
7054
|
+
function invalidate(written) {
|
|
7055
|
+
copies.delete(written);
|
|
7056
|
+
for (const [k, v] of copies) {
|
|
7057
|
+
if (v.kind === "var" && v.name === written)
|
|
7058
|
+
copies.delete(k);
|
|
7059
|
+
}
|
|
7060
|
+
}
|
|
6728
7061
|
const newInstrs = [];
|
|
6729
7062
|
for (const instr of block.instrs) {
|
|
6730
7063
|
switch (instr.op) {
|
|
6731
7064
|
case "assign": {
|
|
6732
7065
|
const src = resolve(instr.src);
|
|
7066
|
+
invalidate(instr.dst);
|
|
6733
7067
|
if (src.kind === "var" || src.kind === "const") {
|
|
6734
7068
|
copies.set(instr.dst, src);
|
|
6735
|
-
} else {
|
|
6736
|
-
copies.delete(instr.dst);
|
|
6737
7069
|
}
|
|
6738
7070
|
newInstrs.push({ ...instr, src });
|
|
6739
7071
|
break;
|
|
6740
7072
|
}
|
|
6741
7073
|
case "binop":
|
|
6742
|
-
|
|
7074
|
+
invalidate(instr.dst);
|
|
6743
7075
|
newInstrs.push({ ...instr, lhs: resolve(instr.lhs), rhs: resolve(instr.rhs) });
|
|
6744
7076
|
break;
|
|
6745
7077
|
case "cmp":
|
|
6746
|
-
|
|
7078
|
+
invalidate(instr.dst);
|
|
6747
7079
|
newInstrs.push({ ...instr, lhs: resolve(instr.lhs), rhs: resolve(instr.rhs) });
|
|
6748
7080
|
break;
|
|
6749
7081
|
case "call":
|
|
6750
7082
|
if (instr.dst)
|
|
6751
|
-
|
|
7083
|
+
invalidate(instr.dst);
|
|
6752
7084
|
newInstrs.push({ ...instr, args: instr.args.map(resolve) });
|
|
6753
7085
|
break;
|
|
6754
7086
|
default:
|
|
@@ -6850,1168 +7182,1439 @@ var require_passes = __commonJS({
|
|
|
6850
7182
|
}
|
|
6851
7183
|
});
|
|
6852
7184
|
|
|
6853
|
-
// ../../dist/
|
|
6854
|
-
var
|
|
6855
|
-
"../../dist/
|
|
7185
|
+
// ../../dist/codegen/var-allocator.js
|
|
7186
|
+
var require_var_allocator = __commonJS({
|
|
7187
|
+
"../../dist/codegen/var-allocator.js"(exports2) {
|
|
6856
7188
|
"use strict";
|
|
6857
7189
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
6858
|
-
exports2.
|
|
6859
|
-
|
|
6860
|
-
|
|
6861
|
-
|
|
6862
|
-
|
|
6863
|
-
|
|
7190
|
+
exports2.VarAllocator = void 0;
|
|
7191
|
+
var VarAllocator = class {
|
|
7192
|
+
constructor(mangle = true) {
|
|
7193
|
+
this.seq = 0;
|
|
7194
|
+
this.varCache = /* @__PURE__ */ new Map();
|
|
7195
|
+
this.constCache = /* @__PURE__ */ new Map();
|
|
7196
|
+
this.internalCache = /* @__PURE__ */ new Map();
|
|
7197
|
+
this.mangle = mangle;
|
|
7198
|
+
}
|
|
7199
|
+
/** Allocate a name for a user variable. Strips leading '$' if present. */
|
|
7200
|
+
alloc(originalName) {
|
|
7201
|
+
const clean = originalName.startsWith("$") ? originalName.slice(1) : originalName;
|
|
7202
|
+
const cached = this.varCache.get(clean);
|
|
7203
|
+
if (cached)
|
|
7204
|
+
return cached;
|
|
7205
|
+
const name = this.mangle ? `$${this.nextSeqName()}` : `$${clean}`;
|
|
7206
|
+
this.varCache.set(clean, name);
|
|
7207
|
+
return name;
|
|
6864
7208
|
}
|
|
6865
|
-
|
|
6866
|
-
|
|
6867
|
-
|
|
6868
|
-
|
|
6869
|
-
|
|
7209
|
+
/** Allocate a name for a constant value (content-addressed). */
|
|
7210
|
+
constant(value) {
|
|
7211
|
+
const cached = this.constCache.get(value);
|
|
7212
|
+
if (cached)
|
|
7213
|
+
return cached;
|
|
7214
|
+
const name = this.mangle ? `$${this.nextSeqName()}` : `$const_${value}`;
|
|
7215
|
+
this.constCache.set(value, name);
|
|
7216
|
+
return name;
|
|
6870
7217
|
}
|
|
6871
|
-
|
|
6872
|
-
|
|
6873
|
-
|
|
6874
|
-
|
|
6875
|
-
|
|
6876
|
-
|
|
6877
|
-
|
|
6878
|
-
|
|
6879
|
-
|
|
6880
|
-
|
|
6881
|
-
|
|
6882
|
-
|
|
6883
|
-
case "bool_lit":
|
|
6884
|
-
case "str_lit":
|
|
6885
|
-
case "mc_name":
|
|
6886
|
-
case "range_lit":
|
|
6887
|
-
case "selector":
|
|
6888
|
-
case "ident":
|
|
6889
|
-
case "blockpos":
|
|
6890
|
-
return true;
|
|
6891
|
-
case "str_interp":
|
|
6892
|
-
return expr.parts.every((part) => typeof part === "string" || isPureExpr(part));
|
|
6893
|
-
case "f_string":
|
|
6894
|
-
return expr.parts.every((part) => part.kind === "text" || isPureExpr(part.expr));
|
|
6895
|
-
case "binary":
|
|
6896
|
-
return isPureExpr(expr.left) && isPureExpr(expr.right);
|
|
6897
|
-
case "is_check":
|
|
6898
|
-
return isPureExpr(expr.expr);
|
|
6899
|
-
case "unary":
|
|
6900
|
-
return isPureExpr(expr.operand);
|
|
6901
|
-
case "member":
|
|
6902
|
-
return isPureExpr(expr.obj);
|
|
6903
|
-
case "index":
|
|
6904
|
-
return isPureExpr(expr.obj) && isPureExpr(expr.index);
|
|
6905
|
-
case "array_lit":
|
|
6906
|
-
return expr.elements.every(isPureExpr);
|
|
6907
|
-
case "struct_lit":
|
|
6908
|
-
return expr.fields.every((field) => isPureExpr(field.value));
|
|
6909
|
-
case "lambda":
|
|
6910
|
-
return true;
|
|
6911
|
-
case "assign":
|
|
6912
|
-
case "member_assign":
|
|
6913
|
-
case "call":
|
|
6914
|
-
case "invoke":
|
|
6915
|
-
case "static_call":
|
|
6916
|
-
return false;
|
|
7218
|
+
/**
|
|
7219
|
+
* Look up the allocated name for a raw scoreboard fake-player name such as
|
|
7220
|
+
* "$_2", "$x", "$p0", or "$ret". Returns the mangled name when mangle=true,
|
|
7221
|
+
* or the original name when mangle=false or the name is not yet known.
|
|
7222
|
+
*
|
|
7223
|
+
* Unlike alloc/internal/constant this does NOT create a new slot — it only
|
|
7224
|
+
* resolves names that were already registered. Used by the codegen to
|
|
7225
|
+
* rewrite variable references inside `raw` IR instructions.
|
|
7226
|
+
*/
|
|
7227
|
+
resolve(rawName) {
|
|
7228
|
+
const clean = rawName.startsWith("$") ? rawName.slice(1) : rawName;
|
|
7229
|
+
return this.varCache.get(clean) ?? this.internalCache.get(clean) ?? rawName;
|
|
6917
7230
|
}
|
|
6918
|
-
|
|
6919
|
-
|
|
6920
|
-
|
|
6921
|
-
|
|
6922
|
-
|
|
6923
|
-
|
|
6924
|
-
|
|
6925
|
-
|
|
6926
|
-
this.localIdCounter = 0;
|
|
6927
|
-
this.warnings = [];
|
|
7231
|
+
/**
|
|
7232
|
+
* Rewrite all $varname tokens in a raw mcfunction command string so that
|
|
7233
|
+
* IR variable names are replaced by their allocated (possibly mangled) names.
|
|
7234
|
+
* Tokens that are not registered in the allocator are left untouched (they
|
|
7235
|
+
* are literal scoreboard fake-player names like "out" or "#rs").
|
|
7236
|
+
*/
|
|
7237
|
+
resolveRaw(cmd) {
|
|
7238
|
+
return cmd.replace(/\$[A-Za-z_][A-Za-z0-9_]*/g, (tok) => this.resolve(tok));
|
|
6928
7239
|
}
|
|
6929
|
-
|
|
6930
|
-
|
|
6931
|
-
this.
|
|
6932
|
-
|
|
6933
|
-
|
|
6934
|
-
this.
|
|
6935
|
-
this.
|
|
6936
|
-
|
|
6937
|
-
|
|
7240
|
+
/** Allocate a name for a compiler internal (e.g. "ret", "p0"). */
|
|
7241
|
+
internal(suffix) {
|
|
7242
|
+
const cached = this.internalCache.get(suffix);
|
|
7243
|
+
if (cached)
|
|
7244
|
+
return cached;
|
|
7245
|
+
const name = this.mangle ? `$${this.nextSeqName()}` : `$${suffix}`;
|
|
7246
|
+
this.internalCache.set(suffix, name);
|
|
7247
|
+
return name;
|
|
7248
|
+
}
|
|
7249
|
+
/** Generate the next sequential name: a, b, ..., z, aa, ab, ..., az, ba, ... */
|
|
7250
|
+
nextSeqName() {
|
|
7251
|
+
const n = this.seq++;
|
|
7252
|
+
let result = "";
|
|
7253
|
+
let remaining = n;
|
|
7254
|
+
do {
|
|
7255
|
+
result = String.fromCharCode(97 + remaining % 26) + result;
|
|
7256
|
+
remaining = Math.floor(remaining / 26) - 1;
|
|
7257
|
+
} while (remaining >= 0);
|
|
7258
|
+
return result;
|
|
7259
|
+
}
|
|
7260
|
+
/**
|
|
7261
|
+
* Returns a sourcemap object mapping allocated name → original name.
|
|
7262
|
+
* Useful for debugging: write to <output>.map.json alongside the datapack.
|
|
7263
|
+
* Only meaningful when mangle=true.
|
|
7264
|
+
*/
|
|
7265
|
+
toSourceMap() {
|
|
7266
|
+
const map = {};
|
|
7267
|
+
for (const [orig, alloc] of this.varCache) {
|
|
7268
|
+
if (/^_\d+$/.test(orig))
|
|
7269
|
+
continue;
|
|
7270
|
+
map[alloc] = orig;
|
|
6938
7271
|
}
|
|
6939
|
-
const
|
|
6940
|
-
|
|
6941
|
-
|
|
6942
|
-
|
|
7272
|
+
for (const [val, alloc] of this.constCache)
|
|
7273
|
+
map[alloc] = `const:${val}`;
|
|
7274
|
+
for (const [suf, alloc] of this.internalCache)
|
|
7275
|
+
map[alloc] = `internal:${suf}`;
|
|
7276
|
+
return map;
|
|
7277
|
+
}
|
|
7278
|
+
};
|
|
7279
|
+
exports2.VarAllocator = VarAllocator;
|
|
7280
|
+
}
|
|
7281
|
+
});
|
|
7282
|
+
|
|
7283
|
+
// ../../dist/codegen/mcfunction/index.js
|
|
7284
|
+
var require_mcfunction = __commonJS({
|
|
7285
|
+
"../../dist/codegen/mcfunction/index.js"(exports2) {
|
|
7286
|
+
"use strict";
|
|
7287
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
7288
|
+
exports2.countMcfunctionCommands = countMcfunctionCommands;
|
|
7289
|
+
exports2.generateDatapackWithStats = generateDatapackWithStats;
|
|
7290
|
+
exports2.generateDatapack = generateDatapack;
|
|
7291
|
+
var commands_1 = require_commands();
|
|
7292
|
+
var types_1 = require_types();
|
|
7293
|
+
var var_allocator_1 = require_var_allocator();
|
|
7294
|
+
var OBJ = "rs";
|
|
7295
|
+
function operandToScore(op, alloc) {
|
|
7296
|
+
if (op.kind === "var")
|
|
7297
|
+
return `${alloc.alloc(op.name)} ${OBJ}`;
|
|
7298
|
+
if (op.kind === "const")
|
|
7299
|
+
return `${alloc.constant(op.value)} ${OBJ}`;
|
|
7300
|
+
if (op.kind === "param")
|
|
7301
|
+
return `${alloc.internal(`p${op.index}`)} ${OBJ}`;
|
|
7302
|
+
throw new Error(`Cannot convert storage operand to score: ${op.path}`);
|
|
7303
|
+
}
|
|
7304
|
+
function collectConsts(fn) {
|
|
7305
|
+
const consts = /* @__PURE__ */ new Set();
|
|
7306
|
+
for (const block of fn.blocks) {
|
|
7307
|
+
for (const instr of block.instrs) {
|
|
7308
|
+
if (instr.op === "assign" && instr.src.kind === "const")
|
|
7309
|
+
consts.add(instr.src.value);
|
|
7310
|
+
if (instr.op === "binop") {
|
|
7311
|
+
if (instr.lhs.kind === "const")
|
|
7312
|
+
consts.add(instr.lhs.value);
|
|
7313
|
+
if (instr.rhs.kind === "const")
|
|
7314
|
+
consts.add(instr.rhs.value);
|
|
6943
7315
|
}
|
|
6944
|
-
|
|
6945
|
-
|
|
6946
|
-
|
|
7316
|
+
if (instr.op === "cmp") {
|
|
7317
|
+
if (instr.lhs.kind === "const")
|
|
7318
|
+
consts.add(instr.lhs.value);
|
|
7319
|
+
if (instr.rhs.kind === "const")
|
|
7320
|
+
consts.add(instr.rhs.value);
|
|
6947
7321
|
}
|
|
6948
7322
|
}
|
|
6949
|
-
|
|
6950
|
-
|
|
6951
|
-
|
|
6952
|
-
|
|
6953
|
-
|
|
6954
|
-
|
|
7323
|
+
const t = block.term;
|
|
7324
|
+
if (t.op === "return" && t.value?.kind === "const")
|
|
7325
|
+
consts.add(t.value.value);
|
|
7326
|
+
}
|
|
7327
|
+
return consts;
|
|
7328
|
+
}
|
|
7329
|
+
var BOP_OP = {
|
|
7330
|
+
"+": "+=",
|
|
7331
|
+
"-": "-=",
|
|
7332
|
+
"*": "*=",
|
|
7333
|
+
"/": "/=",
|
|
7334
|
+
"%": "%="
|
|
7335
|
+
};
|
|
7336
|
+
function emitInstr(instr, ns, alloc) {
|
|
7337
|
+
const lines = [];
|
|
7338
|
+
switch (instr.op) {
|
|
7339
|
+
case "assign": {
|
|
7340
|
+
const dst = alloc.alloc(instr.dst);
|
|
7341
|
+
const src = instr.src;
|
|
7342
|
+
if (src.kind === "const") {
|
|
7343
|
+
lines.push(`scoreboard players set ${dst} ${OBJ} ${src.value}`);
|
|
7344
|
+
} else if (src.kind === "var") {
|
|
7345
|
+
lines.push(`scoreboard players operation ${dst} ${OBJ} = ${alloc.alloc(src.name)} ${OBJ}`);
|
|
7346
|
+
} else if (src.kind === "param") {
|
|
7347
|
+
lines.push(`scoreboard players operation ${dst} ${OBJ} = ${alloc.internal(`p${src.index}`)} ${OBJ}`);
|
|
7348
|
+
} else {
|
|
7349
|
+
lines.push(`execute store result score ${dst} ${OBJ} run data get storage ${src.path}`);
|
|
6955
7350
|
}
|
|
7351
|
+
break;
|
|
7352
|
+
}
|
|
7353
|
+
case "binop": {
|
|
7354
|
+
const dst = alloc.alloc(instr.dst);
|
|
7355
|
+
const bop = BOP_OP[instr.bop] ?? "+=";
|
|
7356
|
+
lines.push(...emitInstr({ op: "assign", dst: instr.dst, src: instr.lhs }, ns, alloc));
|
|
7357
|
+
lines.push(`scoreboard players operation ${dst} ${OBJ} ${bop} ${operandToScore(instr.rhs, alloc)}`);
|
|
7358
|
+
break;
|
|
7359
|
+
}
|
|
7360
|
+
case "cmp": {
|
|
7361
|
+
const dst = alloc.alloc(instr.dst);
|
|
7362
|
+
const lhsScore = operandToScore(instr.lhs, alloc);
|
|
7363
|
+
const rhsScore = operandToScore(instr.rhs, alloc);
|
|
7364
|
+
lines.push(`scoreboard players set ${dst} ${OBJ} 0`);
|
|
7365
|
+
switch (instr.cop) {
|
|
7366
|
+
case "==":
|
|
7367
|
+
lines.push(`execute if score ${lhsScore} = ${rhsScore} run scoreboard players set ${dst} ${OBJ} 1`);
|
|
7368
|
+
break;
|
|
7369
|
+
case "!=":
|
|
7370
|
+
lines.push(`execute unless score ${lhsScore} = ${rhsScore} run scoreboard players set ${dst} ${OBJ} 1`);
|
|
7371
|
+
break;
|
|
7372
|
+
case "<":
|
|
7373
|
+
lines.push(`execute if score ${lhsScore} < ${rhsScore} run scoreboard players set ${dst} ${OBJ} 1`);
|
|
7374
|
+
break;
|
|
7375
|
+
case "<=":
|
|
7376
|
+
lines.push(`execute if score ${lhsScore} <= ${rhsScore} run scoreboard players set ${dst} ${OBJ} 1`);
|
|
7377
|
+
break;
|
|
7378
|
+
case ">":
|
|
7379
|
+
lines.push(`execute if score ${lhsScore} > ${rhsScore} run scoreboard players set ${dst} ${OBJ} 1`);
|
|
7380
|
+
break;
|
|
7381
|
+
case ">=":
|
|
7382
|
+
lines.push(`execute if score ${lhsScore} >= ${rhsScore} run scoreboard players set ${dst} ${OBJ} 1`);
|
|
7383
|
+
break;
|
|
7384
|
+
}
|
|
7385
|
+
break;
|
|
7386
|
+
}
|
|
7387
|
+
case "call": {
|
|
7388
|
+
for (let i = 0; i < instr.args.length; i++) {
|
|
7389
|
+
const paramSlot = alloc.internal(`p${i}`);
|
|
7390
|
+
const arg = instr.args[i];
|
|
7391
|
+
if (arg.kind === "const") {
|
|
7392
|
+
lines.push(`scoreboard players set ${paramSlot} ${OBJ} ${arg.value}`);
|
|
7393
|
+
} else if (arg.kind === "var") {
|
|
7394
|
+
lines.push(`scoreboard players operation ${paramSlot} ${OBJ} = ${alloc.alloc(arg.name)} ${OBJ}`);
|
|
7395
|
+
} else if (arg.kind === "param") {
|
|
7396
|
+
lines.push(`scoreboard players operation ${paramSlot} ${OBJ} = ${alloc.internal(`p${arg.index}`)} ${OBJ}`);
|
|
7397
|
+
}
|
|
7398
|
+
}
|
|
7399
|
+
lines.push(`function ${ns}:${instr.fn}`);
|
|
7400
|
+
if (instr.dst) {
|
|
7401
|
+
const retSlot = alloc.internal("ret");
|
|
7402
|
+
lines.push(`scoreboard players operation ${alloc.alloc(instr.dst)} ${OBJ} = ${retSlot} ${OBJ}`);
|
|
7403
|
+
}
|
|
7404
|
+
break;
|
|
7405
|
+
}
|
|
7406
|
+
case "raw": {
|
|
7407
|
+
const rawResolved = alloc.resolveRaw(instr.cmd).replace(/^\x01/, "$");
|
|
7408
|
+
lines.push(rawResolved);
|
|
7409
|
+
break;
|
|
6956
7410
|
}
|
|
6957
|
-
return {
|
|
6958
|
-
...program,
|
|
6959
|
-
declarations: program.declarations.filter((fn) => this.reachableFunctions.has(fn.name)).map((fn) => this.transformFunction(fn)),
|
|
6960
|
-
consts: program.consts.filter((constDecl) => this.usedConstants.has(constDecl.name)),
|
|
6961
|
-
implBlocks: program.implBlocks.map((implBlock) => ({
|
|
6962
|
-
...implBlock,
|
|
6963
|
-
methods: implBlock.methods.map((method) => this.transformFunction(method))
|
|
6964
|
-
}))
|
|
6965
|
-
};
|
|
6966
7411
|
}
|
|
6967
|
-
|
|
6968
|
-
|
|
6969
|
-
|
|
6970
|
-
|
|
6971
|
-
|
|
7412
|
+
return lines;
|
|
7413
|
+
}
|
|
7414
|
+
function emitTerm(term, ns, fnName, alloc) {
|
|
7415
|
+
const lines = [];
|
|
7416
|
+
switch (term.op) {
|
|
7417
|
+
case "jump":
|
|
7418
|
+
lines.push(`function ${ns}:${fnName}/${term.target}`);
|
|
7419
|
+
break;
|
|
7420
|
+
case "jump_if":
|
|
7421
|
+
lines.push(`execute if score ${alloc.alloc(term.cond)} ${OBJ} matches 1.. run function ${ns}:${fnName}/${term.then}`);
|
|
7422
|
+
lines.push(`execute if score ${alloc.alloc(term.cond)} ${OBJ} matches ..0 run function ${ns}:${fnName}/${term.else_}`);
|
|
7423
|
+
break;
|
|
7424
|
+
case "jump_unless":
|
|
7425
|
+
lines.push(`execute if score ${alloc.alloc(term.cond)} ${OBJ} matches ..0 run function ${ns}:${fnName}/${term.then}`);
|
|
7426
|
+
lines.push(`execute if score ${alloc.alloc(term.cond)} ${OBJ} matches 1.. run function ${ns}:${fnName}/${term.else_}`);
|
|
7427
|
+
break;
|
|
7428
|
+
case "return": {
|
|
7429
|
+
const retSlot = alloc.internal("ret");
|
|
7430
|
+
if (term.value) {
|
|
7431
|
+
if (term.value.kind === "const") {
|
|
7432
|
+
lines.push(`scoreboard players set ${retSlot} ${OBJ} ${term.value.value}`);
|
|
7433
|
+
} else if (term.value.kind === "var") {
|
|
7434
|
+
lines.push(`scoreboard players operation ${retSlot} ${OBJ} = ${alloc.alloc(term.value.name)} ${OBJ}`);
|
|
7435
|
+
} else if (term.value.kind === "param") {
|
|
7436
|
+
lines.push(`scoreboard players operation ${retSlot} ${OBJ} = ${alloc.internal(`p${term.value.index}`)} ${OBJ}`);
|
|
7437
|
+
}
|
|
6972
7438
|
}
|
|
6973
|
-
if (
|
|
6974
|
-
|
|
6975
|
-
|
|
6976
|
-
|
|
6977
|
-
|
|
6978
|
-
|
|
6979
|
-
"on_craft",
|
|
6980
|
-
"on_death",
|
|
6981
|
-
"on_login",
|
|
6982
|
-
"on_join_team",
|
|
6983
|
-
"keep"
|
|
6984
|
-
].includes(decorator.name))) {
|
|
6985
|
-
entries.add(fn.name);
|
|
7439
|
+
if (term.value?.kind === "const") {
|
|
7440
|
+
lines.push(`return ${term.value.value}`);
|
|
7441
|
+
} else if (term.value?.kind === "var") {
|
|
7442
|
+
lines.push(`return run scoreboard players get ${alloc.alloc(term.value.name)} ${OBJ}`);
|
|
7443
|
+
} else if (term.value?.kind === "param") {
|
|
7444
|
+
lines.push(`return run scoreboard players get ${alloc.internal(`p${term.value.index}`)} ${OBJ}`);
|
|
6986
7445
|
}
|
|
7446
|
+
break;
|
|
6987
7447
|
}
|
|
6988
|
-
|
|
7448
|
+
case "tick_yield":
|
|
7449
|
+
lines.push(`schedule function ${ns}:${fnName}/${term.continuation} 1t replace`);
|
|
7450
|
+
break;
|
|
6989
7451
|
}
|
|
6990
|
-
|
|
6991
|
-
|
|
6992
|
-
|
|
7452
|
+
return lines;
|
|
7453
|
+
}
|
|
7454
|
+
function toFunctionName(file) {
|
|
7455
|
+
const match = file.path.match(/^data\/[^/]+\/function\/(.+)\.mcfunction$/);
|
|
7456
|
+
return match?.[1] ?? null;
|
|
7457
|
+
}
|
|
7458
|
+
function applyFunctionOptimization(files) {
|
|
7459
|
+
const functionFiles = files.map((file) => {
|
|
7460
|
+
const functionName = toFunctionName(file);
|
|
7461
|
+
if (!functionName)
|
|
7462
|
+
return null;
|
|
7463
|
+
const commands = file.content.split("\n").map((line) => line.trim()).filter((line) => line !== "" && !line.startsWith("#")).map((cmd) => ({ cmd }));
|
|
7464
|
+
return { file, functionName, commands };
|
|
7465
|
+
}).filter((entry) => entry !== null);
|
|
7466
|
+
const optimized = (0, commands_1.optimizeCommandFunctions)(functionFiles.map((entry) => ({
|
|
7467
|
+
name: entry.functionName,
|
|
7468
|
+
commands: entry.commands
|
|
7469
|
+
})));
|
|
7470
|
+
const commandMap = new Map(optimized.functions.map((fn) => [fn.name, fn.commands]));
|
|
7471
|
+
const optimizedNames = new Set(optimized.functions.map((fn) => fn.name));
|
|
7472
|
+
return {
|
|
7473
|
+
files: files.filter((file) => {
|
|
7474
|
+
const functionName = toFunctionName(file);
|
|
7475
|
+
return !functionName || optimizedNames.has(functionName);
|
|
7476
|
+
}).map((file) => {
|
|
7477
|
+
const functionName = toFunctionName(file);
|
|
7478
|
+
if (!functionName)
|
|
7479
|
+
return file;
|
|
7480
|
+
const commands = commandMap.get(functionName);
|
|
7481
|
+
if (!commands)
|
|
7482
|
+
return file;
|
|
7483
|
+
const lines = file.content.split("\n");
|
|
7484
|
+
const header = lines.filter((line) => line.trim().startsWith("#"));
|
|
7485
|
+
return {
|
|
7486
|
+
...file,
|
|
7487
|
+
content: [...header, ...commands.map((command) => command.cmd)].join("\n")
|
|
7488
|
+
};
|
|
7489
|
+
}),
|
|
7490
|
+
stats: optimized.stats
|
|
7491
|
+
};
|
|
7492
|
+
}
|
|
7493
|
+
function countMcfunctionCommands(files) {
|
|
7494
|
+
return files.reduce((sum, file) => {
|
|
7495
|
+
if (!toFunctionName(file)) {
|
|
7496
|
+
return sum;
|
|
6993
7497
|
}
|
|
6994
|
-
|
|
6995
|
-
|
|
6996
|
-
|
|
7498
|
+
return sum + file.content.split("\n").map((line) => line.trim()).filter((line) => line !== "" && !line.startsWith("#")).length;
|
|
7499
|
+
}, 0);
|
|
7500
|
+
}
|
|
7501
|
+
function preAllocInstr(instr, alloc) {
|
|
7502
|
+
switch (instr.op) {
|
|
7503
|
+
case "assign":
|
|
7504
|
+
alloc.alloc(instr.dst);
|
|
7505
|
+
if (instr.src.kind === "var")
|
|
7506
|
+
alloc.alloc(instr.src.name);
|
|
7507
|
+
break;
|
|
7508
|
+
case "binop":
|
|
7509
|
+
alloc.alloc(instr.dst);
|
|
7510
|
+
if (instr.lhs.kind === "var")
|
|
7511
|
+
alloc.alloc(instr.lhs.name);
|
|
7512
|
+
if (instr.rhs.kind === "var")
|
|
7513
|
+
alloc.alloc(instr.rhs.name);
|
|
7514
|
+
break;
|
|
7515
|
+
case "cmp":
|
|
7516
|
+
alloc.alloc(instr.dst);
|
|
7517
|
+
if (instr.lhs.kind === "var")
|
|
7518
|
+
alloc.alloc(instr.lhs.name);
|
|
7519
|
+
if (instr.rhs.kind === "var")
|
|
7520
|
+
alloc.alloc(instr.rhs.name);
|
|
7521
|
+
break;
|
|
7522
|
+
case "call":
|
|
7523
|
+
for (const arg of instr.args) {
|
|
7524
|
+
if (arg.kind === "var")
|
|
7525
|
+
alloc.alloc(arg.name);
|
|
7526
|
+
}
|
|
7527
|
+
if (instr.dst)
|
|
7528
|
+
alloc.alloc(instr.dst);
|
|
7529
|
+
break;
|
|
7530
|
+
case "raw":
|
|
7531
|
+
;
|
|
7532
|
+
instr.cmd.replace(/\$[A-Za-z_][A-Za-z0-9_]*/g, (tok) => {
|
|
7533
|
+
alloc.alloc(tok);
|
|
7534
|
+
return tok;
|
|
7535
|
+
});
|
|
7536
|
+
break;
|
|
7537
|
+
}
|
|
7538
|
+
}
|
|
7539
|
+
function preAllocTerm(term, alloc) {
|
|
7540
|
+
switch (term.op) {
|
|
7541
|
+
case "jump_if":
|
|
7542
|
+
case "jump_unless":
|
|
7543
|
+
alloc.alloc(term.cond);
|
|
7544
|
+
break;
|
|
7545
|
+
case "return":
|
|
7546
|
+
if (term.value?.kind === "var")
|
|
7547
|
+
alloc.alloc(term.value.name);
|
|
7548
|
+
break;
|
|
7549
|
+
}
|
|
7550
|
+
}
|
|
7551
|
+
function generateDatapackWithStats(module3, options = {}) {
|
|
7552
|
+
const { optimizeCommands = true, mangle = false, scoreboardObjective = "rs" } = options;
|
|
7553
|
+
OBJ = scoreboardObjective;
|
|
7554
|
+
(0, commands_1.setOptimizerObjective)(scoreboardObjective);
|
|
7555
|
+
const alloc = new var_allocator_1.VarAllocator(mangle);
|
|
7556
|
+
const files = [];
|
|
7557
|
+
const advancements = [];
|
|
7558
|
+
const ns = module3.namespace;
|
|
7559
|
+
const triggerHandlers = module3.functions.filter((fn) => fn.isTriggerHandler && fn.triggerName);
|
|
7560
|
+
const triggerNames = new Set(triggerHandlers.map((fn) => fn.triggerName));
|
|
7561
|
+
const eventHandlers = module3.functions.filter((fn) => !!fn.eventHandler && (0, types_1.isEventTypeName)(fn.eventHandler.eventType));
|
|
7562
|
+
const eventTypes = new Set(eventHandlers.map((fn) => fn.eventHandler.eventType));
|
|
7563
|
+
const tickFunctionNames = [];
|
|
7564
|
+
for (const fn of module3.functions) {
|
|
7565
|
+
if (fn.isTickLoop) {
|
|
7566
|
+
tickFunctionNames.push(fn.name);
|
|
6997
7567
|
}
|
|
6998
|
-
this.reachableFunctions.add(fnName);
|
|
6999
|
-
this.collectFunctionRefs(fn);
|
|
7000
7568
|
}
|
|
7001
|
-
|
|
7002
|
-
|
|
7003
|
-
|
|
7004
|
-
|
|
7005
|
-
|
|
7006
|
-
|
|
7569
|
+
files.push({
|
|
7570
|
+
path: "pack.mcmeta",
|
|
7571
|
+
content: JSON.stringify({
|
|
7572
|
+
pack: { pack_format: 26, description: `${ns} datapack \u2014 compiled by redscript` }
|
|
7573
|
+
}, null, 2)
|
|
7574
|
+
});
|
|
7575
|
+
const loadLines = [
|
|
7576
|
+
`# RedScript runtime init`,
|
|
7577
|
+
`scoreboard objectives add ${OBJ} dummy`
|
|
7578
|
+
];
|
|
7579
|
+
for (const g of module3.globals) {
|
|
7580
|
+
loadLines.push(`scoreboard players set ${alloc.alloc(g.name)} ${OBJ} ${g.init}`);
|
|
7581
|
+
}
|
|
7582
|
+
for (const triggerName of triggerNames) {
|
|
7583
|
+
loadLines.push(`scoreboard objectives add ${triggerName} trigger`);
|
|
7584
|
+
loadLines.push(`scoreboard players enable @a ${triggerName}`);
|
|
7585
|
+
}
|
|
7586
|
+
for (const eventType of eventTypes) {
|
|
7587
|
+
const detection = types_1.EVENT_TYPES[eventType].detection;
|
|
7588
|
+
if (eventType === "PlayerDeath") {
|
|
7589
|
+
loadLines.push(`scoreboard objectives add ${OBJ}.deaths deathCount`);
|
|
7590
|
+
} else if (eventType === "EntityKill") {
|
|
7591
|
+
loadLines.push(`scoreboard objectives add ${OBJ}.kills totalKillCount`);
|
|
7592
|
+
} else if (eventType === "ItemUse") {
|
|
7593
|
+
loadLines.push("# ItemUse detection requires a project-specific objective/tag setup");
|
|
7594
|
+
} else if (detection === "tag" || detection === "advancement") {
|
|
7595
|
+
loadLines.push(`# ${eventType} detection expects tag ${types_1.EVENT_TYPES[eventType].tag} to be set externally`);
|
|
7007
7596
|
}
|
|
7008
|
-
this.collectStmtRefs(fn.body, scope);
|
|
7009
7597
|
}
|
|
7010
|
-
|
|
7011
|
-
|
|
7012
|
-
|
|
7013
|
-
|
|
7598
|
+
for (const triggerName of triggerNames) {
|
|
7599
|
+
const handlers = triggerHandlers.filter((fn) => fn.triggerName === triggerName);
|
|
7600
|
+
const dispatchLines = [
|
|
7601
|
+
`# Trigger dispatch for ${triggerName}`
|
|
7602
|
+
];
|
|
7603
|
+
for (const handler of handlers) {
|
|
7604
|
+
dispatchLines.push(`function ${ns}:${handler.name}`);
|
|
7014
7605
|
}
|
|
7015
|
-
|
|
7606
|
+
dispatchLines.push(`scoreboard players set @s ${triggerName} 0`);
|
|
7607
|
+
dispatchLines.push(`scoreboard players enable @s ${triggerName}`);
|
|
7608
|
+
files.push({
|
|
7609
|
+
path: `data/${ns}/function/__trigger_${triggerName}_dispatch.mcfunction`,
|
|
7610
|
+
content: dispatchLines.join("\n")
|
|
7611
|
+
});
|
|
7016
7612
|
}
|
|
7017
|
-
|
|
7018
|
-
|
|
7019
|
-
|
|
7020
|
-
|
|
7021
|
-
|
|
7022
|
-
|
|
7023
|
-
|
|
7024
|
-
|
|
7025
|
-
|
|
7026
|
-
|
|
7027
|
-
|
|
7028
|
-
|
|
7029
|
-
|
|
7030
|
-
|
|
7031
|
-
|
|
7032
|
-
|
|
7033
|
-
break;
|
|
7034
|
-
case "if": {
|
|
7035
|
-
this.collectExprRefs(stmt.cond, scope);
|
|
7036
|
-
const constant = isConstantBoolean(stmt.cond);
|
|
7037
|
-
if (constant === true) {
|
|
7038
|
-
this.collectStmtRefs(stmt.then, scope);
|
|
7039
|
-
} else if (constant === false) {
|
|
7040
|
-
if (stmt.else_) {
|
|
7041
|
-
this.collectStmtRefs(stmt.else_, scope);
|
|
7042
|
-
}
|
|
7043
|
-
} else {
|
|
7044
|
-
this.collectStmtRefs(stmt.then, scope);
|
|
7045
|
-
if (stmt.else_) {
|
|
7046
|
-
this.collectStmtRefs(stmt.else_, scope);
|
|
7047
|
-
}
|
|
7613
|
+
const allConsts = /* @__PURE__ */ new Set();
|
|
7614
|
+
for (const fn of module3.functions) {
|
|
7615
|
+
for (const c of collectConsts(fn))
|
|
7616
|
+
allConsts.add(c);
|
|
7617
|
+
}
|
|
7618
|
+
if (allConsts.size > 0) {
|
|
7619
|
+
loadLines.push(...Array.from(allConsts).sort((a, b) => a - b).map((value) => `scoreboard players set ${alloc.constant(value)} ${OBJ} ${value}`));
|
|
7620
|
+
}
|
|
7621
|
+
if (mangle) {
|
|
7622
|
+
for (const fn of module3.functions) {
|
|
7623
|
+
for (let i = 0; i < fn.params.length; i++)
|
|
7624
|
+
alloc.internal(`p${i}`);
|
|
7625
|
+
alloc.internal("ret");
|
|
7626
|
+
for (const block of fn.blocks) {
|
|
7627
|
+
for (const instr of block.instrs) {
|
|
7628
|
+
preAllocInstr(instr, alloc);
|
|
7048
7629
|
}
|
|
7049
|
-
|
|
7630
|
+
preAllocTerm(block.term, alloc);
|
|
7050
7631
|
}
|
|
7051
|
-
case "while":
|
|
7052
|
-
this.collectExprRefs(stmt.cond, scope);
|
|
7053
|
-
this.collectStmtRefs(stmt.body, scope);
|
|
7054
|
-
break;
|
|
7055
|
-
case "for":
|
|
7056
|
-
scope.push([]);
|
|
7057
|
-
if (stmt.init) {
|
|
7058
|
-
this.collectStmtRef(stmt.init, scope);
|
|
7059
|
-
}
|
|
7060
|
-
this.collectExprRefs(stmt.cond, scope);
|
|
7061
|
-
this.collectExprRefs(stmt.step, scope);
|
|
7062
|
-
this.collectStmtRefs(stmt.body, scope);
|
|
7063
|
-
scope.pop();
|
|
7064
|
-
break;
|
|
7065
|
-
case "foreach":
|
|
7066
|
-
this.collectExprRefs(stmt.iterable, scope);
|
|
7067
|
-
scope.push([{ id: `foreach:${stmt.binding}:${stmt.span?.line ?? 0}:${stmt.span?.col ?? 0}`, name: stmt.binding }]);
|
|
7068
|
-
this.collectStmtRefs(stmt.body, scope);
|
|
7069
|
-
scope.pop();
|
|
7070
|
-
break;
|
|
7071
|
-
case "for_range":
|
|
7072
|
-
this.collectExprRefs(stmt.start, scope);
|
|
7073
|
-
this.collectExprRefs(stmt.end, scope);
|
|
7074
|
-
scope.push([{ id: `range:${stmt.varName}:${stmt.span?.line ?? 0}:${stmt.span?.col ?? 0}`, name: stmt.varName }]);
|
|
7075
|
-
this.collectStmtRefs(stmt.body, scope);
|
|
7076
|
-
scope.pop();
|
|
7077
|
-
break;
|
|
7078
|
-
case "match":
|
|
7079
|
-
this.collectExprRefs(stmt.expr, scope);
|
|
7080
|
-
for (const arm of stmt.arms) {
|
|
7081
|
-
if (arm.pattern) {
|
|
7082
|
-
this.collectExprRefs(arm.pattern, scope);
|
|
7083
|
-
}
|
|
7084
|
-
this.collectStmtRefs(arm.body, scope);
|
|
7085
|
-
}
|
|
7086
|
-
break;
|
|
7087
|
-
case "as_block":
|
|
7088
|
-
case "at_block":
|
|
7089
|
-
case "as_at":
|
|
7090
|
-
case "execute":
|
|
7091
|
-
this.collectNestedStmtRefs(stmt, scope);
|
|
7092
|
-
break;
|
|
7093
|
-
case "raw":
|
|
7094
|
-
case "break":
|
|
7095
|
-
case "continue":
|
|
7096
|
-
break;
|
|
7097
7632
|
}
|
|
7098
7633
|
}
|
|
7099
|
-
|
|
7100
|
-
|
|
7101
|
-
|
|
7102
|
-
|
|
7103
|
-
|
|
7104
|
-
|
|
7105
|
-
this.localReads.add(resolved.id);
|
|
7106
|
-
}
|
|
7107
|
-
}
|
|
7634
|
+
for (const fn of module3.functions) {
|
|
7635
|
+
for (let i = 0; i < fn.blocks.length; i++) {
|
|
7636
|
+
const block = fn.blocks[i];
|
|
7637
|
+
const lines = [`# block: ${block.label}`];
|
|
7638
|
+
for (const instr of block.instrs) {
|
|
7639
|
+
lines.push(...emitInstr(instr, ns, alloc));
|
|
7108
7640
|
}
|
|
7641
|
+
lines.push(...emitTerm(block.term, ns, fn.name, alloc));
|
|
7642
|
+
const filePath = i === 0 ? `data/${ns}/function/${fn.name}.mcfunction` : `data/${ns}/function/${fn.name}/${block.label}.mcfunction`;
|
|
7643
|
+
const hasRealContent = lines.some((l) => !l.startsWith("#") && l.trim() !== "");
|
|
7644
|
+
if (i !== 0 && !hasRealContent)
|
|
7645
|
+
continue;
|
|
7646
|
+
files.push({ path: filePath, content: lines.join("\n") });
|
|
7109
7647
|
}
|
|
7110
|
-
this.collectStmtRefs(stmt.body, scope);
|
|
7111
7648
|
}
|
|
7112
|
-
|
|
7113
|
-
|
|
7114
|
-
|
|
7115
|
-
|
|
7116
|
-
|
|
7117
|
-
|
|
7118
|
-
|
|
7119
|
-
|
|
7120
|
-
|
|
7121
|
-
|
|
7649
|
+
const loadCalls = /* @__PURE__ */ new Set();
|
|
7650
|
+
for (const fn of module3.functions) {
|
|
7651
|
+
if (fn.isLoadInit) {
|
|
7652
|
+
loadCalls.add(fn.name);
|
|
7653
|
+
}
|
|
7654
|
+
for (const dep of fn.requiredLoads ?? []) {
|
|
7655
|
+
loadCalls.add(dep);
|
|
7656
|
+
}
|
|
7657
|
+
}
|
|
7658
|
+
for (const name of loadCalls) {
|
|
7659
|
+
loadLines.push(`function ${ns}:${name}`);
|
|
7660
|
+
}
|
|
7661
|
+
files.push({
|
|
7662
|
+
path: `data/${ns}/function/__load.mcfunction`,
|
|
7663
|
+
content: loadLines.join("\n")
|
|
7664
|
+
});
|
|
7665
|
+
files.push({
|
|
7666
|
+
path: `data/minecraft/tags/function/load.json`,
|
|
7667
|
+
content: JSON.stringify({ values: [`${ns}:__load`] }, null, 2)
|
|
7668
|
+
});
|
|
7669
|
+
const tickLines = ["# RedScript tick dispatcher"];
|
|
7670
|
+
for (const fnName of tickFunctionNames) {
|
|
7671
|
+
tickLines.push(`function ${ns}:${fnName}`);
|
|
7672
|
+
}
|
|
7673
|
+
if (triggerNames.size > 0) {
|
|
7674
|
+
tickLines.push(`# Trigger checks`);
|
|
7675
|
+
for (const triggerName of triggerNames) {
|
|
7676
|
+
tickLines.push(`execute as @a[scores={${triggerName}=1..}] run function ${ns}:__trigger_${triggerName}_dispatch`);
|
|
7677
|
+
}
|
|
7678
|
+
}
|
|
7679
|
+
if (eventHandlers.length > 0) {
|
|
7680
|
+
tickLines.push("# Event checks");
|
|
7681
|
+
for (const eventType of eventTypes) {
|
|
7682
|
+
const tag = types_1.EVENT_TYPES[eventType].tag;
|
|
7683
|
+
const handlers = eventHandlers.filter((fn) => fn.eventHandler?.eventType === eventType);
|
|
7684
|
+
for (const handler of handlers) {
|
|
7685
|
+
tickLines.push(`execute as @a[tag=${tag}] run function ${ns}:${handler.name}`);
|
|
7122
7686
|
}
|
|
7123
|
-
|
|
7124
|
-
|
|
7125
|
-
|
|
7126
|
-
|
|
7127
|
-
|
|
7128
|
-
|
|
7129
|
-
|
|
7687
|
+
tickLines.push(`tag @a[tag=${tag}] remove ${tag}`);
|
|
7688
|
+
}
|
|
7689
|
+
}
|
|
7690
|
+
if (tickFunctionNames.length > 0 || triggerNames.size > 0 || eventHandlers.length > 0) {
|
|
7691
|
+
files.push({
|
|
7692
|
+
path: `data/${ns}/function/__tick.mcfunction`,
|
|
7693
|
+
content: tickLines.join("\n")
|
|
7694
|
+
});
|
|
7695
|
+
files.push({
|
|
7696
|
+
path: `data/minecraft/tags/function/tick.json`,
|
|
7697
|
+
content: JSON.stringify({ values: [`${ns}:__tick`] }, null, 2)
|
|
7698
|
+
});
|
|
7699
|
+
}
|
|
7700
|
+
for (const fn of module3.functions) {
|
|
7701
|
+
const eventTrigger = fn.eventTrigger;
|
|
7702
|
+
if (!eventTrigger) {
|
|
7703
|
+
continue;
|
|
7704
|
+
}
|
|
7705
|
+
let path2 = "";
|
|
7706
|
+
let criteria = {};
|
|
7707
|
+
switch (eventTrigger.kind) {
|
|
7708
|
+
case "advancement":
|
|
7709
|
+
path2 = `data/${ns}/advancements/on_advancement_${fn.name}.json`;
|
|
7710
|
+
criteria = {
|
|
7711
|
+
trigger: {
|
|
7712
|
+
trigger: `minecraft:${eventTrigger.value}`
|
|
7130
7713
|
}
|
|
7131
|
-
}
|
|
7132
|
-
for (const arg of expr.args) {
|
|
7133
|
-
this.collectExprRefs(arg, scope);
|
|
7134
|
-
}
|
|
7135
|
-
break;
|
|
7136
|
-
case "static_call":
|
|
7137
|
-
for (const arg of expr.args) {
|
|
7138
|
-
this.collectExprRefs(arg, scope);
|
|
7139
|
-
}
|
|
7140
|
-
break;
|
|
7141
|
-
case "invoke":
|
|
7142
|
-
this.collectExprRefs(expr.callee, scope);
|
|
7143
|
-
for (const arg of expr.args) {
|
|
7144
|
-
this.collectExprRefs(arg, scope);
|
|
7145
|
-
}
|
|
7146
|
-
break;
|
|
7147
|
-
case "member":
|
|
7148
|
-
this.collectExprRefs(expr.obj, scope);
|
|
7149
|
-
break;
|
|
7150
|
-
case "member_assign":
|
|
7151
|
-
this.collectExprRefs(expr.obj, scope);
|
|
7152
|
-
this.collectExprRefs(expr.value, scope);
|
|
7153
|
-
break;
|
|
7154
|
-
case "index":
|
|
7155
|
-
this.collectExprRefs(expr.obj, scope);
|
|
7156
|
-
this.collectExprRefs(expr.index, scope);
|
|
7157
|
-
break;
|
|
7158
|
-
case "array_lit":
|
|
7159
|
-
expr.elements.forEach((element) => this.collectExprRefs(element, scope));
|
|
7160
|
-
break;
|
|
7161
|
-
case "struct_lit":
|
|
7162
|
-
expr.fields.forEach((field) => this.collectExprRefs(field.value, scope));
|
|
7163
|
-
break;
|
|
7164
|
-
case "binary":
|
|
7165
|
-
this.collectExprRefs(expr.left, scope);
|
|
7166
|
-
this.collectExprRefs(expr.right, scope);
|
|
7167
|
-
break;
|
|
7168
|
-
case "is_check":
|
|
7169
|
-
this.collectExprRefs(expr.expr, scope);
|
|
7170
|
-
break;
|
|
7171
|
-
case "unary":
|
|
7172
|
-
this.collectExprRefs(expr.operand, scope);
|
|
7173
|
-
break;
|
|
7174
|
-
case "assign": {
|
|
7175
|
-
this.collectExprRefs(expr.value, scope);
|
|
7714
|
+
};
|
|
7176
7715
|
break;
|
|
7177
|
-
|
|
7178
|
-
|
|
7179
|
-
|
|
7180
|
-
|
|
7181
|
-
|
|
7716
|
+
case "craft":
|
|
7717
|
+
path2 = `data/${ns}/advancements/on_craft_${fn.name}.json`;
|
|
7718
|
+
criteria = {
|
|
7719
|
+
crafted: {
|
|
7720
|
+
trigger: "minecraft:inventory_changed",
|
|
7721
|
+
conditions: {
|
|
7722
|
+
items: [
|
|
7723
|
+
{
|
|
7724
|
+
items: [eventTrigger.value]
|
|
7725
|
+
}
|
|
7726
|
+
]
|
|
7727
|
+
}
|
|
7182
7728
|
}
|
|
7183
|
-
}
|
|
7729
|
+
};
|
|
7184
7730
|
break;
|
|
7185
|
-
case "
|
|
7186
|
-
|
|
7187
|
-
|
|
7188
|
-
|
|
7731
|
+
case "death":
|
|
7732
|
+
path2 = `data/${ns}/advancements/on_death_${fn.name}.json`;
|
|
7733
|
+
criteria = {
|
|
7734
|
+
death: {
|
|
7735
|
+
trigger: "minecraft:entity_killed_player"
|
|
7189
7736
|
}
|
|
7190
|
-
}
|
|
7191
|
-
break;
|
|
7192
|
-
case "lambda": {
|
|
7193
|
-
const lambdaScope = [
|
|
7194
|
-
...scope.map((entries) => [...entries]),
|
|
7195
|
-
expr.params.map((param) => ({ id: `lambda:${param.name}:${expr.span?.line ?? 0}:${expr.span?.col ?? 0}`, name: param.name }))
|
|
7196
|
-
];
|
|
7197
|
-
if (Array.isArray(expr.body)) {
|
|
7198
|
-
this.collectStmtRefs(expr.body, lambdaScope);
|
|
7199
|
-
} else {
|
|
7200
|
-
this.collectExprRefs(expr.body, lambdaScope);
|
|
7201
|
-
}
|
|
7202
|
-
break;
|
|
7203
|
-
}
|
|
7204
|
-
case "blockpos":
|
|
7205
|
-
case "bool_lit":
|
|
7206
|
-
case "byte_lit":
|
|
7207
|
-
case "double_lit":
|
|
7208
|
-
case "float_lit":
|
|
7209
|
-
case "int_lit":
|
|
7210
|
-
case "long_lit":
|
|
7211
|
-
case "mc_name":
|
|
7212
|
-
case "range_lit":
|
|
7213
|
-
case "selector":
|
|
7214
|
-
case "short_lit":
|
|
7215
|
-
case "str_lit":
|
|
7737
|
+
};
|
|
7216
7738
|
break;
|
|
7739
|
+
case "login":
|
|
7740
|
+
case "join_team":
|
|
7741
|
+
continue;
|
|
7217
7742
|
}
|
|
7218
|
-
|
|
7219
|
-
|
|
7220
|
-
|
|
7221
|
-
|
|
7222
|
-
|
|
7223
|
-
|
|
7743
|
+
advancements.push({
|
|
7744
|
+
path: path2,
|
|
7745
|
+
content: JSON.stringify({
|
|
7746
|
+
criteria,
|
|
7747
|
+
rewards: {
|
|
7748
|
+
function: `${ns}:${fn.name}`
|
|
7224
7749
|
}
|
|
7225
|
-
}
|
|
7226
|
-
}
|
|
7227
|
-
return null;
|
|
7228
|
-
}
|
|
7229
|
-
transformFunction(fn) {
|
|
7230
|
-
const scope = [fn.params.map((param) => ({ id: `param:${fn.name}:${param.name}`, name: param.name }))];
|
|
7231
|
-
const body = this.transformBlock(fn.body, scope);
|
|
7232
|
-
return body === fn.body ? fn : copySpan({ ...fn, body }, fn);
|
|
7233
|
-
}
|
|
7234
|
-
transformBlock(block, scope) {
|
|
7235
|
-
scope.push([]);
|
|
7236
|
-
const transformed = [];
|
|
7237
|
-
for (const stmt of block) {
|
|
7238
|
-
const next = this.transformStmt(stmt, scope);
|
|
7239
|
-
transformed.push(...next);
|
|
7240
|
-
}
|
|
7241
|
-
scope.pop();
|
|
7242
|
-
return transformed;
|
|
7243
|
-
}
|
|
7244
|
-
transformStmt(stmt, scope) {
|
|
7245
|
-
switch (stmt.kind) {
|
|
7246
|
-
case "let": {
|
|
7247
|
-
const init = this.transformExpr(stmt.init, scope);
|
|
7248
|
-
const id = this.localDeclIds.get(stmt) ?? `local:${stmt.name}:${stmt.span?.line ?? 0}:${stmt.span?.col ?? 0}`;
|
|
7249
|
-
scope[scope.length - 1].push({ id, name: stmt.name });
|
|
7250
|
-
if (this.localReads.has(id)) {
|
|
7251
|
-
if (init === stmt.init) {
|
|
7252
|
-
return [stmt];
|
|
7253
|
-
}
|
|
7254
|
-
return [copySpan({ ...stmt, init }, stmt)];
|
|
7255
|
-
}
|
|
7256
|
-
this.warnings.push({
|
|
7257
|
-
message: `Unused variable '${stmt.name}'`,
|
|
7258
|
-
code: "W_UNUSED_VAR",
|
|
7259
|
-
line: stmt.span?.line,
|
|
7260
|
-
col: stmt.span?.col
|
|
7261
|
-
});
|
|
7262
|
-
if (isPureExpr(init)) {
|
|
7263
|
-
return [];
|
|
7264
|
-
}
|
|
7265
|
-
return [copySpan({ kind: "expr", expr: init }, stmt)];
|
|
7266
|
-
}
|
|
7267
|
-
case "expr": {
|
|
7268
|
-
const expr = this.transformExpr(stmt.expr, scope);
|
|
7269
|
-
if (expr.kind === "assign") {
|
|
7270
|
-
const resolved = this.resolveLocal(expr.target, scope);
|
|
7271
|
-
if (resolved && !this.localReads.has(resolved.id)) {
|
|
7272
|
-
if (isPureExpr(expr.value)) {
|
|
7273
|
-
return [];
|
|
7274
|
-
}
|
|
7275
|
-
return [copySpan({ kind: "expr", expr: expr.value }, stmt)];
|
|
7276
|
-
}
|
|
7277
|
-
}
|
|
7278
|
-
if (expr === stmt.expr) {
|
|
7279
|
-
return [stmt];
|
|
7280
|
-
}
|
|
7281
|
-
return [copySpan({ ...stmt, expr }, stmt)];
|
|
7282
|
-
}
|
|
7283
|
-
case "return": {
|
|
7284
|
-
if (!stmt.value) {
|
|
7285
|
-
return [stmt];
|
|
7286
|
-
}
|
|
7287
|
-
const value = this.transformExpr(stmt.value, scope);
|
|
7288
|
-
if (value === stmt.value) {
|
|
7289
|
-
return [stmt];
|
|
7290
|
-
}
|
|
7291
|
-
return [copySpan({ ...stmt, value }, stmt)];
|
|
7292
|
-
}
|
|
7293
|
-
case "if": {
|
|
7294
|
-
const cond = this.transformExpr(stmt.cond, scope);
|
|
7295
|
-
const constant = isConstantBoolean(cond);
|
|
7296
|
-
if (constant === true) {
|
|
7297
|
-
return this.transformBlock(stmt.then, scope);
|
|
7298
|
-
}
|
|
7299
|
-
if (constant === false) {
|
|
7300
|
-
return stmt.else_ ? this.transformBlock(stmt.else_, scope) : [];
|
|
7301
|
-
}
|
|
7302
|
-
const thenBlock = this.transformBlock(stmt.then, scope);
|
|
7303
|
-
const elseBlock = stmt.else_ ? this.transformBlock(stmt.else_, scope) : void 0;
|
|
7304
|
-
if (cond === stmt.cond && thenBlock === stmt.then && elseBlock === stmt.else_) {
|
|
7305
|
-
return [stmt];
|
|
7306
|
-
}
|
|
7307
|
-
return [copySpan({ ...stmt, cond, then: thenBlock, else_: elseBlock }, stmt)];
|
|
7308
|
-
}
|
|
7309
|
-
case "while": {
|
|
7310
|
-
const cond = this.transformExpr(stmt.cond, scope);
|
|
7311
|
-
if (isConstantBoolean(cond) === false) {
|
|
7312
|
-
return [];
|
|
7313
|
-
}
|
|
7314
|
-
const body = this.transformBlock(stmt.body, scope);
|
|
7315
|
-
return [copySpan({ ...stmt, cond, body }, stmt)];
|
|
7316
|
-
}
|
|
7317
|
-
case "for": {
|
|
7318
|
-
const forScope = [...scope, []];
|
|
7319
|
-
const init = stmt.init ? this.transformStmt(stmt.init, forScope)[0] : void 0;
|
|
7320
|
-
const cond = this.transformExpr(stmt.cond, forScope);
|
|
7321
|
-
if (isConstantBoolean(cond) === false) {
|
|
7322
|
-
return init ? [init] : [];
|
|
7323
|
-
}
|
|
7324
|
-
const step = this.transformExpr(stmt.step, forScope);
|
|
7325
|
-
const body = this.transformBlock(stmt.body, forScope);
|
|
7326
|
-
return [copySpan({ ...stmt, init, cond, step, body }, stmt)];
|
|
7327
|
-
}
|
|
7328
|
-
case "foreach": {
|
|
7329
|
-
const iterable = this.transformExpr(stmt.iterable, scope);
|
|
7330
|
-
const foreachScope = [...scope, [{ id: `foreach:${stmt.binding}:${stmt.span?.line ?? 0}:${stmt.span?.col ?? 0}`, name: stmt.binding }]];
|
|
7331
|
-
const body = this.transformBlock(stmt.body, foreachScope);
|
|
7332
|
-
return [copySpan({ ...stmt, iterable, body }, stmt)];
|
|
7333
|
-
}
|
|
7334
|
-
case "for_range": {
|
|
7335
|
-
const start = this.transformExpr(stmt.start, scope);
|
|
7336
|
-
const end = this.transformExpr(stmt.end, scope);
|
|
7337
|
-
const rangeScope = [...scope, [{ id: `range:${stmt.varName}:${stmt.span?.line ?? 0}:${stmt.span?.col ?? 0}`, name: stmt.varName }]];
|
|
7338
|
-
const body = this.transformBlock(stmt.body, rangeScope);
|
|
7339
|
-
return [copySpan({ ...stmt, start, end, body }, stmt)];
|
|
7340
|
-
}
|
|
7341
|
-
case "match": {
|
|
7342
|
-
const expr = this.transformExpr(stmt.expr, scope);
|
|
7343
|
-
const arms = stmt.arms.map((arm) => ({
|
|
7344
|
-
pattern: arm.pattern ? this.transformExpr(arm.pattern, scope) : null,
|
|
7345
|
-
body: this.transformBlock(arm.body, scope)
|
|
7346
|
-
}));
|
|
7347
|
-
return [copySpan({ ...stmt, expr, arms }, stmt)];
|
|
7348
|
-
}
|
|
7349
|
-
case "as_block":
|
|
7350
|
-
return [copySpan({ ...stmt, body: this.transformBlock(stmt.body, scope) }, stmt)];
|
|
7351
|
-
case "at_block":
|
|
7352
|
-
return [copySpan({ ...stmt, body: this.transformBlock(stmt.body, scope) }, stmt)];
|
|
7353
|
-
case "as_at":
|
|
7354
|
-
return [copySpan({ ...stmt, body: this.transformBlock(stmt.body, scope) }, stmt)];
|
|
7355
|
-
case "execute":
|
|
7356
|
-
return [copySpan({ ...stmt, body: this.transformBlock(stmt.body, scope) }, stmt)];
|
|
7357
|
-
case "raw":
|
|
7358
|
-
return [stmt];
|
|
7359
|
-
case "break":
|
|
7360
|
-
return [stmt];
|
|
7361
|
-
case "continue":
|
|
7362
|
-
return [stmt];
|
|
7363
|
-
}
|
|
7750
|
+
}, null, 2)
|
|
7751
|
+
});
|
|
7364
7752
|
}
|
|
7365
|
-
|
|
7366
|
-
|
|
7367
|
-
|
|
7368
|
-
|
|
7369
|
-
case "static_call":
|
|
7370
|
-
return copySpan({ ...expr, args: expr.args.map((arg) => this.transformExpr(arg, scope)) }, expr);
|
|
7371
|
-
case "invoke":
|
|
7372
|
-
return copySpan({
|
|
7373
|
-
...expr,
|
|
7374
|
-
callee: this.transformExpr(expr.callee, scope),
|
|
7375
|
-
args: expr.args.map((arg) => this.transformExpr(arg, scope))
|
|
7376
|
-
}, expr);
|
|
7377
|
-
case "binary":
|
|
7378
|
-
return copySpan({
|
|
7379
|
-
...expr,
|
|
7380
|
-
left: this.transformExpr(expr.left, scope),
|
|
7381
|
-
right: this.transformExpr(expr.right, scope)
|
|
7382
|
-
}, expr);
|
|
7383
|
-
case "is_check":
|
|
7384
|
-
return copySpan({ ...expr, expr: this.transformExpr(expr.expr, scope) }, expr);
|
|
7385
|
-
case "unary":
|
|
7386
|
-
return copySpan({ ...expr, operand: this.transformExpr(expr.operand, scope) }, expr);
|
|
7387
|
-
case "assign":
|
|
7388
|
-
return copySpan({ ...expr, value: this.transformExpr(expr.value, scope) }, expr);
|
|
7389
|
-
case "member":
|
|
7390
|
-
return copySpan({ ...expr, obj: this.transformExpr(expr.obj, scope) }, expr);
|
|
7391
|
-
case "member_assign":
|
|
7392
|
-
return copySpan({
|
|
7393
|
-
...expr,
|
|
7394
|
-
obj: this.transformExpr(expr.obj, scope),
|
|
7395
|
-
value: this.transformExpr(expr.value, scope)
|
|
7396
|
-
}, expr);
|
|
7397
|
-
case "index":
|
|
7398
|
-
return copySpan({
|
|
7399
|
-
...expr,
|
|
7400
|
-
obj: this.transformExpr(expr.obj, scope),
|
|
7401
|
-
index: this.transformExpr(expr.index, scope)
|
|
7402
|
-
}, expr);
|
|
7403
|
-
case "array_lit":
|
|
7404
|
-
return copySpan({ ...expr, elements: expr.elements.map((element) => this.transformExpr(element, scope)) }, expr);
|
|
7405
|
-
case "struct_lit":
|
|
7406
|
-
return copySpan({
|
|
7407
|
-
...expr,
|
|
7408
|
-
fields: expr.fields.map((field) => ({ ...field, value: this.transformExpr(field.value, scope) }))
|
|
7409
|
-
}, expr);
|
|
7410
|
-
case "str_interp":
|
|
7411
|
-
return copySpan({
|
|
7412
|
-
...expr,
|
|
7413
|
-
parts: expr.parts.map((part) => typeof part === "string" ? part : this.transformExpr(part, scope))
|
|
7414
|
-
}, expr);
|
|
7415
|
-
case "f_string":
|
|
7416
|
-
return copySpan({
|
|
7417
|
-
...expr,
|
|
7418
|
-
parts: expr.parts.map((part) => part.kind === "text" ? part : { kind: "expr", expr: this.transformExpr(part.expr, scope) })
|
|
7419
|
-
}, expr);
|
|
7420
|
-
case "lambda": {
|
|
7421
|
-
const lambdaScope = [
|
|
7422
|
-
...scope.map((entries) => [...entries]),
|
|
7423
|
-
expr.params.map((param) => ({ id: `lambda:${param.name}:${expr.span?.line ?? 0}:${expr.span?.col ?? 0}`, name: param.name }))
|
|
7424
|
-
];
|
|
7425
|
-
const body = Array.isArray(expr.body) ? this.transformBlock(expr.body, lambdaScope) : this.transformExpr(expr.body, lambdaScope);
|
|
7426
|
-
return copySpan({ ...expr, body }, expr);
|
|
7427
|
-
}
|
|
7428
|
-
case "blockpos":
|
|
7429
|
-
case "bool_lit":
|
|
7430
|
-
case "byte_lit":
|
|
7431
|
-
case "double_lit":
|
|
7432
|
-
case "float_lit":
|
|
7433
|
-
case "ident":
|
|
7434
|
-
case "int_lit":
|
|
7435
|
-
case "long_lit":
|
|
7436
|
-
case "mc_name":
|
|
7437
|
-
case "range_lit":
|
|
7438
|
-
case "rel_coord":
|
|
7439
|
-
case "local_coord":
|
|
7440
|
-
case "selector":
|
|
7441
|
-
case "short_lit":
|
|
7442
|
-
case "str_lit":
|
|
7443
|
-
return expr;
|
|
7444
|
-
}
|
|
7753
|
+
const stats = (0, commands_1.createEmptyOptimizationStats)();
|
|
7754
|
+
const sourceMap = mangle ? alloc.toSourceMap() : void 0;
|
|
7755
|
+
if (!optimizeCommands) {
|
|
7756
|
+
return { files, advancements, stats, sourceMap };
|
|
7445
7757
|
}
|
|
7446
|
-
|
|
7447
|
-
|
|
7448
|
-
|
|
7449
|
-
|
|
7450
|
-
|
|
7451
|
-
|
|
7758
|
+
const optimized = applyFunctionOptimization(files);
|
|
7759
|
+
(0, commands_1.mergeOptimizationStats)(stats, optimized.stats);
|
|
7760
|
+
return { files: optimized.files, advancements, stats, sourceMap };
|
|
7761
|
+
}
|
|
7762
|
+
function generateDatapack(module3) {
|
|
7763
|
+
const generated = generateDatapackWithStats(module3);
|
|
7764
|
+
return [...generated.files, ...generated.advancements];
|
|
7452
7765
|
}
|
|
7453
7766
|
}
|
|
7454
7767
|
});
|
|
7455
7768
|
|
|
7456
|
-
// ../../dist/
|
|
7457
|
-
var
|
|
7458
|
-
"../../dist/
|
|
7769
|
+
// ../../dist/compile.js
|
|
7770
|
+
var require_compile = __commonJS({
|
|
7771
|
+
"../../dist/compile.js"(exports2) {
|
|
7459
7772
|
"use strict";
|
|
7773
|
+
var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
7774
|
+
if (k2 === void 0) k2 = k;
|
|
7775
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
7776
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7777
|
+
desc = { enumerable: true, get: function() {
|
|
7778
|
+
return m[k];
|
|
7779
|
+
} };
|
|
7780
|
+
}
|
|
7781
|
+
Object.defineProperty(o, k2, desc);
|
|
7782
|
+
}) : (function(o, m, k, k2) {
|
|
7783
|
+
if (k2 === void 0) k2 = k;
|
|
7784
|
+
o[k2] = m[k];
|
|
7785
|
+
}));
|
|
7786
|
+
var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
|
|
7787
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
7788
|
+
}) : function(o, v) {
|
|
7789
|
+
o["default"] = v;
|
|
7790
|
+
});
|
|
7791
|
+
var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
|
|
7792
|
+
var ownKeys = function(o) {
|
|
7793
|
+
ownKeys = Object.getOwnPropertyNames || function(o2) {
|
|
7794
|
+
var ar = [];
|
|
7795
|
+
for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
|
|
7796
|
+
return ar;
|
|
7797
|
+
};
|
|
7798
|
+
return ownKeys(o);
|
|
7799
|
+
};
|
|
7800
|
+
return function(mod) {
|
|
7801
|
+
if (mod && mod.__esModule) return mod;
|
|
7802
|
+
var result = {};
|
|
7803
|
+
if (mod != null) {
|
|
7804
|
+
for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
7805
|
+
}
|
|
7806
|
+
__setModuleDefault(result, mod);
|
|
7807
|
+
return result;
|
|
7808
|
+
};
|
|
7809
|
+
})();
|
|
7460
7810
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
7461
|
-
exports2.
|
|
7462
|
-
exports2.
|
|
7463
|
-
exports2.
|
|
7464
|
-
|
|
7465
|
-
|
|
7466
|
-
var
|
|
7467
|
-
|
|
7468
|
-
|
|
7811
|
+
exports2.resolveSourceLine = resolveSourceLine;
|
|
7812
|
+
exports2.preprocessSourceWithMetadata = preprocessSourceWithMetadata;
|
|
7813
|
+
exports2.preprocessSource = preprocessSource;
|
|
7814
|
+
exports2.compile = compile;
|
|
7815
|
+
exports2.formatCompileError = formatCompileError;
|
|
7816
|
+
var fs2 = __importStar(require("fs"));
|
|
7817
|
+
var path2 = __importStar(require("path"));
|
|
7818
|
+
var lexer_1 = require_lexer();
|
|
7819
|
+
var parser_1 = require_parser();
|
|
7820
|
+
var lowering_1 = require_lowering();
|
|
7821
|
+
var passes_1 = require_passes();
|
|
7822
|
+
var dce_1 = require_dce();
|
|
7823
|
+
var mcfunction_1 = require_mcfunction();
|
|
7824
|
+
var diagnostics_1 = require_diagnostics();
|
|
7825
|
+
function resolveSourceLine(combinedLine, ranges, fallbackFile) {
|
|
7826
|
+
for (const range of ranges) {
|
|
7827
|
+
if (combinedLine >= range.startLine && combinedLine <= range.endLine) {
|
|
7828
|
+
const localLine = combinedLine - range.startLine + 1;
|
|
7829
|
+
return { filePath: range.filePath, line: localLine };
|
|
7830
|
+
}
|
|
7831
|
+
}
|
|
7832
|
+
return { filePath: fallbackFile, line: combinedLine };
|
|
7469
7833
|
}
|
|
7470
|
-
|
|
7471
|
-
|
|
7472
|
-
|
|
7473
|
-
|
|
7474
|
-
|
|
7475
|
-
|
|
7834
|
+
var IMPORT_RE = /^\s*import\s+"([^"]+)"\s*;?\s*$/;
|
|
7835
|
+
function isLibrarySource(source) {
|
|
7836
|
+
for (const line of source.split("\n")) {
|
|
7837
|
+
const trimmed = line.trim();
|
|
7838
|
+
if (!trimmed || trimmed.startsWith("//"))
|
|
7839
|
+
continue;
|
|
7840
|
+
return /^module\s+library\s*;/.test(trimmed);
|
|
7841
|
+
}
|
|
7842
|
+
return false;
|
|
7476
7843
|
}
|
|
7477
|
-
function
|
|
7478
|
-
return
|
|
7844
|
+
function countLines(source) {
|
|
7845
|
+
return source === "" ? 0 : source.split("\n").length;
|
|
7479
7846
|
}
|
|
7480
|
-
function
|
|
7481
|
-
|
|
7482
|
-
|
|
7483
|
-
|
|
7484
|
-
|
|
7485
|
-
|
|
7486
|
-
if (instr.op === "binop") {
|
|
7487
|
-
if (instr.lhs.kind === "const")
|
|
7488
|
-
consts.add(instr.lhs.value);
|
|
7489
|
-
if (instr.rhs.kind === "const")
|
|
7490
|
-
consts.add(instr.rhs.value);
|
|
7491
|
-
}
|
|
7492
|
-
if (instr.op === "cmp") {
|
|
7493
|
-
if (instr.lhs.kind === "const")
|
|
7494
|
-
consts.add(instr.lhs.value);
|
|
7495
|
-
if (instr.rhs.kind === "const")
|
|
7496
|
-
consts.add(instr.rhs.value);
|
|
7497
|
-
}
|
|
7498
|
-
}
|
|
7499
|
-
const t = block.term;
|
|
7500
|
-
if (t.op === "return" && t.value?.kind === "const")
|
|
7501
|
-
consts.add(t.value.value);
|
|
7502
|
-
}
|
|
7503
|
-
return consts;
|
|
7847
|
+
function offsetRanges(ranges, lineOffset) {
|
|
7848
|
+
return ranges.map((range) => ({
|
|
7849
|
+
startLine: range.startLine + lineOffset,
|
|
7850
|
+
endLine: range.endLine + lineOffset,
|
|
7851
|
+
filePath: range.filePath
|
|
7852
|
+
}));
|
|
7504
7853
|
}
|
|
7505
|
-
|
|
7506
|
-
|
|
7507
|
-
|
|
7508
|
-
|
|
7509
|
-
|
|
7510
|
-
|
|
7511
|
-
|
|
7512
|
-
|
|
7513
|
-
const
|
|
7514
|
-
|
|
7515
|
-
|
|
7516
|
-
|
|
7517
|
-
|
|
7518
|
-
|
|
7519
|
-
|
|
7520
|
-
|
|
7521
|
-
|
|
7522
|
-
|
|
7523
|
-
lines.push(`execute store result score ${dst} ${OBJ} run data get storage ${src.path}`);
|
|
7524
|
-
}
|
|
7525
|
-
break;
|
|
7526
|
-
}
|
|
7527
|
-
case "binop": {
|
|
7528
|
-
const dst = varRef(instr.dst);
|
|
7529
|
-
const bop = BOP_OP[instr.bop] ?? "+=";
|
|
7530
|
-
lines.push(...emitInstr({ op: "assign", dst: instr.dst, src: instr.lhs }, ns));
|
|
7531
|
-
lines.push(`scoreboard players operation ${dst} ${OBJ} ${bop} ${operandToScore(instr.rhs)}`);
|
|
7532
|
-
break;
|
|
7533
|
-
}
|
|
7534
|
-
case "cmp": {
|
|
7535
|
-
const dst = varRef(instr.dst);
|
|
7536
|
-
const lhsScore = operandToScore(instr.lhs);
|
|
7537
|
-
const rhsScore = operandToScore(instr.rhs);
|
|
7538
|
-
lines.push(`scoreboard players set ${dst} ${OBJ} 0`);
|
|
7539
|
-
switch (instr.cop) {
|
|
7540
|
-
case "==":
|
|
7541
|
-
lines.push(`execute if score ${lhsScore} = ${rhsScore} run scoreboard players set ${dst} ${OBJ} 1`);
|
|
7542
|
-
break;
|
|
7543
|
-
case "!=":
|
|
7544
|
-
lines.push(`execute unless score ${lhsScore} = ${rhsScore} run scoreboard players set ${dst} ${OBJ} 1`);
|
|
7545
|
-
break;
|
|
7546
|
-
case "<":
|
|
7547
|
-
lines.push(`execute if score ${lhsScore} < ${rhsScore} run scoreboard players set ${dst} ${OBJ} 1`);
|
|
7548
|
-
break;
|
|
7549
|
-
case "<=":
|
|
7550
|
-
lines.push(`execute if score ${lhsScore} <= ${rhsScore} run scoreboard players set ${dst} ${OBJ} 1`);
|
|
7551
|
-
break;
|
|
7552
|
-
case ">":
|
|
7553
|
-
lines.push(`execute if score ${lhsScore} > ${rhsScore} run scoreboard players set ${dst} ${OBJ} 1`);
|
|
7554
|
-
break;
|
|
7555
|
-
case ">=":
|
|
7556
|
-
lines.push(`execute if score ${lhsScore} >= ${rhsScore} run scoreboard players set ${dst} ${OBJ} 1`);
|
|
7557
|
-
break;
|
|
7558
|
-
}
|
|
7559
|
-
break;
|
|
7560
|
-
}
|
|
7561
|
-
case "call": {
|
|
7562
|
-
for (let i = 0; i < instr.args.length; i++) {
|
|
7563
|
-
lines.push(...emitInstr({ op: "assign", dst: `$p${i}`, src: instr.args[i] }, ns));
|
|
7854
|
+
function preprocessSourceWithMetadata(source, options = {}) {
|
|
7855
|
+
const { filePath } = options;
|
|
7856
|
+
const seen = options.seen ?? /* @__PURE__ */ new Set();
|
|
7857
|
+
if (filePath) {
|
|
7858
|
+
seen.add(path2.resolve(filePath));
|
|
7859
|
+
}
|
|
7860
|
+
const lines = source.split("\n");
|
|
7861
|
+
const imports = [];
|
|
7862
|
+
const libraryImports = [];
|
|
7863
|
+
const bodyLines = [];
|
|
7864
|
+
let parsingHeader = true;
|
|
7865
|
+
for (let i = 0; i < lines.length; i++) {
|
|
7866
|
+
const line = lines[i];
|
|
7867
|
+
const trimmed = line.trim();
|
|
7868
|
+
const match = line.match(IMPORT_RE);
|
|
7869
|
+
if (parsingHeader && match) {
|
|
7870
|
+
if (!filePath) {
|
|
7871
|
+
throw new diagnostics_1.DiagnosticError("ParseError", "Import statements require a file path", { line: i + 1, col: 1 }, lines);
|
|
7564
7872
|
}
|
|
7565
|
-
|
|
7566
|
-
if (
|
|
7567
|
-
|
|
7873
|
+
const importPath = path2.resolve(path2.dirname(filePath), match[1]);
|
|
7874
|
+
if (!seen.has(importPath)) {
|
|
7875
|
+
seen.add(importPath);
|
|
7876
|
+
let importedSource;
|
|
7877
|
+
try {
|
|
7878
|
+
importedSource = fs2.readFileSync(importPath, "utf-8");
|
|
7879
|
+
} catch {
|
|
7880
|
+
throw new diagnostics_1.DiagnosticError("ParseError", `Cannot import '${match[1]}'`, { file: filePath, line: i + 1, col: 1 }, lines);
|
|
7881
|
+
}
|
|
7882
|
+
if (isLibrarySource(importedSource)) {
|
|
7883
|
+
const nested = preprocessSourceWithMetadata(importedSource, { filePath: importPath, seen });
|
|
7884
|
+
libraryImports.push({ source: importedSource, filePath: importPath });
|
|
7885
|
+
if (nested.libraryImports)
|
|
7886
|
+
libraryImports.push(...nested.libraryImports);
|
|
7887
|
+
} else {
|
|
7888
|
+
imports.push(preprocessSourceWithMetadata(importedSource, { filePath: importPath, seen }));
|
|
7889
|
+
}
|
|
7568
7890
|
}
|
|
7569
|
-
|
|
7891
|
+
continue;
|
|
7570
7892
|
}
|
|
7571
|
-
|
|
7572
|
-
|
|
7573
|
-
|
|
7893
|
+
if (parsingHeader && (trimmed === "" || trimmed.startsWith("//"))) {
|
|
7894
|
+
bodyLines.push(line);
|
|
7895
|
+
continue;
|
|
7896
|
+
}
|
|
7897
|
+
parsingHeader = false;
|
|
7898
|
+
bodyLines.push(line);
|
|
7574
7899
|
}
|
|
7575
|
-
|
|
7576
|
-
|
|
7577
|
-
|
|
7578
|
-
const
|
|
7579
|
-
|
|
7580
|
-
|
|
7581
|
-
|
|
7582
|
-
|
|
7583
|
-
|
|
7584
|
-
|
|
7585
|
-
|
|
7586
|
-
|
|
7587
|
-
|
|
7588
|
-
|
|
7589
|
-
|
|
7590
|
-
break;
|
|
7591
|
-
case "return":
|
|
7592
|
-
if (term.value) {
|
|
7593
|
-
lines.push(...emitInstr({ op: "assign", dst: "$ret", src: term.value }, ns));
|
|
7594
|
-
}
|
|
7595
|
-
if (term.value?.kind === "const") {
|
|
7596
|
-
lines.push(`return ${term.value.value}`);
|
|
7597
|
-
} else if (term.value?.kind === "var") {
|
|
7598
|
-
lines.push(`return run scoreboard players get ${varRef(term.value.name)} ${OBJ}`);
|
|
7599
|
-
}
|
|
7600
|
-
break;
|
|
7601
|
-
case "tick_yield":
|
|
7602
|
-
lines.push(`schedule function ${ns}:${fnName}/${term.continuation} 1t replace`);
|
|
7603
|
-
break;
|
|
7900
|
+
const body = bodyLines.join("\n");
|
|
7901
|
+
const parts = [...imports.map((entry) => entry.source), body].filter(Boolean);
|
|
7902
|
+
const combined = parts.join("\n");
|
|
7903
|
+
const ranges = [];
|
|
7904
|
+
let lineOffset = 0;
|
|
7905
|
+
for (const entry of imports) {
|
|
7906
|
+
ranges.push(...offsetRanges(entry.ranges, lineOffset));
|
|
7907
|
+
lineOffset += countLines(entry.source);
|
|
7908
|
+
}
|
|
7909
|
+
if (filePath && body) {
|
|
7910
|
+
ranges.push({
|
|
7911
|
+
startLine: lineOffset + 1,
|
|
7912
|
+
endLine: lineOffset + countLines(body),
|
|
7913
|
+
filePath: path2.resolve(filePath)
|
|
7914
|
+
});
|
|
7604
7915
|
}
|
|
7605
|
-
return lines;
|
|
7606
|
-
}
|
|
7607
|
-
function toFunctionName(file) {
|
|
7608
|
-
const match = file.path.match(/^data\/[^/]+\/function\/(.+)\.mcfunction$/);
|
|
7609
|
-
return match?.[1] ?? null;
|
|
7610
|
-
}
|
|
7611
|
-
function applyFunctionOptimization(files) {
|
|
7612
|
-
const functionFiles = files.map((file) => {
|
|
7613
|
-
const functionName = toFunctionName(file);
|
|
7614
|
-
if (!functionName)
|
|
7615
|
-
return null;
|
|
7616
|
-
const commands = file.content.split("\n").map((line) => line.trim()).filter((line) => line !== "" && !line.startsWith("#")).map((cmd) => ({ cmd }));
|
|
7617
|
-
return { file, functionName, commands };
|
|
7618
|
-
}).filter((entry) => entry !== null);
|
|
7619
|
-
const optimized = (0, commands_1.optimizeCommandFunctions)(functionFiles.map((entry) => ({
|
|
7620
|
-
name: entry.functionName,
|
|
7621
|
-
commands: entry.commands
|
|
7622
|
-
})));
|
|
7623
|
-
const commandMap = new Map(optimized.functions.map((fn) => [fn.name, fn.commands]));
|
|
7624
|
-
const optimizedNames = new Set(optimized.functions.map((fn) => fn.name));
|
|
7625
7916
|
return {
|
|
7626
|
-
|
|
7627
|
-
|
|
7628
|
-
|
|
7629
|
-
}).map((file) => {
|
|
7630
|
-
const functionName = toFunctionName(file);
|
|
7631
|
-
if (!functionName)
|
|
7632
|
-
return file;
|
|
7633
|
-
const commands = commandMap.get(functionName);
|
|
7634
|
-
if (!commands)
|
|
7635
|
-
return file;
|
|
7636
|
-
const lines = file.content.split("\n");
|
|
7637
|
-
const header = lines.filter((line) => line.trim().startsWith("#"));
|
|
7638
|
-
return {
|
|
7639
|
-
...file,
|
|
7640
|
-
content: [...header, ...commands.map((command) => command.cmd)].join("\n")
|
|
7641
|
-
};
|
|
7642
|
-
}),
|
|
7643
|
-
stats: optimized.stats
|
|
7917
|
+
source: combined,
|
|
7918
|
+
ranges,
|
|
7919
|
+
libraryImports: libraryImports.length > 0 ? libraryImports : void 0
|
|
7644
7920
|
};
|
|
7645
7921
|
}
|
|
7646
|
-
function
|
|
7647
|
-
return
|
|
7648
|
-
if (!toFunctionName(file)) {
|
|
7649
|
-
return sum;
|
|
7650
|
-
}
|
|
7651
|
-
return sum + file.content.split("\n").map((line) => line.trim()).filter((line) => line !== "" && !line.startsWith("#")).length;
|
|
7652
|
-
}, 0);
|
|
7922
|
+
function preprocessSource(source, options = {}) {
|
|
7923
|
+
return preprocessSourceWithMetadata(source, options).source;
|
|
7653
7924
|
}
|
|
7654
|
-
function
|
|
7655
|
-
const {
|
|
7656
|
-
const
|
|
7657
|
-
|
|
7658
|
-
|
|
7659
|
-
|
|
7660
|
-
|
|
7661
|
-
|
|
7662
|
-
|
|
7663
|
-
|
|
7664
|
-
|
|
7665
|
-
|
|
7666
|
-
|
|
7925
|
+
function compile(source, options = {}) {
|
|
7926
|
+
const { namespace = "redscript", filePath, optimize: shouldOptimize = true } = options;
|
|
7927
|
+
const shouldRunDce = options.dce ?? shouldOptimize;
|
|
7928
|
+
let sourceLines = source.split("\n");
|
|
7929
|
+
try {
|
|
7930
|
+
const preprocessed = preprocessSourceWithMetadata(source, { filePath });
|
|
7931
|
+
const preprocessedSource = preprocessed.source;
|
|
7932
|
+
sourceLines = preprocessedSource.split("\n");
|
|
7933
|
+
const tokens = new lexer_1.Lexer(preprocessedSource, filePath).tokenize();
|
|
7934
|
+
const parsedAst = new parser_1.Parser(tokens, preprocessedSource, filePath).parse(namespace);
|
|
7935
|
+
const allLibrarySources = [];
|
|
7936
|
+
for (const libSrc of options.librarySources ?? []) {
|
|
7937
|
+
allLibrarySources.push({ src: libSrc });
|
|
7938
|
+
}
|
|
7939
|
+
for (const li of preprocessed.libraryImports ?? []) {
|
|
7940
|
+
allLibrarySources.push({ src: li.source, fp: li.filePath });
|
|
7941
|
+
}
|
|
7942
|
+
for (const { src, fp } of allLibrarySources) {
|
|
7943
|
+
const libPreprocessed = preprocessSourceWithMetadata(src, fp ? { filePath: fp } : {});
|
|
7944
|
+
const libTokens = new lexer_1.Lexer(libPreprocessed.source, fp).tokenize();
|
|
7945
|
+
const libAst = new parser_1.Parser(libTokens, libPreprocessed.source, fp).parse(namespace);
|
|
7946
|
+
for (const fn of libAst.declarations)
|
|
7947
|
+
fn.isLibraryFn = true;
|
|
7948
|
+
parsedAst.declarations.push(...libAst.declarations);
|
|
7949
|
+
parsedAst.structs.push(...libAst.structs);
|
|
7950
|
+
parsedAst.implBlocks.push(...libAst.implBlocks);
|
|
7951
|
+
parsedAst.enums.push(...libAst.enums);
|
|
7952
|
+
parsedAst.consts.push(...libAst.consts);
|
|
7953
|
+
parsedAst.globals.push(...libAst.globals);
|
|
7954
|
+
}
|
|
7955
|
+
const dceResult = shouldRunDce ? (0, dce_1.eliminateDeadCode)(parsedAst) : { program: parsedAst, warnings: [] };
|
|
7956
|
+
const ast = dceResult.program;
|
|
7957
|
+
const scoreboardObj = options.scoreboardObjective ?? `__${namespace}`;
|
|
7958
|
+
(0, lowering_1.setScoreboardObjective)(scoreboardObj);
|
|
7959
|
+
const ir = new lowering_1.Lowering(namespace, preprocessed.ranges).lower(ast);
|
|
7960
|
+
const optimized = shouldOptimize ? { ...ir, functions: ir.functions.map((fn) => (0, passes_1.optimize)(fn)) } : ir;
|
|
7961
|
+
const generated = (0, mcfunction_1.generateDatapackWithStats)(optimized, {
|
|
7962
|
+
mangle: options.mangle ?? true,
|
|
7963
|
+
scoreboardObjective: scoreboardObj
|
|
7964
|
+
});
|
|
7965
|
+
return {
|
|
7966
|
+
success: true,
|
|
7967
|
+
files: [...generated.files, ...generated.advancements],
|
|
7968
|
+
advancements: generated.advancements,
|
|
7969
|
+
ast,
|
|
7970
|
+
ir: optimized
|
|
7971
|
+
};
|
|
7972
|
+
} catch (err) {
|
|
7973
|
+
if (err instanceof diagnostics_1.DiagnosticError) {
|
|
7974
|
+
return { success: false, error: err };
|
|
7975
|
+
}
|
|
7976
|
+
if (err instanceof Error) {
|
|
7977
|
+
const diagnostic = (0, diagnostics_1.parseErrorMessage)("ParseError", err.message, sourceLines, filePath);
|
|
7978
|
+
return { success: false, error: diagnostic };
|
|
7667
7979
|
}
|
|
7980
|
+
return {
|
|
7981
|
+
success: false,
|
|
7982
|
+
error: new diagnostics_1.DiagnosticError("ParseError", String(err), { file: filePath, line: 1, col: 1 }, sourceLines)
|
|
7983
|
+
};
|
|
7668
7984
|
}
|
|
7669
|
-
|
|
7670
|
-
|
|
7671
|
-
|
|
7672
|
-
|
|
7673
|
-
}, null, 2)
|
|
7674
|
-
});
|
|
7675
|
-
const loadLines = [
|
|
7676
|
-
`# RedScript runtime init`,
|
|
7677
|
-
`scoreboard objectives add ${OBJ} dummy`
|
|
7678
|
-
];
|
|
7679
|
-
for (const g of module3.globals) {
|
|
7680
|
-
loadLines.push(`scoreboard players set ${varRef(g.name)} ${OBJ} ${g.init}`);
|
|
7985
|
+
}
|
|
7986
|
+
function formatCompileError(result) {
|
|
7987
|
+
if (result.success) {
|
|
7988
|
+
return "Compilation successful";
|
|
7681
7989
|
}
|
|
7682
|
-
|
|
7683
|
-
|
|
7684
|
-
|
|
7990
|
+
if (result.error) {
|
|
7991
|
+
return (0, diagnostics_1.formatError)(result.error, result.error.sourceLines?.join("\n"));
|
|
7992
|
+
}
|
|
7993
|
+
return "Unknown error";
|
|
7994
|
+
}
|
|
7995
|
+
}
|
|
7996
|
+
});
|
|
7997
|
+
|
|
7998
|
+
// ../../dist/optimizer/dce.js
|
|
7999
|
+
var require_dce = __commonJS({
|
|
8000
|
+
"../../dist/optimizer/dce.js"(exports2) {
|
|
8001
|
+
"use strict";
|
|
8002
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
8003
|
+
exports2.DeadCodeEliminator = void 0;
|
|
8004
|
+
exports2.eliminateDeadCode = eliminateDeadCode;
|
|
8005
|
+
function copySpan(target, source) {
|
|
8006
|
+
const descriptor = Object.getOwnPropertyDescriptor(source, "span");
|
|
8007
|
+
if (descriptor) {
|
|
8008
|
+
Object.defineProperty(target, "span", descriptor);
|
|
8009
|
+
}
|
|
8010
|
+
return target;
|
|
8011
|
+
}
|
|
8012
|
+
function isConstantBoolean(expr) {
|
|
8013
|
+
if (expr.kind === "bool_lit") {
|
|
8014
|
+
return expr.value;
|
|
8015
|
+
}
|
|
8016
|
+
return null;
|
|
8017
|
+
}
|
|
8018
|
+
function isPureExpr(expr) {
|
|
8019
|
+
switch (expr.kind) {
|
|
8020
|
+
case "int_lit":
|
|
8021
|
+
case "float_lit":
|
|
8022
|
+
case "byte_lit":
|
|
8023
|
+
case "short_lit":
|
|
8024
|
+
case "long_lit":
|
|
8025
|
+
case "double_lit":
|
|
8026
|
+
case "rel_coord":
|
|
8027
|
+
case "local_coord":
|
|
8028
|
+
case "bool_lit":
|
|
8029
|
+
case "str_lit":
|
|
8030
|
+
case "mc_name":
|
|
8031
|
+
case "range_lit":
|
|
8032
|
+
case "selector":
|
|
8033
|
+
case "ident":
|
|
8034
|
+
case "blockpos":
|
|
8035
|
+
return true;
|
|
8036
|
+
case "str_interp":
|
|
8037
|
+
return expr.parts.every((part) => typeof part === "string" || isPureExpr(part));
|
|
8038
|
+
case "f_string":
|
|
8039
|
+
return expr.parts.every((part) => part.kind === "text" || isPureExpr(part.expr));
|
|
8040
|
+
case "binary":
|
|
8041
|
+
return isPureExpr(expr.left) && isPureExpr(expr.right);
|
|
8042
|
+
case "is_check":
|
|
8043
|
+
return isPureExpr(expr.expr);
|
|
8044
|
+
case "unary":
|
|
8045
|
+
return isPureExpr(expr.operand);
|
|
8046
|
+
case "member":
|
|
8047
|
+
return isPureExpr(expr.obj);
|
|
8048
|
+
case "index":
|
|
8049
|
+
return isPureExpr(expr.obj) && isPureExpr(expr.index);
|
|
8050
|
+
case "array_lit":
|
|
8051
|
+
return expr.elements.every(isPureExpr);
|
|
8052
|
+
case "struct_lit":
|
|
8053
|
+
return expr.fields.every((field) => isPureExpr(field.value));
|
|
8054
|
+
case "lambda":
|
|
8055
|
+
return true;
|
|
8056
|
+
case "assign":
|
|
8057
|
+
case "member_assign":
|
|
8058
|
+
case "call":
|
|
8059
|
+
case "invoke":
|
|
8060
|
+
case "static_call":
|
|
8061
|
+
return false;
|
|
8062
|
+
}
|
|
8063
|
+
}
|
|
8064
|
+
var DeadCodeEliminator = class {
|
|
8065
|
+
constructor() {
|
|
8066
|
+
this.functionMap = /* @__PURE__ */ new Map();
|
|
8067
|
+
this.reachableFunctions = /* @__PURE__ */ new Set();
|
|
8068
|
+
this.usedConstants = /* @__PURE__ */ new Set();
|
|
8069
|
+
this.localReads = /* @__PURE__ */ new Set();
|
|
8070
|
+
this.localDeclIds = /* @__PURE__ */ new WeakMap();
|
|
8071
|
+
this.localIdCounter = 0;
|
|
8072
|
+
this.warnings = [];
|
|
7685
8073
|
}
|
|
7686
|
-
|
|
7687
|
-
|
|
7688
|
-
|
|
7689
|
-
|
|
7690
|
-
|
|
7691
|
-
|
|
7692
|
-
|
|
7693
|
-
|
|
7694
|
-
|
|
7695
|
-
loadLines.push(`# ${eventType} detection expects tag ${types_1.EVENT_TYPES[eventType].tag} to be set externally`);
|
|
8074
|
+
eliminate(program) {
|
|
8075
|
+
this.functionMap.clear();
|
|
8076
|
+
this.reachableFunctions.clear();
|
|
8077
|
+
this.usedConstants.clear();
|
|
8078
|
+
this.localReads.clear();
|
|
8079
|
+
this.localIdCounter = 0;
|
|
8080
|
+
this.warnings.length = 0;
|
|
8081
|
+
for (const fn of program.declarations) {
|
|
8082
|
+
this.functionMap.set(fn.name, fn);
|
|
7696
8083
|
}
|
|
7697
|
-
|
|
7698
|
-
|
|
7699
|
-
|
|
7700
|
-
|
|
7701
|
-
|
|
7702
|
-
|
|
7703
|
-
|
|
7704
|
-
|
|
8084
|
+
const entryPoints = this.findEntryPoints(program);
|
|
8085
|
+
if (entryPoints.length === 0) {
|
|
8086
|
+
for (const fn of program.declarations) {
|
|
8087
|
+
this.markReachable(fn.name);
|
|
8088
|
+
}
|
|
8089
|
+
} else {
|
|
8090
|
+
for (const fnName of entryPoints) {
|
|
8091
|
+
this.markReachable(fnName);
|
|
8092
|
+
}
|
|
7705
8093
|
}
|
|
7706
|
-
|
|
7707
|
-
|
|
7708
|
-
files.push({
|
|
7709
|
-
path: `data/${ns}/function/__trigger_${triggerName}_dispatch.mcfunction`,
|
|
7710
|
-
content: dispatchLines.join("\n")
|
|
7711
|
-
});
|
|
7712
|
-
}
|
|
7713
|
-
for (const fn of module3.functions) {
|
|
7714
|
-
const consts = collectConsts(fn);
|
|
7715
|
-
if (consts.size > 0) {
|
|
7716
|
-
loadLines.push(...Array.from(consts).map(constSetup));
|
|
8094
|
+
for (const global of program.globals) {
|
|
8095
|
+
this.collectExprRefs(global.init, []);
|
|
7717
8096
|
}
|
|
7718
|
-
for (
|
|
7719
|
-
const
|
|
7720
|
-
|
|
7721
|
-
|
|
7722
|
-
|
|
7723
|
-
|
|
8097
|
+
for (const implBlock of program.implBlocks) {
|
|
8098
|
+
for (const method of implBlock.methods) {
|
|
8099
|
+
this.collectFunctionRefs(method);
|
|
8100
|
+
}
|
|
8101
|
+
}
|
|
8102
|
+
return {
|
|
8103
|
+
...program,
|
|
8104
|
+
declarations: program.declarations.filter((fn) => this.reachableFunctions.has(fn.name)).map((fn) => this.transformFunction(fn)),
|
|
8105
|
+
consts: program.consts.filter((constDecl) => this.usedConstants.has(constDecl.name)),
|
|
8106
|
+
implBlocks: program.implBlocks.map((implBlock) => ({
|
|
8107
|
+
...implBlock,
|
|
8108
|
+
methods: implBlock.methods.map((method) => this.transformFunction(method))
|
|
8109
|
+
}))
|
|
8110
|
+
};
|
|
8111
|
+
}
|
|
8112
|
+
findEntryPoints(program) {
|
|
8113
|
+
const entries = /* @__PURE__ */ new Set();
|
|
8114
|
+
for (const fn of program.declarations) {
|
|
8115
|
+
if (!fn.isLibraryFn) {
|
|
8116
|
+
if (!fn.name.startsWith("_")) {
|
|
8117
|
+
entries.add(fn.name);
|
|
7724
8118
|
}
|
|
7725
8119
|
}
|
|
7726
|
-
|
|
7727
|
-
|
|
8120
|
+
if (fn.decorators.some((decorator) => [
|
|
8121
|
+
"tick",
|
|
8122
|
+
"load",
|
|
8123
|
+
"on",
|
|
8124
|
+
"on_trigger",
|
|
8125
|
+
"on_advancement",
|
|
8126
|
+
"on_craft",
|
|
8127
|
+
"on_death",
|
|
8128
|
+
"on_login",
|
|
8129
|
+
"on_join_team",
|
|
8130
|
+
"keep"
|
|
8131
|
+
].includes(decorator.name))) {
|
|
8132
|
+
entries.add(fn.name);
|
|
7728
8133
|
}
|
|
7729
|
-
lines.push(...emitTerm(block.term, ns, fn.name));
|
|
7730
|
-
const filePath = i === 0 ? `data/${ns}/function/${fn.name}.mcfunction` : `data/${ns}/function/${fn.name}/${block.label}.mcfunction`;
|
|
7731
|
-
files.push({ path: filePath, content: lines.join("\n") });
|
|
7732
8134
|
}
|
|
8135
|
+
return [...entries];
|
|
7733
8136
|
}
|
|
7734
|
-
|
|
7735
|
-
if (
|
|
7736
|
-
|
|
8137
|
+
markReachable(fnName) {
|
|
8138
|
+
if (this.reachableFunctions.has(fnName)) {
|
|
8139
|
+
return;
|
|
8140
|
+
}
|
|
8141
|
+
const fn = this.functionMap.get(fnName);
|
|
8142
|
+
if (!fn) {
|
|
8143
|
+
return;
|
|
8144
|
+
}
|
|
8145
|
+
this.reachableFunctions.add(fnName);
|
|
8146
|
+
this.collectFunctionRefs(fn);
|
|
8147
|
+
for (const decorator of fn.decorators) {
|
|
8148
|
+
if (decorator.name === "require_on_load") {
|
|
8149
|
+
for (const arg of decorator.rawArgs ?? []) {
|
|
8150
|
+
if (arg.kind === "string") {
|
|
8151
|
+
this.markReachable(arg.value);
|
|
8152
|
+
}
|
|
8153
|
+
}
|
|
8154
|
+
}
|
|
7737
8155
|
}
|
|
7738
8156
|
}
|
|
7739
|
-
|
|
7740
|
-
|
|
7741
|
-
|
|
7742
|
-
|
|
7743
|
-
|
|
7744
|
-
|
|
7745
|
-
|
|
7746
|
-
|
|
7747
|
-
const tickLines = ["# RedScript tick dispatcher"];
|
|
7748
|
-
for (const fnName of tickFunctionNames) {
|
|
7749
|
-
tickLines.push(`function ${ns}:${fnName}`);
|
|
8157
|
+
collectFunctionRefs(fn) {
|
|
8158
|
+
const scope = [fn.params.map((param) => ({ id: `param:${fn.name}:${param.name}`, name: param.name }))];
|
|
8159
|
+
for (const param of fn.params) {
|
|
8160
|
+
if (param.default) {
|
|
8161
|
+
this.collectExprRefs(param.default, scope);
|
|
8162
|
+
}
|
|
8163
|
+
}
|
|
8164
|
+
this.collectStmtRefs(fn.body, scope);
|
|
7750
8165
|
}
|
|
7751
|
-
|
|
7752
|
-
|
|
7753
|
-
for (const
|
|
7754
|
-
|
|
8166
|
+
collectStmtRefs(block, scope) {
|
|
8167
|
+
scope.push([]);
|
|
8168
|
+
for (const stmt of block) {
|
|
8169
|
+
this.collectStmtRef(stmt, scope);
|
|
7755
8170
|
}
|
|
8171
|
+
scope.pop();
|
|
7756
8172
|
}
|
|
7757
|
-
|
|
7758
|
-
|
|
7759
|
-
|
|
7760
|
-
|
|
7761
|
-
|
|
7762
|
-
|
|
7763
|
-
|
|
8173
|
+
collectStmtRef(stmt, scope) {
|
|
8174
|
+
switch (stmt.kind) {
|
|
8175
|
+
case "let": {
|
|
8176
|
+
this.collectExprRefs(stmt.init, scope);
|
|
8177
|
+
const id = `local:${stmt.name}:${this.localIdCounter++}:${stmt.span?.line ?? 0}:${stmt.span?.col ?? 0}`;
|
|
8178
|
+
this.localDeclIds.set(stmt, id);
|
|
8179
|
+
scope[scope.length - 1].push({ id, name: stmt.name });
|
|
8180
|
+
break;
|
|
7764
8181
|
}
|
|
7765
|
-
|
|
8182
|
+
case "expr":
|
|
8183
|
+
this.collectExprRefs(stmt.expr, scope);
|
|
8184
|
+
break;
|
|
8185
|
+
case "return":
|
|
8186
|
+
if (stmt.value) {
|
|
8187
|
+
this.collectExprRefs(stmt.value, scope);
|
|
8188
|
+
}
|
|
8189
|
+
break;
|
|
8190
|
+
case "if": {
|
|
8191
|
+
this.collectExprRefs(stmt.cond, scope);
|
|
8192
|
+
const constant = isConstantBoolean(stmt.cond);
|
|
8193
|
+
if (constant === true) {
|
|
8194
|
+
this.collectStmtRefs(stmt.then, scope);
|
|
8195
|
+
} else if (constant === false) {
|
|
8196
|
+
if (stmt.else_) {
|
|
8197
|
+
this.collectStmtRefs(stmt.else_, scope);
|
|
8198
|
+
}
|
|
8199
|
+
} else {
|
|
8200
|
+
this.collectStmtRefs(stmt.then, scope);
|
|
8201
|
+
if (stmt.else_) {
|
|
8202
|
+
this.collectStmtRefs(stmt.else_, scope);
|
|
8203
|
+
}
|
|
8204
|
+
}
|
|
8205
|
+
break;
|
|
8206
|
+
}
|
|
8207
|
+
case "while":
|
|
8208
|
+
this.collectExprRefs(stmt.cond, scope);
|
|
8209
|
+
this.collectStmtRefs(stmt.body, scope);
|
|
8210
|
+
break;
|
|
8211
|
+
case "for":
|
|
8212
|
+
scope.push([]);
|
|
8213
|
+
if (stmt.init) {
|
|
8214
|
+
this.collectStmtRef(stmt.init, scope);
|
|
8215
|
+
}
|
|
8216
|
+
this.collectExprRefs(stmt.cond, scope);
|
|
8217
|
+
this.collectExprRefs(stmt.step, scope);
|
|
8218
|
+
this.collectStmtRefs(stmt.body, scope);
|
|
8219
|
+
scope.pop();
|
|
8220
|
+
break;
|
|
8221
|
+
case "foreach":
|
|
8222
|
+
this.collectExprRefs(stmt.iterable, scope);
|
|
8223
|
+
scope.push([{ id: `foreach:${stmt.binding}:${stmt.span?.line ?? 0}:${stmt.span?.col ?? 0}`, name: stmt.binding }]);
|
|
8224
|
+
this.collectStmtRefs(stmt.body, scope);
|
|
8225
|
+
scope.pop();
|
|
8226
|
+
break;
|
|
8227
|
+
case "for_range":
|
|
8228
|
+
this.collectExprRefs(stmt.start, scope);
|
|
8229
|
+
this.collectExprRefs(stmt.end, scope);
|
|
8230
|
+
scope.push([{ id: `range:${stmt.varName}:${stmt.span?.line ?? 0}:${stmt.span?.col ?? 0}`, name: stmt.varName }]);
|
|
8231
|
+
this.collectStmtRefs(stmt.body, scope);
|
|
8232
|
+
scope.pop();
|
|
8233
|
+
break;
|
|
8234
|
+
case "match":
|
|
8235
|
+
this.collectExprRefs(stmt.expr, scope);
|
|
8236
|
+
for (const arm of stmt.arms) {
|
|
8237
|
+
if (arm.pattern) {
|
|
8238
|
+
this.collectExprRefs(arm.pattern, scope);
|
|
8239
|
+
}
|
|
8240
|
+
this.collectStmtRefs(arm.body, scope);
|
|
8241
|
+
}
|
|
8242
|
+
break;
|
|
8243
|
+
case "as_block":
|
|
8244
|
+
case "at_block":
|
|
8245
|
+
case "as_at":
|
|
8246
|
+
case "execute":
|
|
8247
|
+
this.collectNestedStmtRefs(stmt, scope);
|
|
8248
|
+
break;
|
|
8249
|
+
case "raw":
|
|
8250
|
+
case "break":
|
|
8251
|
+
case "continue":
|
|
8252
|
+
break;
|
|
7766
8253
|
}
|
|
7767
8254
|
}
|
|
7768
|
-
|
|
7769
|
-
|
|
7770
|
-
|
|
7771
|
-
|
|
7772
|
-
|
|
7773
|
-
|
|
7774
|
-
|
|
7775
|
-
|
|
7776
|
-
|
|
7777
|
-
|
|
7778
|
-
for (const fn of module3.functions) {
|
|
7779
|
-
const eventTrigger = fn.eventTrigger;
|
|
7780
|
-
if (!eventTrigger) {
|
|
7781
|
-
continue;
|
|
8255
|
+
collectNestedStmtRefs(stmt, scope) {
|
|
8256
|
+
if (stmt.kind === "execute") {
|
|
8257
|
+
for (const sub of stmt.subcommands) {
|
|
8258
|
+
if ("varName" in sub && sub.varName) {
|
|
8259
|
+
const resolved = this.resolveLocal(sub.varName, scope);
|
|
8260
|
+
if (resolved) {
|
|
8261
|
+
this.localReads.add(resolved.id);
|
|
8262
|
+
}
|
|
8263
|
+
}
|
|
8264
|
+
}
|
|
7782
8265
|
}
|
|
7783
|
-
|
|
7784
|
-
|
|
7785
|
-
|
|
7786
|
-
|
|
7787
|
-
|
|
7788
|
-
|
|
7789
|
-
|
|
7790
|
-
|
|
8266
|
+
this.collectStmtRefs(stmt.body, scope);
|
|
8267
|
+
}
|
|
8268
|
+
collectExprRefs(expr, scope) {
|
|
8269
|
+
switch (expr.kind) {
|
|
8270
|
+
case "ident": {
|
|
8271
|
+
const resolved = this.resolveLocal(expr.name, scope);
|
|
8272
|
+
if (resolved) {
|
|
8273
|
+
this.localReads.add(resolved.id);
|
|
8274
|
+
} else {
|
|
8275
|
+
this.usedConstants.add(expr.name);
|
|
8276
|
+
}
|
|
8277
|
+
break;
|
|
8278
|
+
}
|
|
8279
|
+
case "call":
|
|
8280
|
+
{
|
|
8281
|
+
const resolved = this.resolveLocal(expr.fn, scope);
|
|
8282
|
+
if (resolved) {
|
|
8283
|
+
this.localReads.add(resolved.id);
|
|
8284
|
+
} else if (this.functionMap.has(expr.fn)) {
|
|
8285
|
+
this.markReachable(expr.fn);
|
|
7791
8286
|
}
|
|
7792
|
-
}
|
|
8287
|
+
}
|
|
8288
|
+
for (const arg of expr.args) {
|
|
8289
|
+
this.collectExprRefs(arg, scope);
|
|
8290
|
+
}
|
|
7793
8291
|
break;
|
|
7794
|
-
case "
|
|
7795
|
-
|
|
7796
|
-
|
|
7797
|
-
|
|
7798
|
-
|
|
7799
|
-
|
|
7800
|
-
|
|
7801
|
-
|
|
7802
|
-
|
|
7803
|
-
|
|
7804
|
-
|
|
7805
|
-
|
|
8292
|
+
case "static_call":
|
|
8293
|
+
for (const arg of expr.args) {
|
|
8294
|
+
this.collectExprRefs(arg, scope);
|
|
8295
|
+
}
|
|
8296
|
+
break;
|
|
8297
|
+
case "invoke":
|
|
8298
|
+
this.collectExprRefs(expr.callee, scope);
|
|
8299
|
+
for (const arg of expr.args) {
|
|
8300
|
+
this.collectExprRefs(arg, scope);
|
|
8301
|
+
}
|
|
8302
|
+
break;
|
|
8303
|
+
case "member":
|
|
8304
|
+
this.collectExprRefs(expr.obj, scope);
|
|
8305
|
+
break;
|
|
8306
|
+
case "member_assign":
|
|
8307
|
+
this.collectExprRefs(expr.obj, scope);
|
|
8308
|
+
this.collectExprRefs(expr.value, scope);
|
|
8309
|
+
break;
|
|
8310
|
+
case "index":
|
|
8311
|
+
this.collectExprRefs(expr.obj, scope);
|
|
8312
|
+
this.collectExprRefs(expr.index, scope);
|
|
8313
|
+
break;
|
|
8314
|
+
case "array_lit":
|
|
8315
|
+
expr.elements.forEach((element) => this.collectExprRefs(element, scope));
|
|
8316
|
+
break;
|
|
8317
|
+
case "struct_lit":
|
|
8318
|
+
expr.fields.forEach((field) => this.collectExprRefs(field.value, scope));
|
|
8319
|
+
break;
|
|
8320
|
+
case "binary":
|
|
8321
|
+
this.collectExprRefs(expr.left, scope);
|
|
8322
|
+
this.collectExprRefs(expr.right, scope);
|
|
8323
|
+
break;
|
|
8324
|
+
case "is_check":
|
|
8325
|
+
this.collectExprRefs(expr.expr, scope);
|
|
8326
|
+
break;
|
|
8327
|
+
case "unary":
|
|
8328
|
+
this.collectExprRefs(expr.operand, scope);
|
|
8329
|
+
break;
|
|
8330
|
+
case "assign": {
|
|
8331
|
+
this.collectExprRefs(expr.value, scope);
|
|
8332
|
+
break;
|
|
8333
|
+
}
|
|
8334
|
+
case "str_interp":
|
|
8335
|
+
expr.parts.forEach((part) => {
|
|
8336
|
+
if (typeof part !== "string") {
|
|
8337
|
+
this.collectExprRefs(part, scope);
|
|
7806
8338
|
}
|
|
7807
|
-
};
|
|
8339
|
+
});
|
|
7808
8340
|
break;
|
|
7809
|
-
case "
|
|
7810
|
-
|
|
7811
|
-
|
|
7812
|
-
|
|
7813
|
-
trigger: "minecraft:entity_killed_player"
|
|
8341
|
+
case "f_string":
|
|
8342
|
+
expr.parts.forEach((part) => {
|
|
8343
|
+
if (part.kind === "expr") {
|
|
8344
|
+
this.collectExprRefs(part.expr, scope);
|
|
7814
8345
|
}
|
|
7815
|
-
};
|
|
8346
|
+
});
|
|
7816
8347
|
break;
|
|
7817
|
-
case "
|
|
7818
|
-
|
|
7819
|
-
|
|
7820
|
-
|
|
7821
|
-
|
|
7822
|
-
|
|
7823
|
-
|
|
7824
|
-
|
|
7825
|
-
|
|
7826
|
-
function: `${ns}:${fn.name}`
|
|
8348
|
+
case "lambda": {
|
|
8349
|
+
const lambdaScope = [
|
|
8350
|
+
...scope.map((entries) => [...entries]),
|
|
8351
|
+
expr.params.map((param) => ({ id: `lambda:${param.name}:${expr.span?.line ?? 0}:${expr.span?.col ?? 0}`, name: param.name }))
|
|
8352
|
+
];
|
|
8353
|
+
if (Array.isArray(expr.body)) {
|
|
8354
|
+
this.collectStmtRefs(expr.body, lambdaScope);
|
|
8355
|
+
} else {
|
|
8356
|
+
this.collectExprRefs(expr.body, lambdaScope);
|
|
7827
8357
|
}
|
|
7828
|
-
|
|
7829
|
-
|
|
8358
|
+
break;
|
|
8359
|
+
}
|
|
8360
|
+
case "blockpos":
|
|
8361
|
+
case "bool_lit":
|
|
8362
|
+
case "byte_lit":
|
|
8363
|
+
case "double_lit":
|
|
8364
|
+
case "float_lit":
|
|
8365
|
+
case "int_lit":
|
|
8366
|
+
case "long_lit":
|
|
8367
|
+
case "mc_name":
|
|
8368
|
+
case "range_lit":
|
|
8369
|
+
case "selector":
|
|
8370
|
+
case "short_lit":
|
|
8371
|
+
case "str_lit":
|
|
8372
|
+
break;
|
|
8373
|
+
}
|
|
7830
8374
|
}
|
|
7831
|
-
|
|
7832
|
-
|
|
7833
|
-
|
|
8375
|
+
resolveLocal(name, scope) {
|
|
8376
|
+
for (let i = scope.length - 1; i >= 0; i--) {
|
|
8377
|
+
for (let j = scope[i].length - 1; j >= 0; j--) {
|
|
8378
|
+
if (scope[i][j].name === name) {
|
|
8379
|
+
return scope[i][j];
|
|
8380
|
+
}
|
|
8381
|
+
}
|
|
8382
|
+
}
|
|
8383
|
+
return null;
|
|
7834
8384
|
}
|
|
7835
|
-
|
|
7836
|
-
|
|
7837
|
-
|
|
7838
|
-
|
|
7839
|
-
function generateDatapack(module3) {
|
|
7840
|
-
const generated = generateDatapackWithStats(module3);
|
|
7841
|
-
return [...generated.files, ...generated.advancements];
|
|
7842
|
-
}
|
|
7843
|
-
}
|
|
7844
|
-
});
|
|
7845
|
-
|
|
7846
|
-
// ../../dist/compile.js
|
|
7847
|
-
var require_compile = __commonJS({
|
|
7848
|
-
"../../dist/compile.js"(exports2) {
|
|
7849
|
-
"use strict";
|
|
7850
|
-
var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
7851
|
-
if (k2 === void 0) k2 = k;
|
|
7852
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
7853
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7854
|
-
desc = { enumerable: true, get: function() {
|
|
7855
|
-
return m[k];
|
|
7856
|
-
} };
|
|
8385
|
+
transformFunction(fn) {
|
|
8386
|
+
const scope = [fn.params.map((param) => ({ id: `param:${fn.name}:${param.name}`, name: param.name }))];
|
|
8387
|
+
const body = this.transformBlock(fn.body, scope);
|
|
8388
|
+
return body === fn.body ? fn : copySpan({ ...fn, body }, fn);
|
|
7857
8389
|
}
|
|
7858
|
-
|
|
7859
|
-
|
|
7860
|
-
|
|
7861
|
-
|
|
7862
|
-
|
|
7863
|
-
|
|
7864
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
7865
|
-
}) : function(o, v) {
|
|
7866
|
-
o["default"] = v;
|
|
7867
|
-
});
|
|
7868
|
-
var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
|
|
7869
|
-
var ownKeys = function(o) {
|
|
7870
|
-
ownKeys = Object.getOwnPropertyNames || function(o2) {
|
|
7871
|
-
var ar = [];
|
|
7872
|
-
for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
|
|
7873
|
-
return ar;
|
|
7874
|
-
};
|
|
7875
|
-
return ownKeys(o);
|
|
7876
|
-
};
|
|
7877
|
-
return function(mod) {
|
|
7878
|
-
if (mod && mod.__esModule) return mod;
|
|
7879
|
-
var result = {};
|
|
7880
|
-
if (mod != null) {
|
|
7881
|
-
for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
8390
|
+
transformBlock(block, scope) {
|
|
8391
|
+
scope.push([]);
|
|
8392
|
+
const transformed = [];
|
|
8393
|
+
for (const stmt of block) {
|
|
8394
|
+
const next = this.transformStmt(stmt, scope);
|
|
8395
|
+
transformed.push(...next);
|
|
7882
8396
|
}
|
|
7883
|
-
|
|
7884
|
-
return
|
|
7885
|
-
};
|
|
7886
|
-
})();
|
|
7887
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
7888
|
-
exports2.preprocessSourceWithMetadata = preprocessSourceWithMetadata;
|
|
7889
|
-
exports2.preprocessSource = preprocessSource;
|
|
7890
|
-
exports2.compile = compile;
|
|
7891
|
-
exports2.formatCompileError = formatCompileError;
|
|
7892
|
-
var fs2 = __importStar(require("fs"));
|
|
7893
|
-
var path2 = __importStar(require("path"));
|
|
7894
|
-
var lexer_1 = require_lexer();
|
|
7895
|
-
var parser_1 = require_parser();
|
|
7896
|
-
var lowering_1 = require_lowering();
|
|
7897
|
-
var passes_1 = require_passes();
|
|
7898
|
-
var dce_1 = require_dce();
|
|
7899
|
-
var mcfunction_1 = require_mcfunction();
|
|
7900
|
-
var diagnostics_1 = require_diagnostics();
|
|
7901
|
-
var IMPORT_RE = /^\s*import\s+"([^"]+)"\s*;?\s*$/;
|
|
7902
|
-
function countLines(source) {
|
|
7903
|
-
return source === "" ? 0 : source.split("\n").length;
|
|
7904
|
-
}
|
|
7905
|
-
function offsetRanges(ranges, lineOffset) {
|
|
7906
|
-
return ranges.map((range) => ({
|
|
7907
|
-
startLine: range.startLine + lineOffset,
|
|
7908
|
-
endLine: range.endLine + lineOffset,
|
|
7909
|
-
filePath: range.filePath
|
|
7910
|
-
}));
|
|
7911
|
-
}
|
|
7912
|
-
function preprocessSourceWithMetadata(source, options = {}) {
|
|
7913
|
-
const { filePath } = options;
|
|
7914
|
-
const seen = options.seen ?? /* @__PURE__ */ new Set();
|
|
7915
|
-
if (filePath) {
|
|
7916
|
-
seen.add(path2.resolve(filePath));
|
|
8397
|
+
scope.pop();
|
|
8398
|
+
return transformed;
|
|
7917
8399
|
}
|
|
7918
|
-
|
|
7919
|
-
|
|
7920
|
-
|
|
7921
|
-
|
|
7922
|
-
|
|
7923
|
-
|
|
7924
|
-
|
|
7925
|
-
|
|
7926
|
-
|
|
7927
|
-
|
|
7928
|
-
|
|
8400
|
+
transformStmt(stmt, scope) {
|
|
8401
|
+
switch (stmt.kind) {
|
|
8402
|
+
case "let": {
|
|
8403
|
+
const init = this.transformExpr(stmt.init, scope);
|
|
8404
|
+
const id = this.localDeclIds.get(stmt) ?? `local:${stmt.name}:${stmt.span?.line ?? 0}:${stmt.span?.col ?? 0}`;
|
|
8405
|
+
scope[scope.length - 1].push({ id, name: stmt.name });
|
|
8406
|
+
if (this.localReads.has(id)) {
|
|
8407
|
+
if (init === stmt.init) {
|
|
8408
|
+
return [stmt];
|
|
8409
|
+
}
|
|
8410
|
+
return [copySpan({ ...stmt, init }, stmt)];
|
|
8411
|
+
}
|
|
8412
|
+
this.warnings.push({
|
|
8413
|
+
message: `Unused variable '${stmt.name}'`,
|
|
8414
|
+
code: "W_UNUSED_VAR",
|
|
8415
|
+
line: stmt.span?.line,
|
|
8416
|
+
col: stmt.span?.col
|
|
8417
|
+
});
|
|
8418
|
+
if (isPureExpr(init)) {
|
|
8419
|
+
return [];
|
|
8420
|
+
}
|
|
8421
|
+
return [copySpan({ kind: "expr", expr: init }, stmt)];
|
|
7929
8422
|
}
|
|
7930
|
-
|
|
7931
|
-
|
|
7932
|
-
|
|
7933
|
-
|
|
7934
|
-
|
|
7935
|
-
|
|
7936
|
-
|
|
7937
|
-
|
|
8423
|
+
case "expr": {
|
|
8424
|
+
const expr = this.transformExpr(stmt.expr, scope);
|
|
8425
|
+
if (expr.kind === "assign") {
|
|
8426
|
+
const resolved = this.resolveLocal(expr.target, scope);
|
|
8427
|
+
if (resolved && !this.localReads.has(resolved.id)) {
|
|
8428
|
+
if (isPureExpr(expr.value)) {
|
|
8429
|
+
return [];
|
|
8430
|
+
}
|
|
8431
|
+
return [copySpan({ kind: "expr", expr: expr.value }, stmt)];
|
|
8432
|
+
}
|
|
8433
|
+
}
|
|
8434
|
+
if (expr === stmt.expr) {
|
|
8435
|
+
return [stmt];
|
|
7938
8436
|
}
|
|
7939
|
-
|
|
8437
|
+
return [copySpan({ ...stmt, expr }, stmt)];
|
|
7940
8438
|
}
|
|
7941
|
-
|
|
7942
|
-
|
|
7943
|
-
|
|
7944
|
-
|
|
7945
|
-
|
|
8439
|
+
case "return": {
|
|
8440
|
+
if (!stmt.value) {
|
|
8441
|
+
return [stmt];
|
|
8442
|
+
}
|
|
8443
|
+
const value = this.transformExpr(stmt.value, scope);
|
|
8444
|
+
if (value === stmt.value) {
|
|
8445
|
+
return [stmt];
|
|
8446
|
+
}
|
|
8447
|
+
return [copySpan({ ...stmt, value }, stmt)];
|
|
8448
|
+
}
|
|
8449
|
+
case "if": {
|
|
8450
|
+
const cond = this.transformExpr(stmt.cond, scope);
|
|
8451
|
+
const constant = isConstantBoolean(cond);
|
|
8452
|
+
if (constant === true) {
|
|
8453
|
+
return this.transformBlock(stmt.then, scope);
|
|
8454
|
+
}
|
|
8455
|
+
if (constant === false) {
|
|
8456
|
+
return stmt.else_ ? this.transformBlock(stmt.else_, scope) : [];
|
|
8457
|
+
}
|
|
8458
|
+
const thenBlock = this.transformBlock(stmt.then, scope);
|
|
8459
|
+
const elseBlock = stmt.else_ ? this.transformBlock(stmt.else_, scope) : void 0;
|
|
8460
|
+
if (cond === stmt.cond && thenBlock === stmt.then && elseBlock === stmt.else_) {
|
|
8461
|
+
return [stmt];
|
|
8462
|
+
}
|
|
8463
|
+
return [copySpan({ ...stmt, cond, then: thenBlock, else_: elseBlock }, stmt)];
|
|
8464
|
+
}
|
|
8465
|
+
case "while": {
|
|
8466
|
+
const cond = this.transformExpr(stmt.cond, scope);
|
|
8467
|
+
if (isConstantBoolean(cond) === false) {
|
|
8468
|
+
return [];
|
|
8469
|
+
}
|
|
8470
|
+
const body = this.transformBlock(stmt.body, scope);
|
|
8471
|
+
return [copySpan({ ...stmt, cond, body }, stmt)];
|
|
8472
|
+
}
|
|
8473
|
+
case "for": {
|
|
8474
|
+
const forScope = [...scope, []];
|
|
8475
|
+
const init = stmt.init ? this.transformStmt(stmt.init, forScope)[0] : void 0;
|
|
8476
|
+
const cond = this.transformExpr(stmt.cond, forScope);
|
|
8477
|
+
if (isConstantBoolean(cond) === false) {
|
|
8478
|
+
return init ? [init] : [];
|
|
8479
|
+
}
|
|
8480
|
+
const step = this.transformExpr(stmt.step, forScope);
|
|
8481
|
+
const body = this.transformBlock(stmt.body, forScope);
|
|
8482
|
+
return [copySpan({ ...stmt, init, cond, step, body }, stmt)];
|
|
8483
|
+
}
|
|
8484
|
+
case "foreach": {
|
|
8485
|
+
const iterable = this.transformExpr(stmt.iterable, scope);
|
|
8486
|
+
const foreachScope = [...scope, [{ id: `foreach:${stmt.binding}:${stmt.span?.line ?? 0}:${stmt.span?.col ?? 0}`, name: stmt.binding }]];
|
|
8487
|
+
const body = this.transformBlock(stmt.body, foreachScope);
|
|
8488
|
+
return [copySpan({ ...stmt, iterable, body }, stmt)];
|
|
8489
|
+
}
|
|
8490
|
+
case "for_range": {
|
|
8491
|
+
const start = this.transformExpr(stmt.start, scope);
|
|
8492
|
+
const end = this.transformExpr(stmt.end, scope);
|
|
8493
|
+
const rangeScope = [...scope, [{ id: `range:${stmt.varName}:${stmt.span?.line ?? 0}:${stmt.span?.col ?? 0}`, name: stmt.varName }]];
|
|
8494
|
+
const body = this.transformBlock(stmt.body, rangeScope);
|
|
8495
|
+
return [copySpan({ ...stmt, start, end, body }, stmt)];
|
|
8496
|
+
}
|
|
8497
|
+
case "match": {
|
|
8498
|
+
const expr = this.transformExpr(stmt.expr, scope);
|
|
8499
|
+
const arms = stmt.arms.map((arm) => ({
|
|
8500
|
+
pattern: arm.pattern ? this.transformExpr(arm.pattern, scope) : null,
|
|
8501
|
+
body: this.transformBlock(arm.body, scope)
|
|
8502
|
+
}));
|
|
8503
|
+
return [copySpan({ ...stmt, expr, arms }, stmt)];
|
|
8504
|
+
}
|
|
8505
|
+
case "as_block":
|
|
8506
|
+
return [copySpan({ ...stmt, body: this.transformBlock(stmt.body, scope) }, stmt)];
|
|
8507
|
+
case "at_block":
|
|
8508
|
+
return [copySpan({ ...stmt, body: this.transformBlock(stmt.body, scope) }, stmt)];
|
|
8509
|
+
case "as_at":
|
|
8510
|
+
return [copySpan({ ...stmt, body: this.transformBlock(stmt.body, scope) }, stmt)];
|
|
8511
|
+
case "execute":
|
|
8512
|
+
return [copySpan({ ...stmt, body: this.transformBlock(stmt.body, scope) }, stmt)];
|
|
8513
|
+
case "raw":
|
|
8514
|
+
return [stmt];
|
|
8515
|
+
case "break":
|
|
8516
|
+
return [stmt];
|
|
8517
|
+
case "continue":
|
|
8518
|
+
return [stmt];
|
|
7946
8519
|
}
|
|
7947
|
-
parsingHeader = false;
|
|
7948
|
-
bodyLines.push(line);
|
|
7949
|
-
}
|
|
7950
|
-
const body = bodyLines.join("\n");
|
|
7951
|
-
const parts = [...imports.map((entry) => entry.source), body].filter(Boolean);
|
|
7952
|
-
const combined = parts.join("\n");
|
|
7953
|
-
const ranges = [];
|
|
7954
|
-
let lineOffset = 0;
|
|
7955
|
-
for (const entry of imports) {
|
|
7956
|
-
ranges.push(...offsetRanges(entry.ranges, lineOffset));
|
|
7957
|
-
lineOffset += countLines(entry.source);
|
|
7958
|
-
}
|
|
7959
|
-
if (filePath && body) {
|
|
7960
|
-
ranges.push({
|
|
7961
|
-
startLine: lineOffset + 1,
|
|
7962
|
-
endLine: lineOffset + countLines(body),
|
|
7963
|
-
filePath: path2.resolve(filePath)
|
|
7964
|
-
});
|
|
7965
8520
|
}
|
|
7966
|
-
|
|
7967
|
-
|
|
7968
|
-
|
|
7969
|
-
|
|
7970
|
-
|
|
7971
|
-
|
|
7972
|
-
|
|
7973
|
-
|
|
7974
|
-
|
|
7975
|
-
|
|
7976
|
-
|
|
7977
|
-
|
|
7978
|
-
|
|
7979
|
-
|
|
7980
|
-
|
|
7981
|
-
|
|
7982
|
-
|
|
7983
|
-
|
|
7984
|
-
|
|
7985
|
-
|
|
7986
|
-
|
|
7987
|
-
|
|
7988
|
-
|
|
7989
|
-
|
|
7990
|
-
|
|
7991
|
-
|
|
7992
|
-
|
|
7993
|
-
|
|
7994
|
-
|
|
7995
|
-
|
|
7996
|
-
|
|
7997
|
-
|
|
7998
|
-
|
|
7999
|
-
|
|
8521
|
+
transformExpr(expr, scope) {
|
|
8522
|
+
switch (expr.kind) {
|
|
8523
|
+
case "call":
|
|
8524
|
+
return copySpan({ ...expr, args: expr.args.map((arg) => this.transformExpr(arg, scope)) }, expr);
|
|
8525
|
+
case "static_call":
|
|
8526
|
+
return copySpan({ ...expr, args: expr.args.map((arg) => this.transformExpr(arg, scope)) }, expr);
|
|
8527
|
+
case "invoke":
|
|
8528
|
+
return copySpan({
|
|
8529
|
+
...expr,
|
|
8530
|
+
callee: this.transformExpr(expr.callee, scope),
|
|
8531
|
+
args: expr.args.map((arg) => this.transformExpr(arg, scope))
|
|
8532
|
+
}, expr);
|
|
8533
|
+
case "binary":
|
|
8534
|
+
return copySpan({
|
|
8535
|
+
...expr,
|
|
8536
|
+
left: this.transformExpr(expr.left, scope),
|
|
8537
|
+
right: this.transformExpr(expr.right, scope)
|
|
8538
|
+
}, expr);
|
|
8539
|
+
case "is_check":
|
|
8540
|
+
return copySpan({ ...expr, expr: this.transformExpr(expr.expr, scope) }, expr);
|
|
8541
|
+
case "unary":
|
|
8542
|
+
return copySpan({ ...expr, operand: this.transformExpr(expr.operand, scope) }, expr);
|
|
8543
|
+
case "assign":
|
|
8544
|
+
return copySpan({ ...expr, value: this.transformExpr(expr.value, scope) }, expr);
|
|
8545
|
+
case "member":
|
|
8546
|
+
return copySpan({ ...expr, obj: this.transformExpr(expr.obj, scope) }, expr);
|
|
8547
|
+
case "member_assign":
|
|
8548
|
+
return copySpan({
|
|
8549
|
+
...expr,
|
|
8550
|
+
obj: this.transformExpr(expr.obj, scope),
|
|
8551
|
+
value: this.transformExpr(expr.value, scope)
|
|
8552
|
+
}, expr);
|
|
8553
|
+
case "index":
|
|
8554
|
+
return copySpan({
|
|
8555
|
+
...expr,
|
|
8556
|
+
obj: this.transformExpr(expr.obj, scope),
|
|
8557
|
+
index: this.transformExpr(expr.index, scope)
|
|
8558
|
+
}, expr);
|
|
8559
|
+
case "array_lit":
|
|
8560
|
+
return copySpan({ ...expr, elements: expr.elements.map((element) => this.transformExpr(element, scope)) }, expr);
|
|
8561
|
+
case "struct_lit":
|
|
8562
|
+
return copySpan({
|
|
8563
|
+
...expr,
|
|
8564
|
+
fields: expr.fields.map((field) => ({ ...field, value: this.transformExpr(field.value, scope) }))
|
|
8565
|
+
}, expr);
|
|
8566
|
+
case "str_interp":
|
|
8567
|
+
return copySpan({
|
|
8568
|
+
...expr,
|
|
8569
|
+
parts: expr.parts.map((part) => typeof part === "string" ? part : this.transformExpr(part, scope))
|
|
8570
|
+
}, expr);
|
|
8571
|
+
case "f_string":
|
|
8572
|
+
return copySpan({
|
|
8573
|
+
...expr,
|
|
8574
|
+
parts: expr.parts.map((part) => part.kind === "text" ? part : { kind: "expr", expr: this.transformExpr(part.expr, scope) })
|
|
8575
|
+
}, expr);
|
|
8576
|
+
case "lambda": {
|
|
8577
|
+
const lambdaScope = [
|
|
8578
|
+
...scope.map((entries) => [...entries]),
|
|
8579
|
+
expr.params.map((param) => ({ id: `lambda:${param.name}:${expr.span?.line ?? 0}:${expr.span?.col ?? 0}`, name: param.name }))
|
|
8580
|
+
];
|
|
8581
|
+
const body = Array.isArray(expr.body) ? this.transformBlock(expr.body, lambdaScope) : this.transformExpr(expr.body, lambdaScope);
|
|
8582
|
+
return copySpan({ ...expr, body }, expr);
|
|
8583
|
+
}
|
|
8584
|
+
case "blockpos":
|
|
8585
|
+
case "bool_lit":
|
|
8586
|
+
case "byte_lit":
|
|
8587
|
+
case "double_lit":
|
|
8588
|
+
case "float_lit":
|
|
8589
|
+
case "ident":
|
|
8590
|
+
case "int_lit":
|
|
8591
|
+
case "long_lit":
|
|
8592
|
+
case "mc_name":
|
|
8593
|
+
case "range_lit":
|
|
8594
|
+
case "rel_coord":
|
|
8595
|
+
case "local_coord":
|
|
8596
|
+
case "selector":
|
|
8597
|
+
case "short_lit":
|
|
8598
|
+
case "str_lit":
|
|
8599
|
+
return expr;
|
|
8000
8600
|
}
|
|
8001
|
-
return {
|
|
8002
|
-
success: false,
|
|
8003
|
-
error: new diagnostics_1.DiagnosticError("ParseError", String(err), { file: filePath, line: 1, col: 1 }, sourceLines)
|
|
8004
|
-
};
|
|
8005
|
-
}
|
|
8006
|
-
}
|
|
8007
|
-
function formatCompileError(result) {
|
|
8008
|
-
if (result.success) {
|
|
8009
|
-
return "Compilation successful";
|
|
8010
8601
|
}
|
|
8011
|
-
|
|
8012
|
-
|
|
8602
|
+
};
|
|
8603
|
+
exports2.DeadCodeEliminator = DeadCodeEliminator;
|
|
8604
|
+
function eliminateDeadCode(program, sourceRanges) {
|
|
8605
|
+
const eliminator = new DeadCodeEliminator();
|
|
8606
|
+
const result = eliminator.eliminate(program);
|
|
8607
|
+
let warnings = eliminator.warnings;
|
|
8608
|
+
if (sourceRanges && sourceRanges.length > 0) {
|
|
8609
|
+
const { resolveSourceLine } = require_compile();
|
|
8610
|
+
warnings = warnings.map((w) => {
|
|
8611
|
+
if (w.line == null)
|
|
8612
|
+
return w;
|
|
8613
|
+
const resolved = resolveSourceLine(w.line, sourceRanges);
|
|
8614
|
+
return { ...w, line: resolved.line, filePath: resolved.filePath ?? w.filePath };
|
|
8615
|
+
});
|
|
8013
8616
|
}
|
|
8014
|
-
return
|
|
8617
|
+
return { program: result, warnings };
|
|
8015
8618
|
}
|
|
8016
8619
|
}
|
|
8017
8620
|
});
|
|
@@ -8366,22 +8969,42 @@ var require_dist = __commonJS({
|
|
|
8366
8969
|
const shouldOptimize = options.optimize ?? true;
|
|
8367
8970
|
const shouldTypeCheck = options.typeCheck ?? true;
|
|
8368
8971
|
const shouldRunDce = options.dce ?? shouldOptimize;
|
|
8972
|
+
const mangle = options.mangle ?? false;
|
|
8369
8973
|
const filePath = options.filePath;
|
|
8370
8974
|
const preprocessed = (0, compile_1.preprocessSourceWithMetadata)(source, { filePath });
|
|
8371
8975
|
const preprocessedSource = preprocessed.source;
|
|
8372
8976
|
const tokens = new lexer_1.Lexer(preprocessedSource, filePath).tokenize();
|
|
8373
8977
|
const parsedAst = new parser_1.Parser(tokens, preprocessedSource, filePath).parse(namespace);
|
|
8374
|
-
const
|
|
8978
|
+
const allLibrarySources = [];
|
|
8979
|
+
for (const li of preprocessed.libraryImports ?? []) {
|
|
8980
|
+
allLibrarySources.push({ src: li.source, fp: li.filePath });
|
|
8981
|
+
}
|
|
8982
|
+
for (const { src, fp } of allLibrarySources) {
|
|
8983
|
+
const libPreprocessed = (0, compile_1.preprocessSourceWithMetadata)(src, fp ? { filePath: fp } : {});
|
|
8984
|
+
const libTokens = new lexer_1.Lexer(libPreprocessed.source, fp).tokenize();
|
|
8985
|
+
const libAst = new parser_1.Parser(libTokens, libPreprocessed.source, fp).parse(namespace);
|
|
8986
|
+
for (const fn of libAst.declarations)
|
|
8987
|
+
fn.isLibraryFn = true;
|
|
8988
|
+
parsedAst.declarations.push(...libAst.declarations);
|
|
8989
|
+
parsedAst.structs.push(...libAst.structs);
|
|
8990
|
+
parsedAst.implBlocks.push(...libAst.implBlocks);
|
|
8991
|
+
parsedAst.enums.push(...libAst.enums);
|
|
8992
|
+
parsedAst.consts.push(...libAst.consts);
|
|
8993
|
+
parsedAst.globals.push(...libAst.globals);
|
|
8994
|
+
}
|
|
8995
|
+
const dceResult = shouldRunDce ? (0, dce_1.eliminateDeadCode)(parsedAst, preprocessed.ranges) : { program: parsedAst, warnings: [] };
|
|
8375
8996
|
const ast = dceResult.program;
|
|
8376
8997
|
let typeErrors;
|
|
8377
8998
|
if (shouldTypeCheck) {
|
|
8378
8999
|
const checker = new typechecker_1.TypeChecker(preprocessedSource, filePath);
|
|
8379
9000
|
typeErrors = checker.check(ast);
|
|
8380
9001
|
}
|
|
9002
|
+
const scoreboardObj = options.scoreboardObjective ?? `__${namespace}`;
|
|
9003
|
+
(0, lowering_1.setScoreboardObjective)(scoreboardObj);
|
|
8381
9004
|
const lowering = new lowering_1.Lowering(namespace, preprocessed.ranges);
|
|
8382
9005
|
const ir = lowering.lower(ast);
|
|
8383
9006
|
let optimizedIR = ir;
|
|
8384
|
-
let generated = (0, mcfunction_1.generateDatapackWithStats)(ir, { optimizeCommands: shouldOptimize });
|
|
9007
|
+
let generated = (0, mcfunction_1.generateDatapackWithStats)(ir, { optimizeCommands: shouldOptimize, mangle, scoreboardObjective: scoreboardObj });
|
|
8385
9008
|
let optimizationStats;
|
|
8386
9009
|
if (shouldOptimize) {
|
|
8387
9010
|
const stats = (0, commands_1.createEmptyOptimizationStats)();
|
|
@@ -8397,10 +9020,10 @@ var require_dist = __commonJS({
|
|
|
8397
9020
|
}
|
|
8398
9021
|
const copyPropagatedIR = { ...ir, functions: copyPropagatedFunctions };
|
|
8399
9022
|
optimizedIR = { ...ir, functions: deadCodeEliminatedFunctions };
|
|
8400
|
-
const baselineGenerated = (0, mcfunction_1.generateDatapackWithStats)(ir, { optimizeCommands: false });
|
|
8401
|
-
const beforeDceGenerated = (0, mcfunction_1.generateDatapackWithStats)(copyPropagatedIR, { optimizeCommands: false });
|
|
8402
|
-
const afterDceGenerated = (0, mcfunction_1.generateDatapackWithStats)(optimizedIR, { optimizeCommands: false });
|
|
8403
|
-
generated = (0, mcfunction_1.generateDatapackWithStats)(optimizedIR, { optimizeCommands: true });
|
|
9023
|
+
const baselineGenerated = (0, mcfunction_1.generateDatapackWithStats)(ir, { optimizeCommands: false, mangle, scoreboardObjective: scoreboardObj });
|
|
9024
|
+
const beforeDceGenerated = (0, mcfunction_1.generateDatapackWithStats)(copyPropagatedIR, { optimizeCommands: false, mangle, scoreboardObjective: scoreboardObj });
|
|
9025
|
+
const afterDceGenerated = (0, mcfunction_1.generateDatapackWithStats)(optimizedIR, { optimizeCommands: false, mangle, scoreboardObjective: scoreboardObj });
|
|
9026
|
+
generated = (0, mcfunction_1.generateDatapackWithStats)(optimizedIR, { optimizeCommands: true, mangle, scoreboardObjective: scoreboardObj });
|
|
8404
9027
|
stats.deadCodeRemoved = (0, mcfunction_1.countMcfunctionCommands)(beforeDceGenerated.files) - (0, mcfunction_1.countMcfunctionCommands)(afterDceGenerated.files);
|
|
8405
9028
|
stats.licmHoists = generated.stats.licmHoists;
|
|
8406
9029
|
stats.licmLoopBodies = generated.stats.licmLoopBodies;
|
|
@@ -8414,7 +9037,7 @@ var require_dist = __commonJS({
|
|
|
8414
9037
|
optimizationStats = stats;
|
|
8415
9038
|
} else {
|
|
8416
9039
|
optimizedIR = ir;
|
|
8417
|
-
generated = (0, mcfunction_1.generateDatapackWithStats)(ir, { optimizeCommands: false });
|
|
9040
|
+
generated = (0, mcfunction_1.generateDatapackWithStats)(ir, { optimizeCommands: false, mangle, scoreboardObjective: scoreboardObj });
|
|
8418
9041
|
}
|
|
8419
9042
|
return {
|
|
8420
9043
|
files: [...generated.files, ...generated.advancements],
|
|
@@ -8423,7 +9046,8 @@ var require_dist = __commonJS({
|
|
|
8423
9046
|
ir: optimizedIR,
|
|
8424
9047
|
typeErrors,
|
|
8425
9048
|
warnings: [...dceResult.warnings, ...lowering.warnings],
|
|
8426
|
-
stats: optimizationStats
|
|
9049
|
+
stats: optimizationStats,
|
|
9050
|
+
sourceMap: generated.sourceMap
|
|
8427
9051
|
};
|
|
8428
9052
|
}
|
|
8429
9053
|
function check(source, namespace = "redscript", filePath) {
|
|
@@ -9343,6 +9967,22 @@ function registerHoverProvider(context) {
|
|
|
9343
9967
|
vscode.languages.registerHoverProvider("redscript", {
|
|
9344
9968
|
provideHover(document, position) {
|
|
9345
9969
|
const line = document.lineAt(position.line).text;
|
|
9970
|
+
const rsRange = document.getWordRangeAtPosition(position, /#rs\b/);
|
|
9971
|
+
if (rsRange) {
|
|
9972
|
+
const md = new vscode.MarkdownString("", true);
|
|
9973
|
+
md.isTrusted = true;
|
|
9974
|
+
md.appendCodeblock("#rs", "redscript");
|
|
9975
|
+
md.appendMarkdown("**RS Internal Scoreboard Objective** *(compiler token)*\n\n");
|
|
9976
|
+
md.appendMarkdown("Resolves to the current datapack's internal scoreboard objective at compile time.\n\n");
|
|
9977
|
+
md.appendMarkdown("Default: `__<namespace>` (e.g. `__mygame` for namespace `mygame`).\n\n");
|
|
9978
|
+
md.appendMarkdown("Use `#rs` in `scoreboard_get` / `scoreboard_set` when you need to read or write\n");
|
|
9979
|
+
md.appendMarkdown("the compiler's own variable slots \u2014 such as in stdlib implementations.\n\n");
|
|
9980
|
+
md.appendMarkdown("> \u26A0\uFE0F Unlike other `#name` tokens, `#rs` does **not** compile to the literal string `rs`.\n");
|
|
9981
|
+
md.appendMarkdown("> It tracks the `--scoreboard` flag or the `__<namespace>` default.\n\n");
|
|
9982
|
+
md.appendMarkdown("**Example:**\n");
|
|
9983
|
+
md.appendCodeblock('scoreboard_set("timer_ticks", #rs, 0);\n// compiles to: scoreboard players set timer_ticks __mygame 0', "redscript");
|
|
9984
|
+
return new vscode.Hover(md, rsRange);
|
|
9985
|
+
}
|
|
9346
9986
|
const mcRange = document.getWordRangeAtPosition(position, /#[a-zA-Z_][a-zA-Z0-9_]*/);
|
|
9347
9987
|
if (mcRange) {
|
|
9348
9988
|
const raw = document.getText(mcRange);
|