redscript-mc 1.2.14 → 1.2.16
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/CHANGELOG.md +39 -0
- package/README.md +13 -6
- package/builtins.d.mcrs +559 -0
- package/dist/builtins/metadata.d.ts +36 -0
- package/dist/builtins/metadata.js +1022 -0
- package/dist/cli.js +16 -6
- package/dist/lowering/index.d.ts +11 -0
- package/dist/lowering/index.js +46 -25
- package/editors/vscode/builtins.d.mcrs +559 -0
- package/editors/vscode/out/extension.js +797 -80
- package/editors/vscode/src/symbols.ts +68 -0
- package/package.json +1 -1
- package/src/builtins/metadata.ts +1123 -0
- package/src/cli.ts +17 -6
- package/src/lowering/index.ts +50 -27
|
@@ -172,6 +172,8 @@ var require_lexer = __commonJS({
|
|
|
172
172
|
foreach: "foreach",
|
|
173
173
|
match: "match",
|
|
174
174
|
return: "return",
|
|
175
|
+
break: "break",
|
|
176
|
+
continue: "continue",
|
|
175
177
|
as: "as",
|
|
176
178
|
at: "at",
|
|
177
179
|
in: "in",
|
|
@@ -1042,6 +1044,16 @@ var require_parser = __commonJS({
|
|
|
1042
1044
|
if (this.check("return")) {
|
|
1043
1045
|
return this.parseReturnStmt();
|
|
1044
1046
|
}
|
|
1047
|
+
if (this.check("break")) {
|
|
1048
|
+
const token = this.advance();
|
|
1049
|
+
this.match(";");
|
|
1050
|
+
return this.withLoc({ kind: "break" }, token);
|
|
1051
|
+
}
|
|
1052
|
+
if (this.check("continue")) {
|
|
1053
|
+
const token = this.advance();
|
|
1054
|
+
this.match(";");
|
|
1055
|
+
return this.withLoc({ kind: "continue" }, token);
|
|
1056
|
+
}
|
|
1045
1057
|
if (this.check("if")) {
|
|
1046
1058
|
return this.parseIfStmt();
|
|
1047
1059
|
}
|
|
@@ -1164,8 +1176,8 @@ var require_parser = __commonJS({
|
|
|
1164
1176
|
const iterable = this.parseExpr();
|
|
1165
1177
|
this.expect(")");
|
|
1166
1178
|
let executeContext;
|
|
1167
|
-
const execIdentKeywords = ["positioned", "rotated", "facing", "anchored", "align"];
|
|
1168
|
-
if (this.check("at") || this.check("in") || this.check("ident") && execIdentKeywords.includes(this.peek().value)) {
|
|
1179
|
+
const execIdentKeywords = ["positioned", "rotated", "facing", "anchored", "align", "on", "summon"];
|
|
1180
|
+
if (this.check("as") || this.check("at") || this.check("in") || this.check("ident") && execIdentKeywords.includes(this.peek().value)) {
|
|
1169
1181
|
let context = "";
|
|
1170
1182
|
while (!this.check("{") && !this.check("eof")) {
|
|
1171
1183
|
context += this.advance().value + " ";
|
|
@@ -1224,29 +1236,152 @@ var require_parser = __commonJS({
|
|
|
1224
1236
|
} else if (this.match("at")) {
|
|
1225
1237
|
const selector = this.parseSelector();
|
|
1226
1238
|
subcommands.push({ kind: "at", selector });
|
|
1227
|
-
} else if (this.
|
|
1228
|
-
|
|
1239
|
+
} else if (this.checkIdent("positioned")) {
|
|
1240
|
+
this.advance();
|
|
1241
|
+
if (this.match("as")) {
|
|
1242
|
+
const selector = this.parseSelector();
|
|
1243
|
+
subcommands.push({ kind: "positioned_as", selector });
|
|
1244
|
+
} else {
|
|
1245
|
+
const x = this.parseCoordToken();
|
|
1246
|
+
const y = this.parseCoordToken();
|
|
1247
|
+
const z = this.parseCoordToken();
|
|
1248
|
+
subcommands.push({ kind: "positioned", x, y, z });
|
|
1249
|
+
}
|
|
1250
|
+
} else if (this.checkIdent("rotated")) {
|
|
1251
|
+
this.advance();
|
|
1252
|
+
if (this.match("as")) {
|
|
1253
|
+
const selector = this.parseSelector();
|
|
1254
|
+
subcommands.push({ kind: "rotated_as", selector });
|
|
1255
|
+
} else {
|
|
1256
|
+
const yaw = this.parseCoordToken();
|
|
1257
|
+
const pitch = this.parseCoordToken();
|
|
1258
|
+
subcommands.push({ kind: "rotated", yaw, pitch });
|
|
1259
|
+
}
|
|
1260
|
+
} else if (this.checkIdent("facing")) {
|
|
1261
|
+
this.advance();
|
|
1262
|
+
if (this.checkIdent("entity")) {
|
|
1229
1263
|
this.advance();
|
|
1264
|
+
const selector = this.parseSelector();
|
|
1265
|
+
const anchor = this.checkIdent("eyes") || this.checkIdent("feet") ? this.advance().value : "feet";
|
|
1266
|
+
subcommands.push({ kind: "facing_entity", selector, anchor });
|
|
1267
|
+
} else {
|
|
1268
|
+
const x = this.parseCoordToken();
|
|
1269
|
+
const y = this.parseCoordToken();
|
|
1270
|
+
const z = this.parseCoordToken();
|
|
1271
|
+
subcommands.push({ kind: "facing", x, y, z });
|
|
1230
1272
|
}
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1273
|
+
} else if (this.checkIdent("anchored")) {
|
|
1274
|
+
this.advance();
|
|
1275
|
+
const anchor = this.advance().value;
|
|
1276
|
+
subcommands.push({ kind: "anchored", anchor });
|
|
1277
|
+
} else if (this.checkIdent("align")) {
|
|
1278
|
+
this.advance();
|
|
1279
|
+
const axes = this.advance().value;
|
|
1280
|
+
subcommands.push({ kind: "align", axes });
|
|
1281
|
+
} else if (this.checkIdent("on")) {
|
|
1282
|
+
this.advance();
|
|
1283
|
+
const relation = this.advance().value;
|
|
1284
|
+
subcommands.push({ kind: "on", relation });
|
|
1285
|
+
} else if (this.checkIdent("summon")) {
|
|
1286
|
+
this.advance();
|
|
1287
|
+
const entity = this.advance().value;
|
|
1288
|
+
subcommands.push({ kind: "summon", entity });
|
|
1289
|
+
} else if (this.checkIdent("store")) {
|
|
1290
|
+
this.advance();
|
|
1291
|
+
const storeType = this.advance().value;
|
|
1292
|
+
if (this.checkIdent("score")) {
|
|
1235
1293
|
this.advance();
|
|
1294
|
+
const target = this.advance().value;
|
|
1295
|
+
const targetObj = this.advance().value;
|
|
1296
|
+
if (storeType === "result") {
|
|
1297
|
+
subcommands.push({ kind: "store_result", target, targetObj });
|
|
1298
|
+
} else {
|
|
1299
|
+
subcommands.push({ kind: "store_success", target, targetObj });
|
|
1300
|
+
}
|
|
1301
|
+
} else {
|
|
1302
|
+
this.error("store currently only supports score target");
|
|
1236
1303
|
}
|
|
1237
|
-
|
|
1238
|
-
|
|
1304
|
+
} else if (this.match("if")) {
|
|
1305
|
+
this.parseExecuteCondition(subcommands, "if");
|
|
1306
|
+
} else if (this.match("unless")) {
|
|
1307
|
+
this.parseExecuteCondition(subcommands, "unless");
|
|
1239
1308
|
} else if (this.match("in")) {
|
|
1240
|
-
|
|
1309
|
+
let dim = this.advance().value;
|
|
1310
|
+
if (this.match(":")) {
|
|
1311
|
+
dim += ":" + this.advance().value;
|
|
1312
|
+
}
|
|
1241
1313
|
subcommands.push({ kind: "in", dimension: dim });
|
|
1242
1314
|
} else {
|
|
1243
|
-
this.error(`Unexpected token in execute statement: ${this.peek().kind}`);
|
|
1315
|
+
this.error(`Unexpected token in execute statement: ${this.peek().kind} (${this.peek().value})`);
|
|
1244
1316
|
}
|
|
1245
1317
|
}
|
|
1246
1318
|
this.expect("run");
|
|
1247
1319
|
const body = this.parseBlock();
|
|
1248
1320
|
return this.withLoc({ kind: "execute", subcommands, body }, executeToken);
|
|
1249
1321
|
}
|
|
1322
|
+
parseExecuteCondition(subcommands, type) {
|
|
1323
|
+
if (this.checkIdent("entity") || this.check("selector")) {
|
|
1324
|
+
if (this.checkIdent("entity"))
|
|
1325
|
+
this.advance();
|
|
1326
|
+
const selectorOrVar = this.parseSelectorOrVarSelector();
|
|
1327
|
+
subcommands.push({ kind: type === "if" ? "if_entity" : "unless_entity", ...selectorOrVar });
|
|
1328
|
+
} else if (this.checkIdent("block")) {
|
|
1329
|
+
this.advance();
|
|
1330
|
+
const x = this.parseCoordToken();
|
|
1331
|
+
const y = this.parseCoordToken();
|
|
1332
|
+
const z = this.parseCoordToken();
|
|
1333
|
+
const block = this.parseBlockId();
|
|
1334
|
+
subcommands.push({ kind: type === "if" ? "if_block" : "unless_block", pos: [x, y, z], block });
|
|
1335
|
+
} else if (this.checkIdent("score")) {
|
|
1336
|
+
this.advance();
|
|
1337
|
+
const target = this.advance().value;
|
|
1338
|
+
const targetObj = this.advance().value;
|
|
1339
|
+
if (this.checkIdent("matches")) {
|
|
1340
|
+
this.advance();
|
|
1341
|
+
const range = this.advance().value;
|
|
1342
|
+
subcommands.push({ kind: type === "if" ? "if_score_range" : "unless_score_range", target, targetObj, range });
|
|
1343
|
+
} else {
|
|
1344
|
+
const op = this.advance().value;
|
|
1345
|
+
const source = this.advance().value;
|
|
1346
|
+
const sourceObj = this.advance().value;
|
|
1347
|
+
subcommands.push({
|
|
1348
|
+
kind: type === "if" ? "if_score" : "unless_score",
|
|
1349
|
+
target,
|
|
1350
|
+
targetObj,
|
|
1351
|
+
op,
|
|
1352
|
+
source,
|
|
1353
|
+
sourceObj
|
|
1354
|
+
});
|
|
1355
|
+
}
|
|
1356
|
+
} else {
|
|
1357
|
+
this.error(`Unknown condition type after ${type}`);
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1360
|
+
parseCoordToken() {
|
|
1361
|
+
const token = this.peek();
|
|
1362
|
+
if (token.kind === "rel_coord" || token.kind === "local_coord" || token.kind === "int_lit" || token.kind === "float_lit" || token.kind === "-" || token.kind === "ident") {
|
|
1363
|
+
return this.advance().value;
|
|
1364
|
+
}
|
|
1365
|
+
this.error(`Expected coordinate, got ${token.kind}`);
|
|
1366
|
+
return "~";
|
|
1367
|
+
}
|
|
1368
|
+
parseBlockId() {
|
|
1369
|
+
let id = this.advance().value;
|
|
1370
|
+
if (this.match(":")) {
|
|
1371
|
+
id += ":" + this.advance().value;
|
|
1372
|
+
}
|
|
1373
|
+
if (this.check("[")) {
|
|
1374
|
+
id += this.advance().value;
|
|
1375
|
+
while (!this.check("]") && !this.check("eof")) {
|
|
1376
|
+
id += this.advance().value;
|
|
1377
|
+
}
|
|
1378
|
+
id += this.advance().value;
|
|
1379
|
+
}
|
|
1380
|
+
return id;
|
|
1381
|
+
}
|
|
1382
|
+
checkIdent(value) {
|
|
1383
|
+
return this.check("ident") && this.peek().value === value;
|
|
1384
|
+
}
|
|
1250
1385
|
parseExprStmt() {
|
|
1251
1386
|
const expr = this.parseExpr();
|
|
1252
1387
|
this.expect(";");
|
|
@@ -3128,7 +3263,7 @@ var require_lowering = __commonJS({
|
|
|
3128
3263
|
exports2.Lowering = void 0;
|
|
3129
3264
|
var builder_1 = require_builder();
|
|
3130
3265
|
var diagnostics_1 = require_diagnostics();
|
|
3131
|
-
var
|
|
3266
|
+
var path2 = __importStar(require("path"));
|
|
3132
3267
|
var types_1 = require_types();
|
|
3133
3268
|
var BUILTINS2 = {
|
|
3134
3269
|
say: ([msg]) => `say ${msg}`,
|
|
@@ -3245,20 +3380,20 @@ var require_lowering = __commonJS({
|
|
|
3245
3380
|
var NAMESPACED_ENTITY_TYPE_RE = /^[a-z0-9_.-]+:[a-z0-9_./-]+$/;
|
|
3246
3381
|
var BARE_ENTITY_TYPE_RE = /^[a-z0-9_./-]+$/;
|
|
3247
3382
|
var ENTITY_TO_MC_TYPE = {
|
|
3248
|
-
Player: "player",
|
|
3249
|
-
Zombie: "zombie",
|
|
3250
|
-
Skeleton: "skeleton",
|
|
3251
|
-
Creeper: "creeper",
|
|
3252
|
-
Spider: "spider",
|
|
3253
|
-
Enderman: "enderman",
|
|
3254
|
-
Pig: "pig",
|
|
3255
|
-
Cow: "cow",
|
|
3256
|
-
Sheep: "sheep",
|
|
3257
|
-
Chicken: "chicken",
|
|
3258
|
-
Villager: "villager",
|
|
3259
|
-
ArmorStand: "armor_stand",
|
|
3260
|
-
Item: "item",
|
|
3261
|
-
Arrow: "arrow"
|
|
3383
|
+
Player: "minecraft:player",
|
|
3384
|
+
Zombie: "minecraft:zombie",
|
|
3385
|
+
Skeleton: "minecraft:skeleton",
|
|
3386
|
+
Creeper: "minecraft:creeper",
|
|
3387
|
+
Spider: "minecraft:spider",
|
|
3388
|
+
Enderman: "minecraft:enderman",
|
|
3389
|
+
Pig: "minecraft:pig",
|
|
3390
|
+
Cow: "minecraft:cow",
|
|
3391
|
+
Sheep: "minecraft:sheep",
|
|
3392
|
+
Chicken: "minecraft:chicken",
|
|
3393
|
+
Villager: "minecraft:villager",
|
|
3394
|
+
ArmorStand: "minecraft:armor_stand",
|
|
3395
|
+
Item: "minecraft:item",
|
|
3396
|
+
Arrow: "minecraft:arrow"
|
|
3262
3397
|
};
|
|
3263
3398
|
function normalizeSelector(selector, warnings) {
|
|
3264
3399
|
return selector.replace(/type=([^,\]]+)/g, (match, entityType) => {
|
|
@@ -3314,6 +3449,7 @@ var require_lowering = __commonJS({
|
|
|
3314
3449
|
this.currentContext = {};
|
|
3315
3450
|
this.blockPosVars = /* @__PURE__ */ new Map();
|
|
3316
3451
|
this.structDefs = /* @__PURE__ */ new Map();
|
|
3452
|
+
this.structDecls = /* @__PURE__ */ new Map();
|
|
3317
3453
|
this.enumDefs = /* @__PURE__ */ new Map();
|
|
3318
3454
|
this.functionDefaults = /* @__PURE__ */ new Map();
|
|
3319
3455
|
this.constValues = /* @__PURE__ */ new Map();
|
|
@@ -3321,18 +3457,185 @@ var require_lowering = __commonJS({
|
|
|
3321
3457
|
this.varTypes = /* @__PURE__ */ new Map();
|
|
3322
3458
|
this.floatVars = /* @__PURE__ */ new Set();
|
|
3323
3459
|
this.worldObjCounter = 0;
|
|
3460
|
+
this.loopStack = [];
|
|
3461
|
+
this.currentFnParamNames = /* @__PURE__ */ new Set();
|
|
3462
|
+
this.currentFnMacroParams = /* @__PURE__ */ new Set();
|
|
3463
|
+
this.macroFunctionInfo = /* @__PURE__ */ new Map();
|
|
3324
3464
|
this.namespace = namespace;
|
|
3325
3465
|
this.sourceRanges = sourceRanges;
|
|
3326
3466
|
LoweringBuilder.resetTempCounter();
|
|
3327
3467
|
}
|
|
3468
|
+
// ---------------------------------------------------------------------------
|
|
3469
|
+
// MC Macro pre-scan: identify which function params need macro treatment
|
|
3470
|
+
// ---------------------------------------------------------------------------
|
|
3471
|
+
preScanMacroFunctions(program) {
|
|
3472
|
+
for (const fn of program.declarations) {
|
|
3473
|
+
const paramNames = new Set(fn.params.map((p) => p.name));
|
|
3474
|
+
const macroParams = /* @__PURE__ */ new Set();
|
|
3475
|
+
this.preScanStmts(fn.body, paramNames, macroParams);
|
|
3476
|
+
if (macroParams.size > 0) {
|
|
3477
|
+
this.macroFunctionInfo.set(fn.name, [...macroParams]);
|
|
3478
|
+
}
|
|
3479
|
+
}
|
|
3480
|
+
for (const implBlock of program.implBlocks ?? []) {
|
|
3481
|
+
for (const method of implBlock.methods) {
|
|
3482
|
+
const paramNames = new Set(method.params.map((p) => p.name));
|
|
3483
|
+
const macroParams = /* @__PURE__ */ new Set();
|
|
3484
|
+
this.preScanStmts(method.body, paramNames, macroParams);
|
|
3485
|
+
if (macroParams.size > 0) {
|
|
3486
|
+
this.macroFunctionInfo.set(`${implBlock.typeName}_${method.name}`, [...macroParams]);
|
|
3487
|
+
}
|
|
3488
|
+
}
|
|
3489
|
+
}
|
|
3490
|
+
}
|
|
3491
|
+
preScanStmts(stmts, paramNames, macroParams) {
|
|
3492
|
+
for (const stmt of stmts) {
|
|
3493
|
+
this.preScanStmt(stmt, paramNames, macroParams);
|
|
3494
|
+
}
|
|
3495
|
+
}
|
|
3496
|
+
preScanStmt(stmt, paramNames, macroParams) {
|
|
3497
|
+
switch (stmt.kind) {
|
|
3498
|
+
case "expr":
|
|
3499
|
+
this.preScanExpr(stmt.expr, paramNames, macroParams);
|
|
3500
|
+
break;
|
|
3501
|
+
case "let":
|
|
3502
|
+
this.preScanExpr(stmt.init, paramNames, macroParams);
|
|
3503
|
+
break;
|
|
3504
|
+
case "return":
|
|
3505
|
+
if (stmt.value)
|
|
3506
|
+
this.preScanExpr(stmt.value, paramNames, macroParams);
|
|
3507
|
+
break;
|
|
3508
|
+
case "if":
|
|
3509
|
+
this.preScanExpr(stmt.cond, paramNames, macroParams);
|
|
3510
|
+
this.preScanStmts(stmt.then, paramNames, macroParams);
|
|
3511
|
+
if (stmt.else_)
|
|
3512
|
+
this.preScanStmts(stmt.else_, paramNames, macroParams);
|
|
3513
|
+
break;
|
|
3514
|
+
case "while":
|
|
3515
|
+
this.preScanExpr(stmt.cond, paramNames, macroParams);
|
|
3516
|
+
this.preScanStmts(stmt.body, paramNames, macroParams);
|
|
3517
|
+
break;
|
|
3518
|
+
case "for":
|
|
3519
|
+
if (stmt.init)
|
|
3520
|
+
this.preScanStmt(stmt.init, paramNames, macroParams);
|
|
3521
|
+
this.preScanExpr(stmt.cond, paramNames, macroParams);
|
|
3522
|
+
this.preScanStmts(stmt.body, paramNames, macroParams);
|
|
3523
|
+
break;
|
|
3524
|
+
case "for_range":
|
|
3525
|
+
this.preScanStmts(stmt.body, paramNames, macroParams);
|
|
3526
|
+
break;
|
|
3527
|
+
case "foreach":
|
|
3528
|
+
this.preScanStmts(stmt.body, paramNames, macroParams);
|
|
3529
|
+
break;
|
|
3530
|
+
case "match":
|
|
3531
|
+
this.preScanExpr(stmt.expr, paramNames, macroParams);
|
|
3532
|
+
for (const arm of stmt.arms) {
|
|
3533
|
+
this.preScanStmts(arm.body, paramNames, macroParams);
|
|
3534
|
+
}
|
|
3535
|
+
break;
|
|
3536
|
+
case "as_block":
|
|
3537
|
+
case "at_block":
|
|
3538
|
+
this.preScanStmts(stmt.body, paramNames, macroParams);
|
|
3539
|
+
break;
|
|
3540
|
+
case "execute":
|
|
3541
|
+
this.preScanStmts(stmt.body, paramNames, macroParams);
|
|
3542
|
+
break;
|
|
3543
|
+
}
|
|
3544
|
+
}
|
|
3545
|
+
preScanExpr(expr, paramNames, macroParams) {
|
|
3546
|
+
if (expr.kind === "call" && BUILTINS2[expr.fn] !== void 0) {
|
|
3547
|
+
for (const arg of expr.args) {
|
|
3548
|
+
if (arg.kind === "ident" && paramNames.has(arg.name)) {
|
|
3549
|
+
macroParams.add(arg.name);
|
|
3550
|
+
}
|
|
3551
|
+
}
|
|
3552
|
+
return;
|
|
3553
|
+
}
|
|
3554
|
+
if (expr.kind === "call") {
|
|
3555
|
+
for (const arg of expr.args)
|
|
3556
|
+
this.preScanExpr(arg, paramNames, macroParams);
|
|
3557
|
+
} else if (expr.kind === "binary") {
|
|
3558
|
+
this.preScanExpr(expr.left, paramNames, macroParams);
|
|
3559
|
+
this.preScanExpr(expr.right, paramNames, macroParams);
|
|
3560
|
+
} else if (expr.kind === "unary") {
|
|
3561
|
+
this.preScanExpr(expr.operand, paramNames, macroParams);
|
|
3562
|
+
} else if (expr.kind === "assign") {
|
|
3563
|
+
this.preScanExpr(expr.value, paramNames, macroParams);
|
|
3564
|
+
}
|
|
3565
|
+
}
|
|
3566
|
+
// ---------------------------------------------------------------------------
|
|
3567
|
+
// Macro helpers
|
|
3568
|
+
// ---------------------------------------------------------------------------
|
|
3569
|
+
/**
|
|
3570
|
+
* If `expr` is a function parameter that needs macro treatment (runtime value
|
|
3571
|
+
* used in a literal position), returns the param name; otherwise null.
|
|
3572
|
+
*/
|
|
3573
|
+
tryGetMacroParam(expr) {
|
|
3574
|
+
if (expr.kind !== "ident")
|
|
3575
|
+
return null;
|
|
3576
|
+
if (!this.currentFnParamNames.has(expr.name))
|
|
3577
|
+
return null;
|
|
3578
|
+
if (this.constValues.has(expr.name))
|
|
3579
|
+
return null;
|
|
3580
|
+
if (this.stringValues.has(expr.name))
|
|
3581
|
+
return null;
|
|
3582
|
+
return expr.name;
|
|
3583
|
+
}
|
|
3584
|
+
/**
|
|
3585
|
+
* Converts an expression to a string for use as a builtin arg.
|
|
3586
|
+
* If the expression is a macro param, returns `$(name)` and sets macroParam.
|
|
3587
|
+
*/
|
|
3588
|
+
exprToBuiltinArg(expr) {
|
|
3589
|
+
const macroParam = this.tryGetMacroParam(expr);
|
|
3590
|
+
if (macroParam) {
|
|
3591
|
+
return { str: `$(${macroParam})`, macroParam };
|
|
3592
|
+
}
|
|
3593
|
+
if (expr.kind === "struct_lit" || expr.kind === "array_lit") {
|
|
3594
|
+
return { str: this.exprToSnbt(expr) };
|
|
3595
|
+
}
|
|
3596
|
+
return { str: this.exprToString(expr) };
|
|
3597
|
+
}
|
|
3598
|
+
/**
|
|
3599
|
+
* Emits a call to a macro function, setting up both scoreboard params
|
|
3600
|
+
* (for arithmetic use) and NBT macro args (for coordinate/literal use).
|
|
3601
|
+
*/
|
|
3602
|
+
emitMacroFunctionCall(fnName, args, macroParamNames, fnDecl) {
|
|
3603
|
+
const params = fnDecl?.params ?? [];
|
|
3604
|
+
const loweredArgs = args.map((arg) => this.lowerExpr(arg));
|
|
3605
|
+
for (let i = 0; i < loweredArgs.length; i++) {
|
|
3606
|
+
const operand = loweredArgs[i];
|
|
3607
|
+
if (operand.kind === "const") {
|
|
3608
|
+
this.builder.emitRaw(`scoreboard players set $p${i} rs ${operand.value}`);
|
|
3609
|
+
} else if (operand.kind === "var") {
|
|
3610
|
+
this.builder.emitRaw(`scoreboard players operation $p${i} rs = ${operand.name} rs`);
|
|
3611
|
+
}
|
|
3612
|
+
}
|
|
3613
|
+
for (const macroParam of macroParamNames) {
|
|
3614
|
+
const paramIdx = params.findIndex((p) => p.name === macroParam);
|
|
3615
|
+
if (paramIdx < 0 || paramIdx >= loweredArgs.length)
|
|
3616
|
+
continue;
|
|
3617
|
+
const operand = loweredArgs[paramIdx];
|
|
3618
|
+
if (operand.kind === "const") {
|
|
3619
|
+
this.builder.emitRaw(`data modify storage rs:macro_args ${macroParam} set value ${operand.value}`);
|
|
3620
|
+
} else if (operand.kind === "var") {
|
|
3621
|
+
this.builder.emitRaw(`execute store result storage rs:macro_args ${macroParam} int 1 run scoreboard players get ${operand.name} rs`);
|
|
3622
|
+
}
|
|
3623
|
+
}
|
|
3624
|
+
this.builder.emitRaw(`function ${this.namespace}:${fnName} with storage rs:macro_args`);
|
|
3625
|
+
const dst = this.builder.freshTemp();
|
|
3626
|
+
this.builder.emitRaw(`scoreboard players operation ${dst} rs = $ret rs`);
|
|
3627
|
+
return { kind: "var", name: dst };
|
|
3628
|
+
}
|
|
3328
3629
|
lower(program) {
|
|
3329
3630
|
this.namespace = program.namespace;
|
|
3631
|
+
this.preScanMacroFunctions(program);
|
|
3330
3632
|
for (const struct of program.structs ?? []) {
|
|
3331
3633
|
const fields = /* @__PURE__ */ new Map();
|
|
3332
3634
|
for (const field of struct.fields) {
|
|
3333
3635
|
fields.set(field.name, field.type);
|
|
3334
3636
|
}
|
|
3335
3637
|
this.structDefs.set(struct.name, fields);
|
|
3638
|
+
this.structDecls.set(struct.name, struct);
|
|
3336
3639
|
}
|
|
3337
3640
|
for (const enumDecl of program.enums ?? []) {
|
|
3338
3641
|
const variants = /* @__PURE__ */ new Map();
|
|
@@ -3400,6 +3703,8 @@ var require_lowering = __commonJS({
|
|
|
3400
3703
|
this.blockPosVars = /* @__PURE__ */ new Map();
|
|
3401
3704
|
this.stringValues = /* @__PURE__ */ new Map();
|
|
3402
3705
|
this.builder = new LoweringBuilder();
|
|
3706
|
+
this.currentFnParamNames = new Set(runtimeParams.map((p) => p.name));
|
|
3707
|
+
this.currentFnMacroParams = /* @__PURE__ */ new Set();
|
|
3403
3708
|
if (staticEventDec) {
|
|
3404
3709
|
for (let i = 0; i < fn.params.length; i++) {
|
|
3405
3710
|
const param = fn.params[i];
|
|
@@ -3489,6 +3794,11 @@ var require_lowering = __commonJS({
|
|
|
3489
3794
|
if (tickRate && tickRate > 1) {
|
|
3490
3795
|
this.wrapWithTickRate(irFn, tickRate);
|
|
3491
3796
|
}
|
|
3797
|
+
if (this.currentFnMacroParams.size > 0) {
|
|
3798
|
+
irFn.isMacroFunction = true;
|
|
3799
|
+
irFn.macroParamNames = [...this.currentFnMacroParams];
|
|
3800
|
+
this.macroFunctionInfo.set(loweredName, irFn.macroParamNames);
|
|
3801
|
+
}
|
|
3492
3802
|
this.functions.push(irFn);
|
|
3493
3803
|
}
|
|
3494
3804
|
getTickRate(decorators) {
|
|
@@ -3549,6 +3859,12 @@ var require_lowering = __commonJS({
|
|
|
3549
3859
|
case "return":
|
|
3550
3860
|
this.lowerReturnStmt(stmt);
|
|
3551
3861
|
break;
|
|
3862
|
+
case "break":
|
|
3863
|
+
this.lowerBreakStmt();
|
|
3864
|
+
break;
|
|
3865
|
+
case "continue":
|
|
3866
|
+
this.lowerContinueStmt();
|
|
3867
|
+
break;
|
|
3552
3868
|
case "if":
|
|
3553
3869
|
this.lowerIfStmt(stmt);
|
|
3554
3870
|
break;
|
|
@@ -3580,6 +3896,7 @@ var require_lowering = __commonJS({
|
|
|
3580
3896
|
this.lowerExecuteStmt(stmt);
|
|
3581
3897
|
break;
|
|
3582
3898
|
case "raw":
|
|
3899
|
+
this.checkRawCommandInterpolation(stmt.cmd, stmt.span);
|
|
3583
3900
|
this.builder.emitRaw(stmt.cmd);
|
|
3584
3901
|
break;
|
|
3585
3902
|
}
|
|
@@ -3614,12 +3931,25 @@ var require_lowering = __commonJS({
|
|
|
3614
3931
|
if (stmt.init.kind === "struct_lit" && stmt.type?.kind === "struct") {
|
|
3615
3932
|
const structName = stmt.type.name.toLowerCase();
|
|
3616
3933
|
for (const field of stmt.init.fields) {
|
|
3617
|
-
const
|
|
3934
|
+
const path3 = `rs:heap ${structName}_${stmt.name}.${field.name}`;
|
|
3618
3935
|
const fieldValue = this.lowerExpr(field.value);
|
|
3619
3936
|
if (fieldValue.kind === "const") {
|
|
3620
|
-
this.builder.emitRaw(`data modify storage ${
|
|
3937
|
+
this.builder.emitRaw(`data modify storage ${path3} set value ${fieldValue.value}`);
|
|
3621
3938
|
} else if (fieldValue.kind === "var") {
|
|
3622
|
-
this.builder.emitRaw(`execute store result storage ${
|
|
3939
|
+
this.builder.emitRaw(`execute store result storage ${path3} int 1 run scoreboard players get ${fieldValue.name} rs`);
|
|
3940
|
+
}
|
|
3941
|
+
}
|
|
3942
|
+
return;
|
|
3943
|
+
}
|
|
3944
|
+
if ((stmt.init.kind === "call" || stmt.init.kind === "static_call") && stmt.type?.kind === "struct") {
|
|
3945
|
+
this.lowerExpr(stmt.init);
|
|
3946
|
+
const structDecl = this.structDecls.get(stmt.type.name);
|
|
3947
|
+
if (structDecl) {
|
|
3948
|
+
const structName = stmt.type.name.toLowerCase();
|
|
3949
|
+
for (const field of structDecl.fields) {
|
|
3950
|
+
const srcPath = `rs:heap __ret_struct.${field.name}`;
|
|
3951
|
+
const dstPath = `rs:heap ${structName}_${stmt.name}.${field.name}`;
|
|
3952
|
+
this.builder.emitRaw(`data modify storage ${dstPath} set from storage ${srcPath}`);
|
|
3623
3953
|
}
|
|
3624
3954
|
}
|
|
3625
3955
|
return;
|
|
@@ -3665,12 +3995,39 @@ var require_lowering = __commonJS({
|
|
|
3665
3995
|
}
|
|
3666
3996
|
lowerReturnStmt(stmt) {
|
|
3667
3997
|
if (stmt.value) {
|
|
3998
|
+
if (stmt.value.kind === "struct_lit") {
|
|
3999
|
+
for (const field of stmt.value.fields) {
|
|
4000
|
+
const path3 = `rs:heap __ret_struct.${field.name}`;
|
|
4001
|
+
const fieldValue = this.lowerExpr(field.value);
|
|
4002
|
+
if (fieldValue.kind === "const") {
|
|
4003
|
+
this.builder.emitRaw(`data modify storage ${path3} set value ${fieldValue.value}`);
|
|
4004
|
+
} else if (fieldValue.kind === "var") {
|
|
4005
|
+
this.builder.emitRaw(`execute store result storage ${path3} int 1 run scoreboard players get ${fieldValue.name} rs`);
|
|
4006
|
+
}
|
|
4007
|
+
}
|
|
4008
|
+
this.builder.emitReturn({ kind: "const", value: 0 });
|
|
4009
|
+
return;
|
|
4010
|
+
}
|
|
3668
4011
|
const value = this.lowerExpr(stmt.value);
|
|
3669
4012
|
this.builder.emitReturn(value);
|
|
3670
4013
|
} else {
|
|
3671
4014
|
this.builder.emitReturn();
|
|
3672
4015
|
}
|
|
3673
4016
|
}
|
|
4017
|
+
lowerBreakStmt() {
|
|
4018
|
+
if (this.loopStack.length === 0) {
|
|
4019
|
+
throw new diagnostics_1.DiagnosticError("LoweringError", "break statement outside of loop", { line: 1, col: 1 });
|
|
4020
|
+
}
|
|
4021
|
+
const loop = this.loopStack[this.loopStack.length - 1];
|
|
4022
|
+
this.builder.emitJump(loop.breakLabel);
|
|
4023
|
+
}
|
|
4024
|
+
lowerContinueStmt() {
|
|
4025
|
+
if (this.loopStack.length === 0) {
|
|
4026
|
+
throw new diagnostics_1.DiagnosticError("LoweringError", "continue statement outside of loop", { line: 1, col: 1 });
|
|
4027
|
+
}
|
|
4028
|
+
const loop = this.loopStack[this.loopStack.length - 1];
|
|
4029
|
+
this.builder.emitJump(loop.continueLabel);
|
|
4030
|
+
}
|
|
3674
4031
|
lowerIfStmt(stmt) {
|
|
3675
4032
|
if (stmt.cond.kind === "is_check") {
|
|
3676
4033
|
this.lowerIsCheckIfStmt(stmt);
|
|
@@ -3739,11 +4096,13 @@ var require_lowering = __commonJS({
|
|
|
3739
4096
|
const condVar = this.lowerExpr(stmt.cond);
|
|
3740
4097
|
const condName = this.operandToVar(condVar);
|
|
3741
4098
|
this.builder.emitJumpIf(condName, bodyLabel, exitLabel);
|
|
4099
|
+
this.loopStack.push({ breakLabel: exitLabel, continueLabel: checkLabel });
|
|
3742
4100
|
this.builder.startBlock(bodyLabel);
|
|
3743
4101
|
this.lowerBlock(stmt.body);
|
|
3744
4102
|
if (!this.builder.isBlockSealed()) {
|
|
3745
4103
|
this.builder.emitJump(checkLabel);
|
|
3746
4104
|
}
|
|
4105
|
+
this.loopStack.pop();
|
|
3747
4106
|
this.builder.startBlock(exitLabel);
|
|
3748
4107
|
}
|
|
3749
4108
|
lowerForStmt(stmt) {
|
|
@@ -3752,18 +4111,23 @@ var require_lowering = __commonJS({
|
|
|
3752
4111
|
}
|
|
3753
4112
|
const checkLabel = this.builder.freshLabel("for_check");
|
|
3754
4113
|
const bodyLabel = this.builder.freshLabel("for_body");
|
|
4114
|
+
const continueLabel = this.builder.freshLabel("for_continue");
|
|
3755
4115
|
const exitLabel = this.builder.freshLabel("for_exit");
|
|
3756
4116
|
this.builder.emitJump(checkLabel);
|
|
3757
4117
|
this.builder.startBlock(checkLabel);
|
|
3758
4118
|
const condVar = this.lowerExpr(stmt.cond);
|
|
3759
4119
|
const condName = this.operandToVar(condVar);
|
|
3760
4120
|
this.builder.emitJumpIf(condName, bodyLabel, exitLabel);
|
|
4121
|
+
this.loopStack.push({ breakLabel: exitLabel, continueLabel });
|
|
3761
4122
|
this.builder.startBlock(bodyLabel);
|
|
3762
4123
|
this.lowerBlock(stmt.body);
|
|
3763
|
-
this.lowerExpr(stmt.step);
|
|
3764
4124
|
if (!this.builder.isBlockSealed()) {
|
|
3765
|
-
this.builder.emitJump(
|
|
4125
|
+
this.builder.emitJump(continueLabel);
|
|
3766
4126
|
}
|
|
4127
|
+
this.builder.startBlock(continueLabel);
|
|
4128
|
+
this.lowerExpr(stmt.step);
|
|
4129
|
+
this.builder.emitJump(checkLabel);
|
|
4130
|
+
this.loopStack.pop();
|
|
3767
4131
|
this.builder.startBlock(exitLabel);
|
|
3768
4132
|
}
|
|
3769
4133
|
lowerForRangeStmt(stmt) {
|
|
@@ -3841,12 +4205,27 @@ var require_lowering = __commonJS({
|
|
|
3841
4205
|
defaultArm = arm;
|
|
3842
4206
|
continue;
|
|
3843
4207
|
}
|
|
3844
|
-
|
|
3845
|
-
if (
|
|
3846
|
-
|
|
4208
|
+
let matchCondition;
|
|
4209
|
+
if (arm.pattern.kind === "range_lit") {
|
|
4210
|
+
const range = arm.pattern.range;
|
|
4211
|
+
if (range.min !== void 0 && range.max !== void 0) {
|
|
4212
|
+
matchCondition = `${range.min}..${range.max}`;
|
|
4213
|
+
} else if (range.min !== void 0) {
|
|
4214
|
+
matchCondition = `${range.min}..`;
|
|
4215
|
+
} else if (range.max !== void 0) {
|
|
4216
|
+
matchCondition = `..${range.max}`;
|
|
4217
|
+
} else {
|
|
4218
|
+
matchCondition = "0..";
|
|
4219
|
+
}
|
|
4220
|
+
} else {
|
|
4221
|
+
const patternValue = this.lowerExpr(arm.pattern);
|
|
4222
|
+
if (patternValue.kind !== "const") {
|
|
4223
|
+
throw new Error("Match patterns must lower to compile-time constants");
|
|
4224
|
+
}
|
|
4225
|
+
matchCondition = String(patternValue.value);
|
|
3847
4226
|
}
|
|
3848
4227
|
const subFnName = `${this.currentFn}/match_${this.foreachCounter++}`;
|
|
3849
|
-
this.builder.emitRaw(`execute if score ${matchedVar} rs matches ..0 if score ${subject} rs matches ${
|
|
4228
|
+
this.builder.emitRaw(`execute if score ${matchedVar} rs matches ..0 if score ${subject} rs matches ${matchCondition} run function ${this.namespace}:${subFnName}`);
|
|
3850
4229
|
this.emitMatchArmSubFunction(subFnName, matchedVar, arm.body, true);
|
|
3851
4230
|
}
|
|
3852
4231
|
if (defaultArm) {
|
|
@@ -3994,12 +4373,47 @@ var require_lowering = __commonJS({
|
|
|
3994
4373
|
const parts = ["execute"];
|
|
3995
4374
|
for (const sub of stmt.subcommands) {
|
|
3996
4375
|
switch (sub.kind) {
|
|
4376
|
+
// Context modifiers
|
|
3997
4377
|
case "as":
|
|
3998
4378
|
parts.push(`as ${this.selectorToString(sub.selector)}`);
|
|
3999
4379
|
break;
|
|
4000
4380
|
case "at":
|
|
4001
4381
|
parts.push(`at ${this.selectorToString(sub.selector)}`);
|
|
4002
4382
|
break;
|
|
4383
|
+
case "positioned":
|
|
4384
|
+
parts.push(`positioned ${sub.x} ${sub.y} ${sub.z}`);
|
|
4385
|
+
break;
|
|
4386
|
+
case "positioned_as":
|
|
4387
|
+
parts.push(`positioned as ${this.selectorToString(sub.selector)}`);
|
|
4388
|
+
break;
|
|
4389
|
+
case "rotated":
|
|
4390
|
+
parts.push(`rotated ${sub.yaw} ${sub.pitch}`);
|
|
4391
|
+
break;
|
|
4392
|
+
case "rotated_as":
|
|
4393
|
+
parts.push(`rotated as ${this.selectorToString(sub.selector)}`);
|
|
4394
|
+
break;
|
|
4395
|
+
case "facing":
|
|
4396
|
+
parts.push(`facing ${sub.x} ${sub.y} ${sub.z}`);
|
|
4397
|
+
break;
|
|
4398
|
+
case "facing_entity":
|
|
4399
|
+
parts.push(`facing entity ${this.selectorToString(sub.selector)} ${sub.anchor}`);
|
|
4400
|
+
break;
|
|
4401
|
+
case "anchored":
|
|
4402
|
+
parts.push(`anchored ${sub.anchor}`);
|
|
4403
|
+
break;
|
|
4404
|
+
case "align":
|
|
4405
|
+
parts.push(`align ${sub.axes}`);
|
|
4406
|
+
break;
|
|
4407
|
+
case "in":
|
|
4408
|
+
parts.push(`in ${sub.dimension}`);
|
|
4409
|
+
break;
|
|
4410
|
+
case "on":
|
|
4411
|
+
parts.push(`on ${sub.relation}`);
|
|
4412
|
+
break;
|
|
4413
|
+
case "summon":
|
|
4414
|
+
parts.push(`summon ${sub.entity}`);
|
|
4415
|
+
break;
|
|
4416
|
+
// Conditions
|
|
4003
4417
|
case "if_entity":
|
|
4004
4418
|
if (sub.selector) {
|
|
4005
4419
|
parts.push(`if entity ${this.selectorToString(sub.selector)}`);
|
|
@@ -4016,8 +4430,30 @@ var require_lowering = __commonJS({
|
|
|
4016
4430
|
parts.push(`unless entity ${this.selectorToString(sel)}`);
|
|
4017
4431
|
}
|
|
4018
4432
|
break;
|
|
4019
|
-
case "
|
|
4020
|
-
parts.push(`
|
|
4433
|
+
case "if_block":
|
|
4434
|
+
parts.push(`if block ${sub.pos[0]} ${sub.pos[1]} ${sub.pos[2]} ${sub.block}`);
|
|
4435
|
+
break;
|
|
4436
|
+
case "unless_block":
|
|
4437
|
+
parts.push(`unless block ${sub.pos[0]} ${sub.pos[1]} ${sub.pos[2]} ${sub.block}`);
|
|
4438
|
+
break;
|
|
4439
|
+
case "if_score":
|
|
4440
|
+
parts.push(`if score ${sub.target} ${sub.targetObj} ${sub.op} ${sub.source} ${sub.sourceObj}`);
|
|
4441
|
+
break;
|
|
4442
|
+
case "unless_score":
|
|
4443
|
+
parts.push(`unless score ${sub.target} ${sub.targetObj} ${sub.op} ${sub.source} ${sub.sourceObj}`);
|
|
4444
|
+
break;
|
|
4445
|
+
case "if_score_range":
|
|
4446
|
+
parts.push(`if score ${sub.target} ${sub.targetObj} matches ${sub.range}`);
|
|
4447
|
+
break;
|
|
4448
|
+
case "unless_score_range":
|
|
4449
|
+
parts.push(`unless score ${sub.target} ${sub.targetObj} matches ${sub.range}`);
|
|
4450
|
+
break;
|
|
4451
|
+
// Store
|
|
4452
|
+
case "store_result":
|
|
4453
|
+
parts.push(`store result score ${sub.target} ${sub.targetObj}`);
|
|
4454
|
+
break;
|
|
4455
|
+
case "store_success":
|
|
4456
|
+
parts.push(`store success score ${sub.target} ${sub.targetObj}`);
|
|
4021
4457
|
break;
|
|
4022
4458
|
}
|
|
4023
4459
|
}
|
|
@@ -4136,9 +4572,9 @@ var require_lowering = __commonJS({
|
|
|
4136
4572
|
}
|
|
4137
4573
|
if (varType?.kind === "struct") {
|
|
4138
4574
|
const structName = varType.name.toLowerCase();
|
|
4139
|
-
const
|
|
4575
|
+
const path3 = `rs:heap ${structName}_${expr.obj.name}.${expr.field}`;
|
|
4140
4576
|
const dst = this.builder.freshTemp();
|
|
4141
|
-
this.builder.emitRaw(`execute store result score ${dst} rs run data get storage ${
|
|
4577
|
+
this.builder.emitRaw(`execute store result score ${dst} rs run data get storage ${path3}`);
|
|
4142
4578
|
return { kind: "var", name: dst };
|
|
4143
4579
|
}
|
|
4144
4580
|
if (varType?.kind === "array" && expr.field === "len") {
|
|
@@ -4176,20 +4612,20 @@ var require_lowering = __commonJS({
|
|
|
4176
4612
|
}
|
|
4177
4613
|
if (varType?.kind === "struct") {
|
|
4178
4614
|
const structName = varType.name.toLowerCase();
|
|
4179
|
-
const
|
|
4615
|
+
const path3 = `rs:heap ${structName}_${expr.obj.name}.${expr.field}`;
|
|
4180
4616
|
const value2 = this.lowerExpr(expr.value);
|
|
4181
4617
|
if (expr.op === "=") {
|
|
4182
4618
|
if (value2.kind === "const") {
|
|
4183
|
-
this.builder.emitRaw(`data modify storage ${
|
|
4619
|
+
this.builder.emitRaw(`data modify storage ${path3} set value ${value2.value}`);
|
|
4184
4620
|
} else if (value2.kind === "var") {
|
|
4185
|
-
this.builder.emitRaw(`execute store result storage ${
|
|
4621
|
+
this.builder.emitRaw(`execute store result storage ${path3} int 1 run scoreboard players get ${value2.name} rs`);
|
|
4186
4622
|
}
|
|
4187
4623
|
} else {
|
|
4188
4624
|
const dst = this.builder.freshTemp();
|
|
4189
|
-
this.builder.emitRaw(`execute store result score ${dst} rs run data get storage ${
|
|
4625
|
+
this.builder.emitRaw(`execute store result score ${dst} rs run data get storage ${path3}`);
|
|
4190
4626
|
const binOp = expr.op.slice(0, -1);
|
|
4191
4627
|
this.builder.emitBinop(dst, { kind: "var", name: dst }, binOp, value2);
|
|
4192
|
-
this.builder.emitRaw(`execute store result storage ${
|
|
4628
|
+
this.builder.emitRaw(`execute store result storage ${path3} int 1 run scoreboard players get ${dst} rs`);
|
|
4193
4629
|
}
|
|
4194
4630
|
return { kind: "const", value: 0 };
|
|
4195
4631
|
}
|
|
@@ -4384,6 +4820,21 @@ var require_lowering = __commonJS({
|
|
|
4384
4820
|
}
|
|
4385
4821
|
const implMethod = this.resolveInstanceMethod(expr);
|
|
4386
4822
|
if (implMethod) {
|
|
4823
|
+
const receiver = expr.args[0];
|
|
4824
|
+
if (receiver?.kind === "ident") {
|
|
4825
|
+
const receiverType = this.inferExprType(receiver);
|
|
4826
|
+
if (receiverType?.kind === "struct") {
|
|
4827
|
+
const structDecl = this.structDecls.get(receiverType.name);
|
|
4828
|
+
const structName = receiverType.name.toLowerCase();
|
|
4829
|
+
if (structDecl) {
|
|
4830
|
+
for (const field of structDecl.fields) {
|
|
4831
|
+
const srcPath = `rs:heap ${structName}_${receiver.name}.${field.name}`;
|
|
4832
|
+
const dstPath = `rs:heap ${structName}_self.${field.name}`;
|
|
4833
|
+
this.builder.emitRaw(`data modify storage ${dstPath} set from storage ${srcPath}`);
|
|
4834
|
+
}
|
|
4835
|
+
}
|
|
4836
|
+
}
|
|
4837
|
+
}
|
|
4387
4838
|
return this.emitMethodCall(implMethod.loweredName, implMethod.fn, expr.args);
|
|
4388
4839
|
}
|
|
4389
4840
|
const fnDecl = this.fnDecls.get(expr.fn);
|
|
@@ -4413,8 +4864,16 @@ var require_lowering = __commonJS({
|
|
|
4413
4864
|
}
|
|
4414
4865
|
const stdlibCallSite = this.getStdlibCallSiteContext(fnDecl, getSpan(expr));
|
|
4415
4866
|
const targetFn = callbackBindings.size > 0 || stdlibCallSite ? this.ensureSpecializedFunctionWithContext(fnDecl, callbackBindings, stdlibCallSite) : expr.fn;
|
|
4867
|
+
const macroParams = this.macroFunctionInfo.get(targetFn);
|
|
4868
|
+
if (macroParams && macroParams.length > 0) {
|
|
4869
|
+
return this.emitMacroFunctionCall(targetFn, runtimeArgs, macroParams, fnDecl);
|
|
4870
|
+
}
|
|
4416
4871
|
return this.emitDirectFunctionCall(targetFn, runtimeArgs);
|
|
4417
4872
|
}
|
|
4873
|
+
const macroParamsForUnknown = this.macroFunctionInfo.get(expr.fn);
|
|
4874
|
+
if (macroParamsForUnknown && macroParamsForUnknown.length > 0) {
|
|
4875
|
+
return this.emitMacroFunctionCall(expr.fn, fullArgs, macroParamsForUnknown, void 0);
|
|
4876
|
+
}
|
|
4418
4877
|
return this.emitDirectFunctionCall(expr.fn, fullArgs);
|
|
4419
4878
|
}
|
|
4420
4879
|
lowerStaticCallExpr(expr) {
|
|
@@ -4541,6 +5000,8 @@ var require_lowering = __commonJS({
|
|
|
4541
5000
|
const savedBlockPosVars = new Map(this.blockPosVars);
|
|
4542
5001
|
const savedStringValues = new Map(this.stringValues);
|
|
4543
5002
|
const savedVarTypes = new Map(this.varTypes);
|
|
5003
|
+
const savedCurrentFnParamNames = new Set(this.currentFnParamNames);
|
|
5004
|
+
const savedCurrentFnMacroParams = new Set(this.currentFnMacroParams);
|
|
4544
5005
|
try {
|
|
4545
5006
|
return callback();
|
|
4546
5007
|
} finally {
|
|
@@ -4556,6 +5017,8 @@ var require_lowering = __commonJS({
|
|
|
4556
5017
|
this.blockPosVars = savedBlockPosVars;
|
|
4557
5018
|
this.stringValues = savedStringValues;
|
|
4558
5019
|
this.varTypes = savedVarTypes;
|
|
5020
|
+
this.currentFnParamNames = savedCurrentFnParamNames;
|
|
5021
|
+
this.currentFnMacroParams = savedCurrentFnMacroParams;
|
|
4559
5022
|
}
|
|
4560
5023
|
}
|
|
4561
5024
|
lowerBuiltinCall(name, args, callSpan) {
|
|
@@ -4702,9 +5165,9 @@ var require_lowering = __commonJS({
|
|
|
4702
5165
|
const dst = this.builder.freshTemp();
|
|
4703
5166
|
const targetType = this.exprToString(args[0]);
|
|
4704
5167
|
const target = targetType === "entity" ? this.exprToTargetString(args[1]) : this.exprToString(args[1]);
|
|
4705
|
-
const
|
|
5168
|
+
const path3 = this.exprToString(args[2]);
|
|
4706
5169
|
const scale = args[3] ? this.exprToString(args[3]) : "1";
|
|
4707
|
-
this.builder.emitRaw(`execute store result score ${dst} rs run data get ${targetType} ${target} ${
|
|
5170
|
+
this.builder.emitRaw(`execute store result score ${dst} rs run data get ${targetType} ${target} ${path3} ${scale}`);
|
|
4708
5171
|
return { kind: "var", name: dst };
|
|
4709
5172
|
}
|
|
4710
5173
|
if (name === "data_merge") {
|
|
@@ -4764,23 +5227,31 @@ var require_lowering = __commonJS({
|
|
|
4764
5227
|
code: "W_DEPRECATED",
|
|
4765
5228
|
...callSpan ? { line: callSpan.line, col: callSpan.col } : {}
|
|
4766
5229
|
});
|
|
4767
|
-
const
|
|
4768
|
-
if (
|
|
4769
|
-
this.builder.emitRaw(
|
|
5230
|
+
const tpResult = this.lowerTpCommandMacroAware(args);
|
|
5231
|
+
if (tpResult) {
|
|
5232
|
+
this.builder.emitRaw(tpResult.cmd);
|
|
4770
5233
|
}
|
|
4771
5234
|
return { kind: "const", value: 0 };
|
|
4772
5235
|
}
|
|
4773
5236
|
if (name === "tp") {
|
|
4774
|
-
const
|
|
4775
|
-
if (
|
|
4776
|
-
this.builder.emitRaw(
|
|
5237
|
+
const tpResult = this.lowerTpCommandMacroAware(args);
|
|
5238
|
+
if (tpResult) {
|
|
5239
|
+
this.builder.emitRaw(tpResult.cmd);
|
|
4777
5240
|
}
|
|
4778
5241
|
return { kind: "const", value: 0 };
|
|
4779
5242
|
}
|
|
4780
|
-
const
|
|
4781
|
-
const
|
|
5243
|
+
const argResults = args.map((arg) => this.exprToBuiltinArg(arg));
|
|
5244
|
+
const hasMacroArg = argResults.some((r) => r.macroParam !== void 0);
|
|
5245
|
+
if (hasMacroArg) {
|
|
5246
|
+
argResults.forEach((r) => {
|
|
5247
|
+
if (r.macroParam)
|
|
5248
|
+
this.currentFnMacroParams.add(r.macroParam);
|
|
5249
|
+
});
|
|
5250
|
+
}
|
|
5251
|
+
const strArgs = argResults.map((r) => r.str);
|
|
5252
|
+
const cmd = BUILTINS2[name]?.(strArgs);
|
|
4782
5253
|
if (cmd) {
|
|
4783
|
-
this.builder.emitRaw(cmd);
|
|
5254
|
+
this.builder.emitRaw(hasMacroArg ? `$${cmd}` : cmd);
|
|
4784
5255
|
}
|
|
4785
5256
|
return { kind: "const", value: 0 };
|
|
4786
5257
|
}
|
|
@@ -5221,8 +5692,8 @@ var require_lowering = __commonJS({
|
|
|
5221
5692
|
return (hash >>> 0).toString(16).padStart(8, "0").slice(0, 4);
|
|
5222
5693
|
}
|
|
5223
5694
|
isStdlibFile(filePath) {
|
|
5224
|
-
const normalized =
|
|
5225
|
-
const stdlibSegment = `${
|
|
5695
|
+
const normalized = path2.normalize(filePath);
|
|
5696
|
+
const stdlibSegment = `${path2.sep}src${path2.sep}stdlib${path2.sep}`;
|
|
5226
5697
|
return normalized.includes(stdlibSegment);
|
|
5227
5698
|
}
|
|
5228
5699
|
filePathForSpan(span) {
|
|
@@ -5280,6 +5751,35 @@ var require_lowering = __commonJS({
|
|
|
5280
5751
|
}
|
|
5281
5752
|
return null;
|
|
5282
5753
|
}
|
|
5754
|
+
lowerTpCommandMacroAware(args) {
|
|
5755
|
+
const pos0 = args[0] ? this.resolveBlockPosExpr(args[0]) : null;
|
|
5756
|
+
const pos1 = args[1] ? this.resolveBlockPosExpr(args[1]) : null;
|
|
5757
|
+
if (args.length === 1 && pos0) {
|
|
5758
|
+
return { cmd: `tp ${emitBlockPos(pos0)}` };
|
|
5759
|
+
}
|
|
5760
|
+
if (args.length === 2 && pos1) {
|
|
5761
|
+
return { cmd: `tp ${this.exprToString(args[0])} ${emitBlockPos(pos1)}` };
|
|
5762
|
+
}
|
|
5763
|
+
if (args.length >= 2) {
|
|
5764
|
+
const argResults = args.map((a) => this.exprToBuiltinArg(a));
|
|
5765
|
+
const hasMacro = argResults.some((r) => r.macroParam !== void 0);
|
|
5766
|
+
if (hasMacro) {
|
|
5767
|
+
argResults.forEach((r) => {
|
|
5768
|
+
if (r.macroParam)
|
|
5769
|
+
this.currentFnMacroParams.add(r.macroParam);
|
|
5770
|
+
});
|
|
5771
|
+
const strs = argResults.map((r) => r.str);
|
|
5772
|
+
if (args.length === 2) {
|
|
5773
|
+
return { cmd: `$tp ${strs[0]} ${strs[1]}` };
|
|
5774
|
+
}
|
|
5775
|
+
if (args.length === 4) {
|
|
5776
|
+
return { cmd: `$tp ${strs[0]} ${strs[1]} ${strs[2]} ${strs[3]}` };
|
|
5777
|
+
}
|
|
5778
|
+
}
|
|
5779
|
+
}
|
|
5780
|
+
const plain = this.lowerTpCommand(args);
|
|
5781
|
+
return plain ? { cmd: plain } : null;
|
|
5782
|
+
}
|
|
5283
5783
|
resolveBlockPosExpr(expr) {
|
|
5284
5784
|
if (expr.kind === "blockpos") {
|
|
5285
5785
|
return expr;
|
|
@@ -5373,6 +5873,28 @@ var require_lowering = __commonJS({
|
|
|
5373
5873
|
}
|
|
5374
5874
|
return void 0;
|
|
5375
5875
|
}
|
|
5876
|
+
/**
|
|
5877
|
+
* Checks a raw() command string for `${...}` interpolation containing runtime variables.
|
|
5878
|
+
* - If the interpolated name is a compile-time constant → OK, no error.
|
|
5879
|
+
* - If the interpolated name is a runtime variable → DiagnosticError.
|
|
5880
|
+
* This catches the common mistake of writing raw("say ${score}") expecting interpolation,
|
|
5881
|
+
* which would silently emit a literal `${score}` in the MC command.
|
|
5882
|
+
*/
|
|
5883
|
+
checkRawCommandInterpolation(cmd, span) {
|
|
5884
|
+
const interpRe = /\$\{([^}]+)\}/g;
|
|
5885
|
+
let match;
|
|
5886
|
+
while ((match = interpRe.exec(cmd)) !== null) {
|
|
5887
|
+
const name = match[1].trim();
|
|
5888
|
+
if (/^\d+(\.\d+)?$/.test(name) || name === "true" || name === "false") {
|
|
5889
|
+
continue;
|
|
5890
|
+
}
|
|
5891
|
+
if (this.constValues.has(name)) {
|
|
5892
|
+
continue;
|
|
5893
|
+
}
|
|
5894
|
+
const loc = span ?? { line: 1, col: 1 };
|
|
5895
|
+
throw new diagnostics_1.DiagnosticError("LoweringError", `raw() command contains runtime variable interpolation '\${${name}}'. Variables cannot be interpolated into raw commands at compile time. Use f-string messages for say/tell/announce, or MC macro syntax '$(${name})' for MC 1.20.2+ commands.`, loc);
|
|
5896
|
+
}
|
|
5897
|
+
}
|
|
5376
5898
|
resolveInstanceMethod(expr) {
|
|
5377
5899
|
const receiver = expr.args[0];
|
|
5378
5900
|
if (!receiver) {
|
|
@@ -5647,6 +6169,7 @@ var require_commands = __commonJS({
|
|
|
5647
6169
|
setblockSavedCommands: 0,
|
|
5648
6170
|
deadCodeRemoved: 0,
|
|
5649
6171
|
constantFolds: 0,
|
|
6172
|
+
inlinedTrivialFunctions: 0,
|
|
5650
6173
|
totalCommandsBefore: 0,
|
|
5651
6174
|
totalCommandsAfter: 0
|
|
5652
6175
|
};
|
|
@@ -5943,11 +6466,81 @@ var require_commands = __commonJS({
|
|
|
5943
6466
|
stats.totalCommandsAfter = optimized.reduce((sum, fn) => sum + fn.commands.length, 0);
|
|
5944
6467
|
return { functions: optimized, stats };
|
|
5945
6468
|
}
|
|
6469
|
+
function inlineTrivialFunctions(functions) {
|
|
6470
|
+
const FUNCTION_CMD_RE = /^function ([^:]+):(.+)$/;
|
|
6471
|
+
const trivialMap = /* @__PURE__ */ new Map();
|
|
6472
|
+
const emptyFunctions = /* @__PURE__ */ new Set();
|
|
6473
|
+
const SYSTEM_FUNCTIONS = /* @__PURE__ */ new Set(["__tick", "__load"]);
|
|
6474
|
+
for (const fn of functions) {
|
|
6475
|
+
if (SYSTEM_FUNCTIONS.has(fn.name) || fn.name.startsWith("__trigger_")) {
|
|
6476
|
+
continue;
|
|
6477
|
+
}
|
|
6478
|
+
const nonCommentCmds = fn.commands.filter((cmd) => !cmd.cmd.startsWith("#"));
|
|
6479
|
+
if (nonCommentCmds.length === 0 && fn.name.includes("/")) {
|
|
6480
|
+
emptyFunctions.add(fn.name);
|
|
6481
|
+
} else if (nonCommentCmds.length === 1 && fn.name.includes("/")) {
|
|
6482
|
+
const match = nonCommentCmds[0].cmd.match(FUNCTION_CMD_RE);
|
|
6483
|
+
if (match) {
|
|
6484
|
+
trivialMap.set(fn.name, match[2]);
|
|
6485
|
+
}
|
|
6486
|
+
}
|
|
6487
|
+
}
|
|
6488
|
+
let changed = true;
|
|
6489
|
+
while (changed) {
|
|
6490
|
+
changed = false;
|
|
6491
|
+
for (const [from, to] of trivialMap) {
|
|
6492
|
+
if (emptyFunctions.has(to)) {
|
|
6493
|
+
trivialMap.delete(from);
|
|
6494
|
+
emptyFunctions.add(from);
|
|
6495
|
+
changed = true;
|
|
6496
|
+
} else {
|
|
6497
|
+
const finalTarget = trivialMap.get(to);
|
|
6498
|
+
if (finalTarget && finalTarget !== to) {
|
|
6499
|
+
trivialMap.set(from, finalTarget);
|
|
6500
|
+
changed = true;
|
|
6501
|
+
}
|
|
6502
|
+
}
|
|
6503
|
+
}
|
|
6504
|
+
}
|
|
6505
|
+
const totalRemoved = trivialMap.size + emptyFunctions.size;
|
|
6506
|
+
if (totalRemoved === 0) {
|
|
6507
|
+
return { functions, stats: {} };
|
|
6508
|
+
}
|
|
6509
|
+
const removedNames = /* @__PURE__ */ new Set([...trivialMap.keys(), ...emptyFunctions]);
|
|
6510
|
+
const result = [];
|
|
6511
|
+
for (const fn of functions) {
|
|
6512
|
+
if (removedNames.has(fn.name)) {
|
|
6513
|
+
continue;
|
|
6514
|
+
}
|
|
6515
|
+
const rewrittenCmds = [];
|
|
6516
|
+
for (const cmd of fn.commands) {
|
|
6517
|
+
const emptyCallMatch = cmd.cmd.match(/^(?:execute .* run )?function ([^:]+):([^\s]+)$/);
|
|
6518
|
+
if (emptyCallMatch) {
|
|
6519
|
+
const targetFn = emptyCallMatch[2];
|
|
6520
|
+
if (emptyFunctions.has(targetFn)) {
|
|
6521
|
+
continue;
|
|
6522
|
+
}
|
|
6523
|
+
}
|
|
6524
|
+
const rewritten = cmd.cmd.replace(/function ([^:]+):([^\s]+)/g, (match, ns, fnPath) => {
|
|
6525
|
+
const target = trivialMap.get(fnPath);
|
|
6526
|
+
return target ? `function ${ns}:${target}` : match;
|
|
6527
|
+
});
|
|
6528
|
+
rewrittenCmds.push({ ...cmd, cmd: rewritten });
|
|
6529
|
+
}
|
|
6530
|
+
result.push({ name: fn.name, commands: rewrittenCmds });
|
|
6531
|
+
}
|
|
6532
|
+
return {
|
|
6533
|
+
functions: result,
|
|
6534
|
+
stats: { inlinedTrivialFunctions: totalRemoved }
|
|
6535
|
+
};
|
|
6536
|
+
}
|
|
5946
6537
|
function optimizeCommandFunctions(functions) {
|
|
5947
6538
|
const initial = cloneFunctions(functions);
|
|
5948
6539
|
const stats = createEmptyOptimizationStats();
|
|
5949
6540
|
stats.totalCommandsBefore = initial.reduce((sum, fn) => sum + fn.commands.length, 0);
|
|
5950
|
-
const
|
|
6541
|
+
const inlined = inlineTrivialFunctions(initial);
|
|
6542
|
+
mergeOptimizationStats(stats, inlined.stats);
|
|
6543
|
+
const licm = applyLICM(inlined.functions);
|
|
5951
6544
|
mergeOptimizationStats(stats, licm.stats);
|
|
5952
6545
|
const cse = applyCSE(licm.functions);
|
|
5953
6546
|
mergeOptimizationStats(stats, cse.stats);
|
|
@@ -6249,6 +6842,7 @@ var require_dce = __commonJS({
|
|
|
6249
6842
|
this.localReads = /* @__PURE__ */ new Set();
|
|
6250
6843
|
this.localDeclIds = /* @__PURE__ */ new WeakMap();
|
|
6251
6844
|
this.localIdCounter = 0;
|
|
6845
|
+
this.warnings = [];
|
|
6252
6846
|
}
|
|
6253
6847
|
eliminate(program) {
|
|
6254
6848
|
this.functionMap.clear();
|
|
@@ -6256,6 +6850,7 @@ var require_dce = __commonJS({
|
|
|
6256
6850
|
this.usedConstants.clear();
|
|
6257
6851
|
this.localReads.clear();
|
|
6258
6852
|
this.localIdCounter = 0;
|
|
6853
|
+
this.warnings.length = 0;
|
|
6259
6854
|
for (const fn of program.declarations) {
|
|
6260
6855
|
this.functionMap.set(fn.name, fn);
|
|
6261
6856
|
}
|
|
@@ -6290,7 +6885,7 @@ var require_dce = __commonJS({
|
|
|
6290
6885
|
findEntryPoints(program) {
|
|
6291
6886
|
const entries = /* @__PURE__ */ new Set();
|
|
6292
6887
|
for (const fn of program.declarations) {
|
|
6293
|
-
if (fn.name
|
|
6888
|
+
if (!fn.name.startsWith("_")) {
|
|
6294
6889
|
entries.add(fn.name);
|
|
6295
6890
|
}
|
|
6296
6891
|
if (fn.decorators.some((decorator) => [
|
|
@@ -6304,7 +6899,6 @@ var require_dce = __commonJS({
|
|
|
6304
6899
|
"on_login",
|
|
6305
6900
|
"on_join_team",
|
|
6306
6901
|
"keep"
|
|
6307
|
-
// Prevent DCE from removing this function
|
|
6308
6902
|
].includes(decorator.name))) {
|
|
6309
6903
|
entries.add(fn.name);
|
|
6310
6904
|
}
|
|
@@ -6415,6 +7009,8 @@ var require_dce = __commonJS({
|
|
|
6415
7009
|
this.collectNestedStmtRefs(stmt, scope);
|
|
6416
7010
|
break;
|
|
6417
7011
|
case "raw":
|
|
7012
|
+
case "break":
|
|
7013
|
+
case "continue":
|
|
6418
7014
|
break;
|
|
6419
7015
|
}
|
|
6420
7016
|
}
|
|
@@ -6575,6 +7171,12 @@ var require_dce = __commonJS({
|
|
|
6575
7171
|
}
|
|
6576
7172
|
return [copySpan({ ...stmt, init }, stmt)];
|
|
6577
7173
|
}
|
|
7174
|
+
this.warnings.push({
|
|
7175
|
+
message: `Unused variable '${stmt.name}'`,
|
|
7176
|
+
code: "W_UNUSED_VAR",
|
|
7177
|
+
line: stmt.span?.line,
|
|
7178
|
+
col: stmt.span?.col
|
|
7179
|
+
});
|
|
6578
7180
|
if (isPureExpr(init)) {
|
|
6579
7181
|
return [];
|
|
6580
7182
|
}
|
|
@@ -6672,6 +7274,10 @@ var require_dce = __commonJS({
|
|
|
6672
7274
|
return [copySpan({ ...stmt, body: this.transformBlock(stmt.body, scope) }, stmt)];
|
|
6673
7275
|
case "raw":
|
|
6674
7276
|
return [stmt];
|
|
7277
|
+
case "break":
|
|
7278
|
+
return [stmt];
|
|
7279
|
+
case "continue":
|
|
7280
|
+
return [stmt];
|
|
6675
7281
|
}
|
|
6676
7282
|
}
|
|
6677
7283
|
transformExpr(expr, scope) {
|
|
@@ -6758,7 +7364,9 @@ var require_dce = __commonJS({
|
|
|
6758
7364
|
};
|
|
6759
7365
|
exports2.DeadCodeEliminator = DeadCodeEliminator;
|
|
6760
7366
|
function eliminateDeadCode(program) {
|
|
6761
|
-
|
|
7367
|
+
const eliminator = new DeadCodeEliminator();
|
|
7368
|
+
const result = eliminator.eliminate(program);
|
|
7369
|
+
return { program: result, warnings: eliminator.warnings };
|
|
6762
7370
|
}
|
|
6763
7371
|
}
|
|
6764
7372
|
});
|
|
@@ -6931,8 +7539,12 @@ var require_mcfunction = __commonJS({
|
|
|
6931
7539
|
commands: entry.commands
|
|
6932
7540
|
})));
|
|
6933
7541
|
const commandMap = new Map(optimized.functions.map((fn) => [fn.name, fn.commands]));
|
|
7542
|
+
const optimizedNames = new Set(optimized.functions.map((fn) => fn.name));
|
|
6934
7543
|
return {
|
|
6935
|
-
files: files.
|
|
7544
|
+
files: files.filter((file) => {
|
|
7545
|
+
const functionName = toFunctionName(file);
|
|
7546
|
+
return !functionName || optimizedNames.has(functionName);
|
|
7547
|
+
}).map((file) => {
|
|
6936
7548
|
const functionName = toFunctionName(file);
|
|
6937
7549
|
if (!functionName)
|
|
6938
7550
|
return file;
|
|
@@ -7086,11 +7698,11 @@ var require_mcfunction = __commonJS({
|
|
|
7086
7698
|
if (!eventTrigger) {
|
|
7087
7699
|
continue;
|
|
7088
7700
|
}
|
|
7089
|
-
let
|
|
7701
|
+
let path2 = "";
|
|
7090
7702
|
let criteria = {};
|
|
7091
7703
|
switch (eventTrigger.kind) {
|
|
7092
7704
|
case "advancement":
|
|
7093
|
-
|
|
7705
|
+
path2 = `data/${ns}/advancements/on_advancement_${fn.name}.json`;
|
|
7094
7706
|
criteria = {
|
|
7095
7707
|
trigger: {
|
|
7096
7708
|
trigger: `minecraft:${eventTrigger.value}`
|
|
@@ -7098,7 +7710,7 @@ var require_mcfunction = __commonJS({
|
|
|
7098
7710
|
};
|
|
7099
7711
|
break;
|
|
7100
7712
|
case "craft":
|
|
7101
|
-
|
|
7713
|
+
path2 = `data/${ns}/advancements/on_craft_${fn.name}.json`;
|
|
7102
7714
|
criteria = {
|
|
7103
7715
|
crafted: {
|
|
7104
7716
|
trigger: "minecraft:inventory_changed",
|
|
@@ -7113,7 +7725,7 @@ var require_mcfunction = __commonJS({
|
|
|
7113
7725
|
};
|
|
7114
7726
|
break;
|
|
7115
7727
|
case "death":
|
|
7116
|
-
|
|
7728
|
+
path2 = `data/${ns}/advancements/on_death_${fn.name}.json`;
|
|
7117
7729
|
criteria = {
|
|
7118
7730
|
death: {
|
|
7119
7731
|
trigger: "minecraft:entity_killed_player"
|
|
@@ -7125,7 +7737,7 @@ var require_mcfunction = __commonJS({
|
|
|
7125
7737
|
continue;
|
|
7126
7738
|
}
|
|
7127
7739
|
advancements.push({
|
|
7128
|
-
path,
|
|
7740
|
+
path: path2,
|
|
7129
7741
|
content: JSON.stringify({
|
|
7130
7742
|
criteria,
|
|
7131
7743
|
rewards: {
|
|
@@ -7195,8 +7807,8 @@ var require_compile = __commonJS({
|
|
|
7195
7807
|
exports2.preprocessSource = preprocessSource;
|
|
7196
7808
|
exports2.compile = compile;
|
|
7197
7809
|
exports2.formatCompileError = formatCompileError;
|
|
7198
|
-
var
|
|
7199
|
-
var
|
|
7810
|
+
var fs2 = __importStar(require("fs"));
|
|
7811
|
+
var path2 = __importStar(require("path"));
|
|
7200
7812
|
var lexer_1 = require_lexer();
|
|
7201
7813
|
var parser_1 = require_parser();
|
|
7202
7814
|
var lowering_1 = require_lowering();
|
|
@@ -7219,7 +7831,7 @@ var require_compile = __commonJS({
|
|
|
7219
7831
|
const { filePath } = options;
|
|
7220
7832
|
const seen = options.seen ?? /* @__PURE__ */ new Set();
|
|
7221
7833
|
if (filePath) {
|
|
7222
|
-
seen.add(
|
|
7834
|
+
seen.add(path2.resolve(filePath));
|
|
7223
7835
|
}
|
|
7224
7836
|
const lines = source.split("\n");
|
|
7225
7837
|
const imports = [];
|
|
@@ -7233,12 +7845,12 @@ var require_compile = __commonJS({
|
|
|
7233
7845
|
if (!filePath) {
|
|
7234
7846
|
throw new diagnostics_1.DiagnosticError("ParseError", "Import statements require a file path", { line: i + 1, col: 1 }, lines);
|
|
7235
7847
|
}
|
|
7236
|
-
const importPath =
|
|
7848
|
+
const importPath = path2.resolve(path2.dirname(filePath), match[1]);
|
|
7237
7849
|
if (!seen.has(importPath)) {
|
|
7238
7850
|
seen.add(importPath);
|
|
7239
7851
|
let importedSource;
|
|
7240
7852
|
try {
|
|
7241
|
-
importedSource =
|
|
7853
|
+
importedSource = fs2.readFileSync(importPath, "utf-8");
|
|
7242
7854
|
} catch {
|
|
7243
7855
|
throw new diagnostics_1.DiagnosticError("ParseError", `Cannot import '${match[1]}'`, { file: filePath, line: i + 1, col: 1 }, lines);
|
|
7244
7856
|
}
|
|
@@ -7266,7 +7878,7 @@ var require_compile = __commonJS({
|
|
|
7266
7878
|
ranges.push({
|
|
7267
7879
|
startLine: lineOffset + 1,
|
|
7268
7880
|
endLine: lineOffset + countLines(body),
|
|
7269
|
-
filePath:
|
|
7881
|
+
filePath: path2.resolve(filePath)
|
|
7270
7882
|
});
|
|
7271
7883
|
}
|
|
7272
7884
|
return { source: combined, ranges };
|
|
@@ -7284,7 +7896,8 @@ var require_compile = __commonJS({
|
|
|
7284
7896
|
sourceLines = preprocessedSource.split("\n");
|
|
7285
7897
|
const tokens = new lexer_1.Lexer(preprocessedSource, filePath).tokenize();
|
|
7286
7898
|
const parsedAst = new parser_1.Parser(tokens, preprocessedSource, filePath).parse(namespace);
|
|
7287
|
-
const
|
|
7899
|
+
const dceResult = shouldRunDce ? (0, dce_1.eliminateDeadCode)(parsedAst) : { program: parsedAst, warnings: [] };
|
|
7900
|
+
const ast = dceResult.program;
|
|
7288
7901
|
const ir = new lowering_1.Lowering(namespace, preprocessed.ranges).lower(ast);
|
|
7289
7902
|
const optimized = shouldOptimize ? { ...ir, functions: ir.functions.map((fn) => (0, passes_1.optimize)(fn)) } : ir;
|
|
7290
7903
|
const generated = (0, mcfunction_1.generateDatapackWithStats)(optimized);
|
|
@@ -7364,7 +7977,7 @@ var require_mc_validator = __commonJS({
|
|
|
7364
7977
|
})();
|
|
7365
7978
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
7366
7979
|
exports2.MCCommandValidator = void 0;
|
|
7367
|
-
var
|
|
7980
|
+
var fs2 = __importStar(require("fs"));
|
|
7368
7981
|
var FUNCTION_ID_RE = /^[0-9a-z_.-]+:[0-9a-z_./-]+$/i;
|
|
7369
7982
|
var INTEGER_RE = /^-?\d+$/;
|
|
7370
7983
|
var SCORE_RANGE_RE = /^-?\d+\.\.$|^\.\.-?\d+$|^-?\d+\.\.-?\d+$|^-?\d+$/;
|
|
@@ -7377,7 +7990,7 @@ var require_mc_validator = __commonJS({
|
|
|
7377
7990
|
var SCOREBOARD_OPERATIONS = /* @__PURE__ */ new Set(["=", "+=", "-=", "*=", "/=", "%=", "<", ">", "><"]);
|
|
7378
7991
|
var MCCommandValidator = class {
|
|
7379
7992
|
constructor(commandsPath) {
|
|
7380
|
-
const parsed = JSON.parse(
|
|
7993
|
+
const parsed = JSON.parse(fs2.readFileSync(commandsPath, "utf-8"));
|
|
7381
7994
|
this.root = parsed.root;
|
|
7382
7995
|
this.rootChildren = parsed.root.children ?? [];
|
|
7383
7996
|
}
|
|
@@ -7653,9 +8266,10 @@ var require_dist = __commonJS({
|
|
|
7653
8266
|
"../../dist/index.js"(exports2) {
|
|
7654
8267
|
"use strict";
|
|
7655
8268
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
7656
|
-
exports2.MCCommandValidator = exports2.generateDatapack = exports2.optimize = exports2.Lowering = exports2.TypeChecker = exports2.Parser = exports2.Lexer = void 0;
|
|
8269
|
+
exports2.MCCommandValidator = exports2.generateDatapack = exports2.optimize = exports2.Lowering = exports2.TypeChecker = exports2.Parser = exports2.Lexer = exports2.version = void 0;
|
|
7657
8270
|
exports2.compile = compile;
|
|
7658
8271
|
exports2.check = check;
|
|
8272
|
+
exports2.version = "1.2.11";
|
|
7659
8273
|
var lexer_1 = require_lexer();
|
|
7660
8274
|
var parser_1 = require_parser();
|
|
7661
8275
|
var typechecker_1 = require_typechecker();
|
|
@@ -7675,7 +8289,8 @@ var require_dist = __commonJS({
|
|
|
7675
8289
|
const preprocessedSource = preprocessed.source;
|
|
7676
8290
|
const tokens = new lexer_1.Lexer(preprocessedSource, filePath).tokenize();
|
|
7677
8291
|
const parsedAst = new parser_1.Parser(tokens, preprocessedSource, filePath).parse(namespace);
|
|
7678
|
-
const
|
|
8292
|
+
const dceResult = shouldRunDce ? (0, dce_1.eliminateDeadCode)(parsedAst) : { program: parsedAst, warnings: [] };
|
|
8293
|
+
const ast = dceResult.program;
|
|
7679
8294
|
let typeErrors;
|
|
7680
8295
|
if (shouldTypeCheck) {
|
|
7681
8296
|
const checker = new typechecker_1.TypeChecker(preprocessedSource, filePath);
|
|
@@ -7725,7 +8340,7 @@ var require_dist = __commonJS({
|
|
|
7725
8340
|
ast,
|
|
7726
8341
|
ir: optimizedIR,
|
|
7727
8342
|
typeErrors,
|
|
7728
|
-
warnings: lowering.warnings,
|
|
8343
|
+
warnings: [...dceResult.warnings, ...lowering.warnings],
|
|
7729
8344
|
stats: optimizationStats
|
|
7730
8345
|
};
|
|
7731
8346
|
}
|
|
@@ -8950,6 +9565,8 @@ function registerCompletionProvider(context) {
|
|
|
8950
9565
|
|
|
8951
9566
|
// src/symbols.ts
|
|
8952
9567
|
var vscode4 = __toESM(require("vscode"));
|
|
9568
|
+
var path = __toESM(require("path"));
|
|
9569
|
+
var fs = __toESM(require("fs"));
|
|
8953
9570
|
var DECL_RE = /\b(fn|let|const|struct|enum)\s+(\w+)/g;
|
|
8954
9571
|
function findDeclarations(doc) {
|
|
8955
9572
|
const text = doc.getText();
|
|
@@ -9028,6 +9645,94 @@ function findAllOccurrences(doc, word) {
|
|
|
9028
9645
|
function escapeRegex(s) {
|
|
9029
9646
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
9030
9647
|
}
|
|
9648
|
+
var builtinLineCache = null;
|
|
9649
|
+
function getBuiltinDtsPath(context) {
|
|
9650
|
+
return path.join(context.extensionPath, "builtins.d.mcrs");
|
|
9651
|
+
}
|
|
9652
|
+
function loadBuiltinLines(dtsPath) {
|
|
9653
|
+
if (builtinLineCache) return builtinLineCache;
|
|
9654
|
+
const cache = /* @__PURE__ */ new Map();
|
|
9655
|
+
try {
|
|
9656
|
+
const content = fs.readFileSync(dtsPath, "utf-8");
|
|
9657
|
+
const lines = content.split("\n");
|
|
9658
|
+
for (let i = 0; i < lines.length; i++) {
|
|
9659
|
+
const m = lines[i].match(/^declare fn (\w+)\(/);
|
|
9660
|
+
if (m) {
|
|
9661
|
+
cache.set(m[1], i);
|
|
9662
|
+
}
|
|
9663
|
+
}
|
|
9664
|
+
} catch {
|
|
9665
|
+
}
|
|
9666
|
+
builtinLineCache = cache;
|
|
9667
|
+
return cache;
|
|
9668
|
+
}
|
|
9669
|
+
var KNOWN_BUILTINS = /* @__PURE__ */ new Set([
|
|
9670
|
+
"say",
|
|
9671
|
+
"tell",
|
|
9672
|
+
"tellraw",
|
|
9673
|
+
"announce",
|
|
9674
|
+
"title",
|
|
9675
|
+
"subtitle",
|
|
9676
|
+
"actionbar",
|
|
9677
|
+
"title_times",
|
|
9678
|
+
"give",
|
|
9679
|
+
"kill",
|
|
9680
|
+
"effect",
|
|
9681
|
+
"effect_clear",
|
|
9682
|
+
"clear",
|
|
9683
|
+
"kick",
|
|
9684
|
+
"xp_add",
|
|
9685
|
+
"xp_set",
|
|
9686
|
+
"tp",
|
|
9687
|
+
"tp_to",
|
|
9688
|
+
"setblock",
|
|
9689
|
+
"fill",
|
|
9690
|
+
"clone",
|
|
9691
|
+
"summon",
|
|
9692
|
+
"particle",
|
|
9693
|
+
"playsound",
|
|
9694
|
+
"weather",
|
|
9695
|
+
"time_set",
|
|
9696
|
+
"time_add",
|
|
9697
|
+
"gamerule",
|
|
9698
|
+
"difficulty",
|
|
9699
|
+
"tag_add",
|
|
9700
|
+
"tag_remove",
|
|
9701
|
+
"scoreboard_get",
|
|
9702
|
+
"score",
|
|
9703
|
+
"scoreboard_set",
|
|
9704
|
+
"scoreboard_display",
|
|
9705
|
+
"scoreboard_hide",
|
|
9706
|
+
"scoreboard_add_objective",
|
|
9707
|
+
"scoreboard_remove_objective",
|
|
9708
|
+
"random",
|
|
9709
|
+
"random_native",
|
|
9710
|
+
"random_sequence",
|
|
9711
|
+
"data_get",
|
|
9712
|
+
"data_merge",
|
|
9713
|
+
"bossbar_add",
|
|
9714
|
+
"bossbar_set_value",
|
|
9715
|
+
"bossbar_set_max",
|
|
9716
|
+
"bossbar_set_color",
|
|
9717
|
+
"bossbar_set_style",
|
|
9718
|
+
"bossbar_set_visible",
|
|
9719
|
+
"bossbar_set_players",
|
|
9720
|
+
"bossbar_remove",
|
|
9721
|
+
"bossbar_get_value",
|
|
9722
|
+
"team_add",
|
|
9723
|
+
"team_remove",
|
|
9724
|
+
"team_join",
|
|
9725
|
+
"team_leave",
|
|
9726
|
+
"team_option",
|
|
9727
|
+
"set_new",
|
|
9728
|
+
"set_add",
|
|
9729
|
+
"set_contains",
|
|
9730
|
+
"set_remove",
|
|
9731
|
+
"set_clear",
|
|
9732
|
+
"setTimeout",
|
|
9733
|
+
"setInterval",
|
|
9734
|
+
"clearInterval"
|
|
9735
|
+
]);
|
|
9031
9736
|
function registerSymbolProviders(context) {
|
|
9032
9737
|
const selector = { language: "redscript", scheme: "file" };
|
|
9033
9738
|
context.subscriptions.push(
|
|
@@ -9037,6 +9742,18 @@ function registerSymbolProviders(context) {
|
|
|
9037
9742
|
const wordRange = doc.getWordRangeAtPosition(position);
|
|
9038
9743
|
if (!wordRange) return null;
|
|
9039
9744
|
const word = doc.getText(wordRange);
|
|
9745
|
+
const line = doc.lineAt(position.line).text;
|
|
9746
|
+
const afterWord = line.slice(wordRange.end.character).trimStart();
|
|
9747
|
+
if (afterWord.startsWith("(") && KNOWN_BUILTINS.has(word)) {
|
|
9748
|
+
const dtsPath = getBuiltinDtsPath(context);
|
|
9749
|
+
const lines = loadBuiltinLines(dtsPath);
|
|
9750
|
+
const lineNum = lines.get(word);
|
|
9751
|
+
if (lineNum !== void 0) {
|
|
9752
|
+
const dtsUri = vscode4.Uri.file(dtsPath);
|
|
9753
|
+
const pos = new vscode4.Position(lineNum, 0);
|
|
9754
|
+
return new vscode4.Location(dtsUri, pos);
|
|
9755
|
+
}
|
|
9756
|
+
}
|
|
9040
9757
|
const structType = isStructLiteralField(doc, position, word);
|
|
9041
9758
|
if (structType) {
|
|
9042
9759
|
const structFields = findStructFields(doc);
|