redscript-mc 3.0.1 → 3.0.2
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/.github/workflows/ci.yml +1 -0
- package/README.md +119 -313
- package/README.zh.md +118 -314
- package/ROADMAP.md +5 -5
- package/dist/data/impl_test/function/counter/get.mcfunction +5 -0
- package/dist/data/impl_test/function/counter/inc.mcfunction +7 -0
- package/dist/data/impl_test/function/counter/new.mcfunction +4 -0
- package/dist/data/impl_test/function/load.mcfunction +1 -0
- package/dist/data/impl_test/function/test_impl.mcfunction +10 -0
- package/dist/data/minecraft/tags/function/load.json +5 -0
- package/dist/data/playground/function/load.mcfunction +1 -0
- package/dist/data/playground/function/start.mcfunction +4 -0
- package/dist/data/playground/function/start__say_macro_t1.mcfunction +1 -0
- package/dist/data/playground/function/stop.mcfunction +5 -0
- package/dist/data/playground/function/stop__say_macro_t0.mcfunction +1 -0
- package/dist/data/stdlib_queue8_test/function/__queue_append_apply.mcfunction +4 -0
- package/dist/data/stdlib_queue8_test/function/__queue_peek_apply.mcfunction +4 -0
- package/dist/data/stdlib_queue8_test/function/__queue_size_raw_apply.mcfunction +4 -0
- package/dist/data/stdlib_queue8_test/function/load.mcfunction +1 -0
- package/dist/data/stdlib_queue8_test/function/queue_clear.mcfunction +6 -0
- package/dist/data/stdlib_queue8_test/function/queue_empty__merge_1.mcfunction +5 -0
- package/dist/data/stdlib_queue8_test/function/queue_empty__then_0.mcfunction +5 -0
- package/dist/data/stdlib_queue8_test/function/queue_peek__merge_1.mcfunction +13 -0
- package/dist/data/stdlib_queue8_test/function/queue_peek__then_0.mcfunction +5 -0
- package/dist/data/stdlib_queue8_test/function/queue_pop__merge_1.mcfunction +15 -0
- package/dist/data/stdlib_queue8_test/function/queue_pop__then_0.mcfunction +5 -0
- package/dist/data/stdlib_queue8_test/function/queue_push__const_11.mcfunction +6 -0
- package/dist/data/stdlib_queue8_test/function/queue_push__const_22.mcfunction +6 -0
- package/dist/data/stdlib_queue8_test/function/queue_size.mcfunction +13 -0
- package/dist/data/stdlib_queue8_test/function/test_queue_push_and_size.mcfunction +13 -0
- package/dist/data/test/function/load.mcfunction +1 -0
- package/dist/data/test/function/say_at.mcfunction +6 -0
- package/dist/data/test/function/test.mcfunction +4 -0
- package/dist/pack.mcmeta +6 -0
- package/dist/package.json +1 -1
- package/dist/src/__tests__/formatter-extra.test.d.ts +7 -0
- package/dist/src/__tests__/formatter-extra.test.js +123 -0
- package/dist/src/__tests__/global-vars.test.d.ts +13 -0
- package/dist/src/__tests__/global-vars.test.js +156 -0
- package/dist/src/__tests__/lint/new-rules.test.d.ts +9 -0
- package/dist/src/__tests__/lint/new-rules.test.js +402 -0
- package/dist/src/__tests__/lsp-rename.test.d.ts +8 -0
- package/dist/src/__tests__/lsp-rename.test.js +157 -0
- package/dist/src/__tests__/mc-integration/say-fstring.test.d.ts +11 -0
- package/dist/src/__tests__/mc-integration/say-fstring.test.js +220 -0
- package/dist/src/__tests__/mc-integration/stdlib-coverage-2.test.js +1 -1
- package/dist/src/__tests__/mc-integration/stdlib-coverage-3.test.js +1 -1
- package/dist/src/__tests__/mc-integration/stdlib-coverage-4.test.js +1 -1
- package/dist/src/__tests__/mc-integration/stdlib-coverage-5.test.js +1 -1
- package/dist/src/__tests__/mc-integration/stdlib-coverage-6.test.js +1 -1
- package/dist/src/__tests__/mc-integration/stdlib-coverage-7.test.js +1 -1
- package/dist/src/__tests__/mc-integration/stdlib-coverage-8.test.js +1 -1
- package/dist/src/__tests__/mc-syntax.test.js +4 -1
- package/dist/src/__tests__/monomorphize-coverage.test.d.ts +9 -0
- package/dist/src/__tests__/monomorphize-coverage.test.js +204 -0
- package/dist/src/__tests__/optimizer-cse.test.d.ts +7 -0
- package/dist/src/__tests__/optimizer-cse.test.js +226 -0
- package/dist/src/__tests__/parser.test.js +4 -13
- package/dist/src/__tests__/repl-server-extra.test.js +6 -7
- package/dist/src/__tests__/repl-server.test.js +5 -7
- package/dist/src/__tests__/stdlib/queue.test.js +6 -6
- package/dist/src/cli.js +0 -0
- package/dist/src/lexer/index.js +2 -1
- package/dist/src/lint/index.d.ts +12 -5
- package/dist/src/lint/index.js +730 -5
- package/dist/src/lsp/main.js +0 -0
- package/dist/src/mc-test/client.d.ts +21 -0
- package/dist/src/mc-test/client.js +34 -0
- package/dist/src/mir/lower.js +108 -6
- package/dist/src/optimizer/interprocedural.js +37 -2
- package/dist/src/parser/decl-parser.d.ts +19 -0
- package/dist/src/parser/decl-parser.js +323 -0
- package/dist/src/parser/expr-parser.d.ts +46 -0
- package/dist/src/parser/expr-parser.js +759 -0
- package/dist/src/parser/index.d.ts +8 -129
- package/dist/src/parser/index.js +13 -2262
- package/dist/src/parser/stmt-parser.d.ts +28 -0
- package/dist/src/parser/stmt-parser.js +577 -0
- package/dist/src/parser/type-parser.d.ts +20 -0
- package/dist/src/parser/type-parser.js +257 -0
- package/dist/src/parser/utils.d.ts +34 -0
- package/dist/src/parser/utils.js +141 -0
- package/docs/dev/README-mc-integration-tests.md +141 -0
- package/docs/lint-rules.md +162 -0
- package/docs/stdlib/bigint.md +2 -0
- package/editors/vscode/README.md +63 -41
- package/editors/vscode/out/extension.js +1881 -1776
- package/editors/vscode/out/lsp-server.js +4257 -3651
- package/editors/vscode/package-lock.json +3 -3
- package/editors/vscode/package.json +1 -1
- package/examples/loops-demo.mcrs +87 -0
- package/package.json +1 -1
- package/redscript-docs/docs/en/stdlib/advanced.md +629 -0
- package/redscript-docs/docs/en/stdlib/bigint.md +316 -0
- package/redscript-docs/docs/en/stdlib/bits.md +292 -0
- package/redscript-docs/docs/en/stdlib/bossbar.md +177 -0
- package/redscript-docs/docs/en/stdlib/calculus.md +289 -0
- package/redscript-docs/docs/en/stdlib/color.md +353 -0
- package/redscript-docs/docs/en/stdlib/combat.md +88 -0
- package/redscript-docs/docs/en/stdlib/cooldown.md +82 -0
- package/redscript-docs/docs/en/stdlib/dialog.md +155 -0
- package/redscript-docs/docs/en/stdlib/easing.md +558 -0
- package/redscript-docs/docs/en/stdlib/ecs.md +475 -0
- package/redscript-docs/docs/en/stdlib/effects.md +324 -0
- package/redscript-docs/docs/en/stdlib/events.md +3 -0
- package/redscript-docs/docs/en/stdlib/expr.md +45 -0
- package/redscript-docs/docs/en/stdlib/fft.md +141 -0
- package/redscript-docs/docs/en/stdlib/geometry.md +430 -0
- package/redscript-docs/docs/en/stdlib/graph.md +259 -0
- package/redscript-docs/docs/en/stdlib/heap.md +185 -0
- package/redscript-docs/docs/en/stdlib/interactions.md +179 -0
- package/redscript-docs/docs/en/stdlib/inventory.md +97 -0
- package/redscript-docs/docs/en/stdlib/linalg.md +557 -0
- package/redscript-docs/docs/en/stdlib/list.md +559 -0
- package/redscript-docs/docs/en/stdlib/map.md +140 -0
- package/redscript-docs/docs/en/stdlib/math.md +193 -0
- package/redscript-docs/docs/en/stdlib/math_hp.md +149 -0
- package/redscript-docs/docs/en/stdlib/matrix.md +403 -0
- package/redscript-docs/docs/en/stdlib/mobs.md +965 -0
- package/redscript-docs/docs/en/stdlib/noise.md +244 -0
- package/redscript-docs/docs/en/stdlib/ode.md +253 -0
- package/redscript-docs/docs/en/stdlib/parabola.md +342 -0
- package/redscript-docs/docs/en/stdlib/particles.md +311 -0
- package/redscript-docs/docs/en/stdlib/pathfind.md +255 -0
- package/redscript-docs/docs/en/stdlib/physics.md +493 -0
- package/redscript-docs/docs/en/stdlib/player.md +78 -0
- package/redscript-docs/docs/en/stdlib/quaternion.md +673 -0
- package/redscript-docs/docs/en/stdlib/queue.md +134 -0
- package/redscript-docs/docs/en/stdlib/random.md +223 -0
- package/redscript-docs/docs/en/stdlib/result.md +143 -0
- package/redscript-docs/docs/en/stdlib/scheduler.md +183 -0
- package/redscript-docs/docs/en/stdlib/set_int.md +190 -0
- package/redscript-docs/docs/en/stdlib/sets.md +101 -0
- package/redscript-docs/docs/en/stdlib/signal.md +400 -0
- package/redscript-docs/docs/en/stdlib/sort.md +104 -0
- package/redscript-docs/docs/en/stdlib/spawn.md +147 -0
- package/redscript-docs/docs/en/stdlib/state.md +142 -0
- package/redscript-docs/docs/en/stdlib/strings.md +154 -0
- package/redscript-docs/docs/en/stdlib/tags.md +3451 -0
- package/redscript-docs/docs/en/stdlib/teams.md +153 -0
- package/redscript-docs/docs/en/stdlib/timer.md +246 -0
- package/redscript-docs/docs/en/stdlib/vec.md +158 -0
- package/redscript-docs/docs/en/stdlib/world.md +298 -0
- package/redscript-docs/docs/zh/stdlib/advanced.md +615 -0
- package/redscript-docs/docs/zh/stdlib/bigint.md +316 -0
- package/redscript-docs/docs/zh/stdlib/bits.md +292 -0
- package/redscript-docs/docs/zh/stdlib/bossbar.md +170 -0
- package/redscript-docs/docs/zh/stdlib/calculus.md +287 -0
- package/redscript-docs/docs/zh/stdlib/color.md +353 -0
- package/redscript-docs/docs/zh/stdlib/combat.md +88 -0
- package/redscript-docs/docs/zh/stdlib/cooldown.md +84 -0
- package/redscript-docs/docs/zh/stdlib/dialog.md +152 -0
- package/redscript-docs/docs/zh/stdlib/easing.md +558 -0
- package/redscript-docs/docs/zh/stdlib/ecs.md +472 -0
- package/redscript-docs/docs/zh/stdlib/effects.md +324 -0
- package/redscript-docs/docs/zh/stdlib/events.md +3 -0
- package/redscript-docs/docs/zh/stdlib/expr.md +37 -0
- package/redscript-docs/docs/zh/stdlib/fft.md +128 -0
- package/redscript-docs/docs/zh/stdlib/geometry.md +430 -0
- package/redscript-docs/docs/zh/stdlib/graph.md +259 -0
- package/redscript-docs/docs/zh/stdlib/heap.md +185 -0
- package/redscript-docs/docs/zh/stdlib/interactions.md +160 -0
- package/redscript-docs/docs/zh/stdlib/inventory.md +94 -0
- package/redscript-docs/docs/zh/stdlib/linalg.md +543 -0
- package/redscript-docs/docs/zh/stdlib/list.md +561 -0
- package/redscript-docs/docs/zh/stdlib/map.md +132 -0
- package/redscript-docs/docs/zh/stdlib/math.md +193 -0
- package/redscript-docs/docs/zh/stdlib/math_hp.md +143 -0
- package/redscript-docs/docs/zh/stdlib/matrix.md +396 -0
- package/redscript-docs/docs/zh/stdlib/mobs.md +965 -0
- package/redscript-docs/docs/zh/stdlib/noise.md +244 -0
- package/redscript-docs/docs/zh/stdlib/ode.md +243 -0
- package/redscript-docs/docs/zh/stdlib/parabola.md +337 -0
- package/redscript-docs/docs/zh/stdlib/particles.md +307 -0
- package/redscript-docs/docs/zh/stdlib/pathfind.md +255 -0
- package/redscript-docs/docs/zh/stdlib/physics.md +493 -0
- package/redscript-docs/docs/zh/stdlib/player.md +78 -0
- package/redscript-docs/docs/zh/stdlib/quaternion.md +669 -0
- package/redscript-docs/docs/zh/stdlib/queue.md +124 -0
- package/redscript-docs/docs/zh/stdlib/random.md +222 -0
- package/redscript-docs/docs/zh/stdlib/result.md +147 -0
- package/redscript-docs/docs/zh/stdlib/scheduler.md +173 -0
- package/redscript-docs/docs/zh/stdlib/set_int.md +180 -0
- package/redscript-docs/docs/zh/stdlib/sets.md +107 -0
- package/redscript-docs/docs/zh/stdlib/signal.md +373 -0
- package/redscript-docs/docs/zh/stdlib/sort.md +104 -0
- package/redscript-docs/docs/zh/stdlib/spawn.md +142 -0
- package/redscript-docs/docs/zh/stdlib/state.md +134 -0
- package/redscript-docs/docs/zh/stdlib/strings.md +107 -0
- package/redscript-docs/docs/zh/stdlib/tags.md +3451 -0
- package/redscript-docs/docs/zh/stdlib/teams.md +150 -0
- package/redscript-docs/docs/zh/stdlib/timer.md +254 -0
- package/redscript-docs/docs/zh/stdlib/vec.md +158 -0
- package/redscript-docs/docs/zh/stdlib/world.md +289 -0
- package/src/__tests__/formatter-extra.test.ts +139 -0
- package/src/__tests__/global-vars.test.ts +171 -0
- package/src/__tests__/lint/new-rules.test.ts +437 -0
- package/src/__tests__/lsp-rename.test.ts +171 -0
- package/src/__tests__/mc-integration/say-fstring.test.ts +211 -0
- package/src/__tests__/mc-integration/stdlib-coverage-2.test.ts +1 -1
- package/src/__tests__/mc-integration/stdlib-coverage-3.test.ts +1 -1
- package/src/__tests__/mc-integration/stdlib-coverage-4.test.ts +1 -1
- package/src/__tests__/mc-integration/stdlib-coverage-5.test.ts +1 -1
- package/src/__tests__/mc-integration/stdlib-coverage-6.test.ts +1 -1
- package/src/__tests__/mc-integration/stdlib-coverage-7.test.ts +1 -1
- package/src/__tests__/mc-integration/stdlib-coverage-8.test.ts +1 -1
- package/src/__tests__/mc-syntax.test.ts +3 -0
- package/src/__tests__/monomorphize-coverage.test.ts +220 -0
- package/src/__tests__/optimizer-cse.test.ts +250 -0
- package/src/__tests__/parser.test.ts +4 -13
- package/src/__tests__/repl-server-extra.test.ts +6 -6
- package/src/__tests__/repl-server.test.ts +5 -6
- package/src/__tests__/stdlib/queue.test.ts +6 -6
- package/src/lexer/index.ts +2 -1
- package/src/lint/index.ts +713 -5
- package/src/mc-test/client.ts +40 -0
- package/src/mir/lower.ts +111 -2
- package/src/optimizer/interprocedural.ts +40 -2
- package/src/parser/decl-parser.ts +349 -0
- package/src/parser/expr-parser.ts +838 -0
- package/src/parser/index.ts +17 -2558
- package/src/parser/stmt-parser.ts +585 -0
- package/src/parser/type-parser.ts +276 -0
- package/src/parser/utils.ts +173 -0
- package/src/stdlib/queue.mcrs +19 -6
|
@@ -18107,7 +18107,7 @@ var require_package = __commonJS({
|
|
|
18107
18107
|
"../../dist/package.json"(exports2, module2) {
|
|
18108
18108
|
module2.exports = {
|
|
18109
18109
|
name: "redscript-mc",
|
|
18110
|
-
version: "3.0.
|
|
18110
|
+
version: "3.0.2",
|
|
18111
18111
|
description: "A high-level programming language that compiles to Minecraft datapacks",
|
|
18112
18112
|
main: "dist/src/index.js",
|
|
18113
18113
|
bin: {
|
|
@@ -18877,15 +18877,15 @@ var require_lexer = __commonJS({
|
|
|
18877
18877
|
}
|
|
18878
18878
|
});
|
|
18879
18879
|
|
|
18880
|
-
// ../../dist/src/parser/
|
|
18881
|
-
var
|
|
18882
|
-
"../../dist/src/parser/
|
|
18880
|
+
// ../../dist/src/parser/utils.js
|
|
18881
|
+
var require_utils = __commonJS({
|
|
18882
|
+
"../../dist/src/parser/utils.js"(exports2) {
|
|
18883
18883
|
"use strict";
|
|
18884
18884
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
18885
|
-
exports2.
|
|
18885
|
+
exports2.ParserBase = exports2.BINARY_OPS = exports2.PRECEDENCE = void 0;
|
|
18886
18886
|
var lexer_1 = require_lexer();
|
|
18887
18887
|
var diagnostics_1 = require_diagnostics();
|
|
18888
|
-
|
|
18888
|
+
exports2.PRECEDENCE = {
|
|
18889
18889
|
"||": 1,
|
|
18890
18890
|
"&&": 2,
|
|
18891
18891
|
"==": 3,
|
|
@@ -18901,45 +18901,8 @@ var require_parser = __commonJS({
|
|
|
18901
18901
|
"/": 6,
|
|
18902
18902
|
"%": 6
|
|
18903
18903
|
};
|
|
18904
|
-
|
|
18905
|
-
var
|
|
18906
|
-
"entity",
|
|
18907
|
-
"Player",
|
|
18908
|
-
"Mob",
|
|
18909
|
-
"HostileMob",
|
|
18910
|
-
"PassiveMob",
|
|
18911
|
-
"Zombie",
|
|
18912
|
-
"Skeleton",
|
|
18913
|
-
"Creeper",
|
|
18914
|
-
"Spider",
|
|
18915
|
-
"Enderman",
|
|
18916
|
-
"Blaze",
|
|
18917
|
-
"Witch",
|
|
18918
|
-
"Slime",
|
|
18919
|
-
"ZombieVillager",
|
|
18920
|
-
"Husk",
|
|
18921
|
-
"Drowned",
|
|
18922
|
-
"Stray",
|
|
18923
|
-
"WitherSkeleton",
|
|
18924
|
-
"CaveSpider",
|
|
18925
|
-
"Pig",
|
|
18926
|
-
"Cow",
|
|
18927
|
-
"Sheep",
|
|
18928
|
-
"Chicken",
|
|
18929
|
-
"Villager",
|
|
18930
|
-
"WanderingTrader",
|
|
18931
|
-
"ArmorStand",
|
|
18932
|
-
"Item",
|
|
18933
|
-
"Arrow"
|
|
18934
|
-
]);
|
|
18935
|
-
function computeIsSingle(raw) {
|
|
18936
|
-
if (/^@[spr](\[|$)/.test(raw))
|
|
18937
|
-
return true;
|
|
18938
|
-
if (/[\[,\s]limit=1[,\]\s]/.test(raw))
|
|
18939
|
-
return true;
|
|
18940
|
-
return false;
|
|
18941
|
-
}
|
|
18942
|
-
var Parser = class _Parser {
|
|
18904
|
+
exports2.BINARY_OPS = /* @__PURE__ */ new Set(["||", "&&", "==", "!=", "<", "<=", ">", ">=", "is", "+", "-", "*", "/", "%"]);
|
|
18905
|
+
var ParserBase = class _ParserBase {
|
|
18943
18906
|
constructor(tokens, source, filePath) {
|
|
18944
18907
|
this.pos = 0;
|
|
18945
18908
|
this.inLibraryMode = false;
|
|
@@ -18950,7 +18913,7 @@ var require_parser = __commonJS({
|
|
|
18950
18913
|
this.filePath = filePath;
|
|
18951
18914
|
}
|
|
18952
18915
|
// -------------------------------------------------------------------------
|
|
18953
|
-
//
|
|
18916
|
+
// Token navigation
|
|
18954
18917
|
// -------------------------------------------------------------------------
|
|
18955
18918
|
peek(offset = 0) {
|
|
18956
18919
|
const idx = this.pos + offset;
|
|
@@ -19005,14 +18968,12 @@ var require_parser = __commonJS({
|
|
|
19005
18968
|
}
|
|
19006
18969
|
return { kind: "eof", value: "", line: span.line, col: span.col };
|
|
19007
18970
|
}
|
|
18971
|
+
checkIdent(value) {
|
|
18972
|
+
return this.check("ident") && this.peek().value === value;
|
|
18973
|
+
}
|
|
19008
18974
|
// -------------------------------------------------------------------------
|
|
19009
18975
|
// Error Recovery
|
|
19010
18976
|
// -------------------------------------------------------------------------
|
|
19011
|
-
/**
|
|
19012
|
-
* Synchronize to the next top-level declaration boundary after a parse error.
|
|
19013
|
-
* Skips tokens until we find a keyword that starts a top-level declaration,
|
|
19014
|
-
* or a `}` (end of a block), or EOF.
|
|
19015
|
-
*/
|
|
19016
18977
|
syncToNextDecl() {
|
|
19017
18978
|
const TOP_LEVEL_KEYWORDS = /* @__PURE__ */ new Set([
|
|
19018
18979
|
"fn",
|
|
@@ -19042,10 +19003,6 @@ var require_parser = __commonJS({
|
|
|
19042
19003
|
this.advance();
|
|
19043
19004
|
}
|
|
19044
19005
|
}
|
|
19045
|
-
/**
|
|
19046
|
-
* Synchronize to the next statement boundary inside a block after a parse error.
|
|
19047
|
-
* Skips tokens until we reach `;`, `}`, or EOF.
|
|
19048
|
-
*/
|
|
19049
19006
|
syncToNextStmt() {
|
|
19050
19007
|
while (!this.check("eof")) {
|
|
19051
19008
|
const kind = this.peek().kind;
|
|
@@ -19060,215 +19017,230 @@ var require_parser = __commonJS({
|
|
|
19060
19017
|
}
|
|
19061
19018
|
}
|
|
19062
19019
|
// -------------------------------------------------------------------------
|
|
19063
|
-
//
|
|
19020
|
+
// Sub-parser helper (used by string interpolation)
|
|
19064
19021
|
// -------------------------------------------------------------------------
|
|
19065
|
-
|
|
19066
|
-
|
|
19067
|
-
|
|
19068
|
-
|
|
19069
|
-
|
|
19070
|
-
|
|
19071
|
-
|
|
19072
|
-
|
|
19073
|
-
|
|
19074
|
-
|
|
19075
|
-
|
|
19076
|
-
|
|
19077
|
-
|
|
19022
|
+
makeSubParser(source) {
|
|
19023
|
+
const tokens = new lexer_1.Lexer(source, this.filePath).tokenize();
|
|
19024
|
+
return new _ParserBase(tokens, source, this.filePath);
|
|
19025
|
+
}
|
|
19026
|
+
};
|
|
19027
|
+
exports2.ParserBase = ParserBase;
|
|
19028
|
+
}
|
|
19029
|
+
});
|
|
19030
|
+
|
|
19031
|
+
// ../../dist/src/parser/type-parser.js
|
|
19032
|
+
var require_type_parser = __commonJS({
|
|
19033
|
+
"../../dist/src/parser/type-parser.js"(exports2) {
|
|
19034
|
+
"use strict";
|
|
19035
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
19036
|
+
exports2.TypeParser = void 0;
|
|
19037
|
+
var utils_1 = require_utils();
|
|
19038
|
+
var TypeParser = class extends utils_1.ParserBase {
|
|
19039
|
+
// -------------------------------------------------------------------------
|
|
19040
|
+
// Type Parsing
|
|
19041
|
+
// -------------------------------------------------------------------------
|
|
19042
|
+
parseType() {
|
|
19043
|
+
const token = this.peek();
|
|
19044
|
+
let type;
|
|
19045
|
+
if (token.kind === "(") {
|
|
19046
|
+
const saved = this.pos;
|
|
19078
19047
|
this.advance();
|
|
19079
|
-
const
|
|
19080
|
-
|
|
19081
|
-
|
|
19048
|
+
const elements = [];
|
|
19049
|
+
if (!this.check(")")) {
|
|
19050
|
+
do {
|
|
19051
|
+
elements.push(this.parseType());
|
|
19052
|
+
} while (this.match(","));
|
|
19053
|
+
}
|
|
19054
|
+
this.expect(")");
|
|
19055
|
+
if (this.check("->")) {
|
|
19056
|
+
this.pos = saved;
|
|
19057
|
+
return this.parseFunctionType();
|
|
19058
|
+
}
|
|
19059
|
+
return { kind: "tuple", elements };
|
|
19082
19060
|
}
|
|
19083
|
-
if (
|
|
19061
|
+
if (token.kind === "float") {
|
|
19084
19062
|
this.advance();
|
|
19085
|
-
const
|
|
19086
|
-
|
|
19087
|
-
|
|
19088
|
-
|
|
19063
|
+
const filePart = this.filePath ? `${this.filePath}:` : "";
|
|
19064
|
+
this.warnings.push(`[DeprecatedType] ${filePart}line ${token.line}, col ${token.col}: 'float' is deprecated, use 'fixed' instead (\xD710000 fixed-point)`);
|
|
19065
|
+
type = { kind: "named", name: "float" };
|
|
19066
|
+
} else if (token.kind === "int" || token.kind === "bool" || token.kind === "fixed" || token.kind === "string" || token.kind === "void" || token.kind === "BlockPos") {
|
|
19067
|
+
this.advance();
|
|
19068
|
+
type = { kind: "named", name: token.kind };
|
|
19069
|
+
} else if (token.kind === "ident") {
|
|
19070
|
+
this.advance();
|
|
19071
|
+
if (token.value === "selector" && this.check("<")) {
|
|
19072
|
+
this.advance();
|
|
19073
|
+
const entityType = this.expect("ident").value;
|
|
19074
|
+
this.expect(">");
|
|
19075
|
+
type = { kind: "selector", entityType };
|
|
19076
|
+
} else if (token.value === "selector") {
|
|
19077
|
+
type = { kind: "selector" };
|
|
19078
|
+
} else if (token.value === "Option" && this.check("<")) {
|
|
19079
|
+
this.advance();
|
|
19080
|
+
const inner = this.parseType();
|
|
19081
|
+
this.expect(">");
|
|
19082
|
+
type = { kind: "option", inner };
|
|
19083
|
+
} else if (token.value === "double" || token.value === "byte" || token.value === "short" || token.value === "long" || token.value === "format_string") {
|
|
19084
|
+
type = { kind: "named", name: token.value };
|
|
19089
19085
|
} else {
|
|
19090
|
-
|
|
19086
|
+
type = { kind: "struct", name: token.value };
|
|
19091
19087
|
}
|
|
19092
|
-
|
|
19088
|
+
} else {
|
|
19089
|
+
this.error(`Expected type, got '${token.value || token.kind}'. Valid types: int, float, bool, string, void, or a struct/enum name`);
|
|
19093
19090
|
}
|
|
19094
|
-
while (
|
|
19095
|
-
|
|
19096
|
-
|
|
19097
|
-
|
|
19098
|
-
|
|
19099
|
-
|
|
19100
|
-
|
|
19101
|
-
|
|
19102
|
-
|
|
19103
|
-
|
|
19104
|
-
|
|
19105
|
-
|
|
19106
|
-
|
|
19107
|
-
|
|
19108
|
-
|
|
19109
|
-
|
|
19110
|
-
|
|
19111
|
-
|
|
19112
|
-
|
|
19113
|
-
|
|
19114
|
-
|
|
19115
|
-
|
|
19116
|
-
|
|
19117
|
-
|
|
19118
|
-
|
|
19119
|
-
|
|
19120
|
-
|
|
19121
|
-
|
|
19122
|
-
|
|
19123
|
-
|
|
19124
|
-
|
|
19125
|
-
|
|
19126
|
-
|
|
19127
|
-
|
|
19128
|
-
|
|
19129
|
-
} else if (this.check("export")) {
|
|
19130
|
-
declarations.push(this.parseExportedFnDecl());
|
|
19131
|
-
} else if (this.check("import") || this.check("ident") && this.peek().value === "import") {
|
|
19132
|
-
this.advance();
|
|
19133
|
-
const importToken = this.peek();
|
|
19134
|
-
const modName = this.expect("ident").value;
|
|
19135
|
-
if (this.check("::")) {
|
|
19136
|
-
this.advance();
|
|
19137
|
-
let symbol;
|
|
19138
|
-
if (this.check("*")) {
|
|
19139
|
-
this.advance();
|
|
19140
|
-
symbol = "*";
|
|
19141
|
-
} else {
|
|
19142
|
-
symbol = this.expect("ident").value;
|
|
19143
|
-
}
|
|
19144
|
-
this.match(";");
|
|
19145
|
-
imports.push(this.withLoc({ moduleName: modName, symbol }, importToken));
|
|
19146
|
-
} else {
|
|
19147
|
-
this.match(";");
|
|
19148
|
-
imports.push(this.withLoc({ moduleName: modName, symbol: void 0 }, importToken));
|
|
19149
|
-
}
|
|
19150
|
-
} else {
|
|
19151
|
-
declarations.push(this.parseFnDecl());
|
|
19152
|
-
}
|
|
19153
|
-
} catch (err) {
|
|
19154
|
-
if (err instanceof diagnostics_1.DiagnosticError) {
|
|
19155
|
-
this.parseErrors.push(err);
|
|
19156
|
-
this.syncToNextDecl();
|
|
19157
|
-
} else {
|
|
19158
|
-
throw err;
|
|
19159
|
-
}
|
|
19091
|
+
while (this.match("[")) {
|
|
19092
|
+
this.expect("]");
|
|
19093
|
+
type = { kind: "array", elem: type };
|
|
19094
|
+
}
|
|
19095
|
+
return type;
|
|
19096
|
+
}
|
|
19097
|
+
parseFunctionType() {
|
|
19098
|
+
this.expect("(");
|
|
19099
|
+
const params = [];
|
|
19100
|
+
if (!this.check(")")) {
|
|
19101
|
+
do {
|
|
19102
|
+
params.push(this.parseType());
|
|
19103
|
+
} while (this.match(","));
|
|
19104
|
+
}
|
|
19105
|
+
this.expect(")");
|
|
19106
|
+
this.expect("->");
|
|
19107
|
+
const returnType = this.parseType();
|
|
19108
|
+
return { kind: "function_type", params, return: returnType };
|
|
19109
|
+
}
|
|
19110
|
+
/**
|
|
19111
|
+
* Try to parse `<Type, ...>` as explicit generic type arguments.
|
|
19112
|
+
* Returns the parsed type list if successful, null if this looks like a comparison.
|
|
19113
|
+
* Does NOT consume any tokens if it returns null.
|
|
19114
|
+
*/
|
|
19115
|
+
tryParseTypeArgs() {
|
|
19116
|
+
const saved = this.pos;
|
|
19117
|
+
this.advance();
|
|
19118
|
+
const typeArgs = [];
|
|
19119
|
+
try {
|
|
19120
|
+
do {
|
|
19121
|
+
typeArgs.push(this.parseType());
|
|
19122
|
+
} while (this.match(","));
|
|
19123
|
+
if (!this.check(">")) {
|
|
19124
|
+
this.pos = saved;
|
|
19125
|
+
return null;
|
|
19160
19126
|
}
|
|
19127
|
+
this.advance();
|
|
19128
|
+
return typeArgs;
|
|
19129
|
+
} catch {
|
|
19130
|
+
this.pos = saved;
|
|
19131
|
+
return null;
|
|
19161
19132
|
}
|
|
19162
|
-
return { namespace, moduleName, globals, declarations, structs, implBlocks, enums, consts, imports, interfaces, isLibrary };
|
|
19163
19133
|
}
|
|
19164
19134
|
// -------------------------------------------------------------------------
|
|
19165
|
-
//
|
|
19135
|
+
// Lambda lookahead helpers (needed by expr-parser)
|
|
19166
19136
|
// -------------------------------------------------------------------------
|
|
19167
|
-
|
|
19168
|
-
|
|
19169
|
-
|
|
19170
|
-
|
|
19171
|
-
this.
|
|
19172
|
-
|
|
19173
|
-
|
|
19174
|
-
|
|
19175
|
-
|
|
19176
|
-
|
|
19177
|
-
|
|
19178
|
-
|
|
19179
|
-
|
|
19180
|
-
|
|
19181
|
-
|
|
19182
|
-
|
|
19183
|
-
|
|
19184
|
-
|
|
19185
|
-
|
|
19186
|
-
|
|
19187
|
-
|
|
19188
|
-
let nextValue = 0;
|
|
19189
|
-
while (!this.check("}") && !this.check("eof")) {
|
|
19190
|
-
const variantToken = this.expect("ident");
|
|
19191
|
-
const variant = { name: variantToken.value };
|
|
19192
|
-
if (this.check("(")) {
|
|
19193
|
-
this.advance();
|
|
19194
|
-
const fields = [];
|
|
19195
|
-
while (!this.check(")") && !this.check("eof")) {
|
|
19196
|
-
const fieldName = this.expect("ident").value;
|
|
19197
|
-
this.expect(":");
|
|
19198
|
-
const fieldType = this.parseType();
|
|
19199
|
-
fields.push({ name: fieldName, type: fieldType });
|
|
19200
|
-
if (!this.match(","))
|
|
19201
|
-
break;
|
|
19137
|
+
isLambdaStart() {
|
|
19138
|
+
if (!this.check("("))
|
|
19139
|
+
return false;
|
|
19140
|
+
let offset = 1;
|
|
19141
|
+
if (this.peek(offset).kind !== ")") {
|
|
19142
|
+
while (true) {
|
|
19143
|
+
if (this.peek(offset).kind !== "ident") {
|
|
19144
|
+
return false;
|
|
19145
|
+
}
|
|
19146
|
+
offset += 1;
|
|
19147
|
+
if (this.peek(offset).kind === ":") {
|
|
19148
|
+
offset += 1;
|
|
19149
|
+
const consumed = this.typeTokenLength(offset);
|
|
19150
|
+
if (consumed === 0) {
|
|
19151
|
+
return false;
|
|
19152
|
+
}
|
|
19153
|
+
offset += consumed;
|
|
19154
|
+
}
|
|
19155
|
+
if (this.peek(offset).kind === ",") {
|
|
19156
|
+
offset += 1;
|
|
19157
|
+
continue;
|
|
19202
19158
|
}
|
|
19203
|
-
this.expect(")");
|
|
19204
|
-
variant.fields = fields;
|
|
19205
|
-
}
|
|
19206
|
-
if (this.match("=")) {
|
|
19207
|
-
const valueToken = this.expect("int_lit");
|
|
19208
|
-
variant.value = parseInt(valueToken.value, 10);
|
|
19209
|
-
nextValue = variant.value + 1;
|
|
19210
|
-
} else {
|
|
19211
|
-
variant.value = nextValue++;
|
|
19212
|
-
}
|
|
19213
|
-
variants.push(variant);
|
|
19214
|
-
if (!this.match(",")) {
|
|
19215
19159
|
break;
|
|
19216
19160
|
}
|
|
19217
19161
|
}
|
|
19218
|
-
this.
|
|
19219
|
-
|
|
19220
|
-
}
|
|
19221
|
-
parseImplBlock() {
|
|
19222
|
-
const implToken = this.expect("impl");
|
|
19223
|
-
let traitName;
|
|
19224
|
-
let typeName;
|
|
19225
|
-
const firstName = this.expect("ident").value;
|
|
19226
|
-
if (this.match("for")) {
|
|
19227
|
-
traitName = firstName;
|
|
19228
|
-
typeName = this.expect("ident").value;
|
|
19229
|
-
} else {
|
|
19230
|
-
typeName = firstName;
|
|
19162
|
+
if (this.peek(offset).kind !== ")") {
|
|
19163
|
+
return false;
|
|
19231
19164
|
}
|
|
19232
|
-
|
|
19233
|
-
|
|
19234
|
-
|
|
19235
|
-
methods.push(this.parseFnDecl(typeName));
|
|
19165
|
+
offset += 1;
|
|
19166
|
+
if (this.peek(offset).kind === "=>") {
|
|
19167
|
+
return true;
|
|
19236
19168
|
}
|
|
19237
|
-
this.
|
|
19238
|
-
|
|
19169
|
+
if (this.peek(offset).kind === "->") {
|
|
19170
|
+
offset += 1;
|
|
19171
|
+
const consumed = this.typeTokenLength(offset);
|
|
19172
|
+
if (consumed === 0) {
|
|
19173
|
+
return false;
|
|
19174
|
+
}
|
|
19175
|
+
offset += consumed;
|
|
19176
|
+
return this.peek(offset).kind === "=>";
|
|
19177
|
+
}
|
|
19178
|
+
return false;
|
|
19239
19179
|
}
|
|
19240
|
-
|
|
19241
|
-
|
|
19242
|
-
|
|
19243
|
-
|
|
19244
|
-
|
|
19245
|
-
|
|
19246
|
-
|
|
19247
|
-
|
|
19248
|
-
|
|
19249
|
-
|
|
19250
|
-
|
|
19251
|
-
|
|
19252
|
-
|
|
19253
|
-
|
|
19254
|
-
|
|
19255
|
-
|
|
19256
|
-
|
|
19257
|
-
const params = this.parseInterfaceParams();
|
|
19258
|
-
this.expect(")");
|
|
19259
|
-
let returnType;
|
|
19260
|
-
if (this.match(":")) {
|
|
19261
|
-
returnType = this.parseType();
|
|
19180
|
+
typeTokenLength(offset) {
|
|
19181
|
+
const token = this.peek(offset);
|
|
19182
|
+
if (token.kind === "(") {
|
|
19183
|
+
let inner = offset + 1;
|
|
19184
|
+
if (this.peek(inner).kind !== ")") {
|
|
19185
|
+
while (true) {
|
|
19186
|
+
const consumed = this.typeTokenLength(inner);
|
|
19187
|
+
if (consumed === 0) {
|
|
19188
|
+
return 0;
|
|
19189
|
+
}
|
|
19190
|
+
inner += consumed;
|
|
19191
|
+
if (this.peek(inner).kind === ",") {
|
|
19192
|
+
inner += 1;
|
|
19193
|
+
continue;
|
|
19194
|
+
}
|
|
19195
|
+
break;
|
|
19196
|
+
}
|
|
19262
19197
|
}
|
|
19263
|
-
|
|
19198
|
+
if (this.peek(inner).kind !== ")") {
|
|
19199
|
+
return 0;
|
|
19200
|
+
}
|
|
19201
|
+
inner += 1;
|
|
19202
|
+
if (this.peek(inner).kind !== "->") {
|
|
19203
|
+
return 0;
|
|
19204
|
+
}
|
|
19205
|
+
inner += 1;
|
|
19206
|
+
const returnLen = this.typeTokenLength(inner);
|
|
19207
|
+
return returnLen === 0 ? 0 : inner + returnLen - offset;
|
|
19264
19208
|
}
|
|
19265
|
-
|
|
19266
|
-
|
|
19209
|
+
const isNamedType = token.kind === "int" || token.kind === "bool" || token.kind === "float" || token.kind === "fixed" || token.kind === "string" || token.kind === "void" || token.kind === "BlockPos" || token.kind === "ident";
|
|
19210
|
+
if (!isNamedType) {
|
|
19211
|
+
return 0;
|
|
19212
|
+
}
|
|
19213
|
+
let length = 1;
|
|
19214
|
+
while (this.peek(offset + length).kind === "[" && this.peek(offset + length + 1).kind === "]") {
|
|
19215
|
+
length += 2;
|
|
19216
|
+
}
|
|
19217
|
+
return length;
|
|
19218
|
+
}
|
|
19219
|
+
// -------------------------------------------------------------------------
|
|
19220
|
+
// Params parsing (used by decl-parser)
|
|
19221
|
+
// -------------------------------------------------------------------------
|
|
19222
|
+
parseParams(implTypeName) {
|
|
19223
|
+
const params = [];
|
|
19224
|
+
if (!this.check(")")) {
|
|
19225
|
+
do {
|
|
19226
|
+
const paramToken = this.expect("ident");
|
|
19227
|
+
const name = paramToken.value;
|
|
19228
|
+
let type;
|
|
19229
|
+
if (implTypeName && params.length === 0 && name === "self" && !this.check(":")) {
|
|
19230
|
+
type = { kind: "struct", name: implTypeName };
|
|
19231
|
+
} else {
|
|
19232
|
+
this.expect(":");
|
|
19233
|
+
type = this.parseType();
|
|
19234
|
+
}
|
|
19235
|
+
let defaultValue;
|
|
19236
|
+
if (this.match("=")) {
|
|
19237
|
+
defaultValue = this.parseExpr();
|
|
19238
|
+
}
|
|
19239
|
+
params.push(this.withLoc({ name, type, default: defaultValue }, paramToken));
|
|
19240
|
+
} while (this.match(","));
|
|
19241
|
+
}
|
|
19242
|
+
return params;
|
|
19267
19243
|
}
|
|
19268
|
-
/**
|
|
19269
|
-
* Parse interface method params — like parseParams but allows bare `self`
|
|
19270
|
-
* (no `:` required for the first param named 'self').
|
|
19271
|
-
*/
|
|
19272
19244
|
parseInterfaceParams() {
|
|
19273
19245
|
const params = [];
|
|
19274
19246
|
if (!this.check(")")) {
|
|
@@ -19287,1731 +19259,1757 @@ var require_parser = __commonJS({
|
|
|
19287
19259
|
}
|
|
19288
19260
|
return params;
|
|
19289
19261
|
}
|
|
19290
|
-
|
|
19291
|
-
|
|
19292
|
-
|
|
19293
|
-
|
|
19294
|
-
|
|
19295
|
-
|
|
19296
|
-
|
|
19297
|
-
|
|
19298
|
-
|
|
19299
|
-
|
|
19300
|
-
|
|
19301
|
-
|
|
19302
|
-
|
|
19303
|
-
|
|
19304
|
-
|
|
19305
|
-
|
|
19306
|
-
|
|
19307
|
-
|
|
19308
|
-
|
|
19309
|
-
|
|
19310
|
-
|
|
19311
|
-
|
|
19312
|
-
|
|
19313
|
-
|
|
19314
|
-
|
|
19315
|
-
|
|
19316
|
-
|
|
19262
|
+
};
|
|
19263
|
+
exports2.TypeParser = TypeParser;
|
|
19264
|
+
}
|
|
19265
|
+
});
|
|
19266
|
+
|
|
19267
|
+
// ../../dist/src/parser/expr-parser.js
|
|
19268
|
+
var require_expr_parser = __commonJS({
|
|
19269
|
+
"../../dist/src/parser/expr-parser.js"(exports2) {
|
|
19270
|
+
"use strict";
|
|
19271
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
19272
|
+
exports2.ExprParser = void 0;
|
|
19273
|
+
var lexer_1 = require_lexer();
|
|
19274
|
+
var type_parser_1 = require_type_parser();
|
|
19275
|
+
var utils_1 = require_utils();
|
|
19276
|
+
var ENTITY_TYPE_NAMES = /* @__PURE__ */ new Set([
|
|
19277
|
+
"entity",
|
|
19278
|
+
"Player",
|
|
19279
|
+
"Mob",
|
|
19280
|
+
"HostileMob",
|
|
19281
|
+
"PassiveMob",
|
|
19282
|
+
"Zombie",
|
|
19283
|
+
"Skeleton",
|
|
19284
|
+
"Creeper",
|
|
19285
|
+
"Spider",
|
|
19286
|
+
"Enderman",
|
|
19287
|
+
"Blaze",
|
|
19288
|
+
"Witch",
|
|
19289
|
+
"Slime",
|
|
19290
|
+
"ZombieVillager",
|
|
19291
|
+
"Husk",
|
|
19292
|
+
"Drowned",
|
|
19293
|
+
"Stray",
|
|
19294
|
+
"WitherSkeleton",
|
|
19295
|
+
"CaveSpider",
|
|
19296
|
+
"Pig",
|
|
19297
|
+
"Cow",
|
|
19298
|
+
"Sheep",
|
|
19299
|
+
"Chicken",
|
|
19300
|
+
"Villager",
|
|
19301
|
+
"WanderingTrader",
|
|
19302
|
+
"ArmorStand",
|
|
19303
|
+
"Item",
|
|
19304
|
+
"Arrow"
|
|
19305
|
+
]);
|
|
19306
|
+
function computeIsSingle(raw) {
|
|
19307
|
+
if (/^@[spr](\[|$)/.test(raw))
|
|
19308
|
+
return true;
|
|
19309
|
+
if (/[\[,\s]limit=1[,\]\s]/.test(raw))
|
|
19310
|
+
return true;
|
|
19311
|
+
return false;
|
|
19312
|
+
}
|
|
19313
|
+
var ExprParser = class extends type_parser_1.TypeParser {
|
|
19317
19314
|
// -------------------------------------------------------------------------
|
|
19318
|
-
//
|
|
19315
|
+
// Expressions (Precedence Climbing)
|
|
19319
19316
|
// -------------------------------------------------------------------------
|
|
19320
|
-
|
|
19321
|
-
|
|
19322
|
-
this.expect("export");
|
|
19323
|
-
const fn = this.parseFnDecl();
|
|
19324
|
-
fn.isExported = true;
|
|
19325
|
-
return fn;
|
|
19317
|
+
parseExpr() {
|
|
19318
|
+
return this.parseAssignment();
|
|
19326
19319
|
}
|
|
19327
|
-
|
|
19328
|
-
const
|
|
19329
|
-
const
|
|
19330
|
-
|
|
19331
|
-
|
|
19332
|
-
if (
|
|
19333
|
-
|
|
19334
|
-
return
|
|
19320
|
+
parseAssignment() {
|
|
19321
|
+
const left = this.parseBinaryExpr(1);
|
|
19322
|
+
const token = this.peek();
|
|
19323
|
+
if (token.kind === "=" || token.kind === "+=" || token.kind === "-=" || token.kind === "*=" || token.kind === "/=" || token.kind === "%=") {
|
|
19324
|
+
const op = this.advance().kind;
|
|
19325
|
+
if (left.kind === "ident") {
|
|
19326
|
+
const value = this.parseAssignment();
|
|
19327
|
+
return this.withLoc({ kind: "assign", target: left.name, op, value }, this.getLocToken(left) ?? token);
|
|
19328
|
+
}
|
|
19329
|
+
if (left.kind === "member") {
|
|
19330
|
+
const value = this.parseAssignment();
|
|
19331
|
+
return this.withLoc({ kind: "member_assign", obj: left.obj, field: left.field, op, value }, this.getLocToken(left) ?? token);
|
|
19332
|
+
}
|
|
19333
|
+
if (left.kind === "index") {
|
|
19334
|
+
const value = this.parseAssignment();
|
|
19335
|
+
return this.withLoc({ kind: "index_assign", obj: left.obj, index: left.index, op, value }, this.getLocToken(left) ?? token);
|
|
19335
19336
|
}
|
|
19336
|
-
return true;
|
|
19337
|
-
});
|
|
19338
|
-
const fnToken = this.expect("fn");
|
|
19339
|
-
const name = this.expect("ident").value;
|
|
19340
|
-
let typeParams;
|
|
19341
|
-
if (this.check("<")) {
|
|
19342
|
-
this.advance();
|
|
19343
|
-
typeParams = [];
|
|
19344
|
-
do {
|
|
19345
|
-
typeParams.push(this.expect("ident").value);
|
|
19346
|
-
} while (this.match(","));
|
|
19347
|
-
this.expect(">");
|
|
19348
19337
|
}
|
|
19349
|
-
|
|
19350
|
-
|
|
19351
|
-
|
|
19352
|
-
let
|
|
19353
|
-
|
|
19354
|
-
|
|
19338
|
+
return left;
|
|
19339
|
+
}
|
|
19340
|
+
parseBinaryExpr(minPrec) {
|
|
19341
|
+
let left = this.parseUnaryExpr();
|
|
19342
|
+
while (true) {
|
|
19343
|
+
const op = this.peek().kind;
|
|
19344
|
+
if (!utils_1.BINARY_OPS.has(op))
|
|
19345
|
+
break;
|
|
19346
|
+
const prec = utils_1.PRECEDENCE[op];
|
|
19347
|
+
if (prec < minPrec)
|
|
19348
|
+
break;
|
|
19349
|
+
const opToken = this.advance();
|
|
19350
|
+
if (op === "is") {
|
|
19351
|
+
const entityType = this.parseEntityTypeName();
|
|
19352
|
+
left = this.withLoc({ kind: "is_check", expr: left, entityType }, this.getLocToken(left) ?? opToken);
|
|
19353
|
+
continue;
|
|
19354
|
+
}
|
|
19355
|
+
const right = this.parseBinaryExpr(prec + 1);
|
|
19356
|
+
left = this.withLoc({ kind: "binary", op, left, right }, this.getLocToken(left) ?? opToken);
|
|
19355
19357
|
}
|
|
19356
|
-
|
|
19357
|
-
const closingBraceLine = this.tokens[this.pos - 1]?.line;
|
|
19358
|
-
const fn = this.withLoc({
|
|
19359
|
-
name,
|
|
19360
|
-
typeParams,
|
|
19361
|
-
params,
|
|
19362
|
-
returnType,
|
|
19363
|
-
decorators: filteredDecorators,
|
|
19364
|
-
body,
|
|
19365
|
-
isLibraryFn: this.inLibraryMode || void 0,
|
|
19366
|
-
isExported,
|
|
19367
|
-
watchObjective
|
|
19368
|
-
}, fnToken);
|
|
19369
|
-
if (fn.span && closingBraceLine)
|
|
19370
|
-
fn.span.endLine = closingBraceLine;
|
|
19371
|
-
return fn;
|
|
19358
|
+
return left;
|
|
19372
19359
|
}
|
|
19373
|
-
|
|
19374
|
-
|
|
19375
|
-
|
|
19376
|
-
|
|
19377
|
-
|
|
19378
|
-
let depth = 1;
|
|
19379
|
-
while (!this.check("eof") && depth > 0) {
|
|
19380
|
-
const t = this.advance();
|
|
19381
|
-
if (t.kind === "(")
|
|
19382
|
-
depth++;
|
|
19383
|
-
else if (t.kind === ")")
|
|
19384
|
-
depth--;
|
|
19360
|
+
parseUnaryExpr() {
|
|
19361
|
+
if (this.match("!")) {
|
|
19362
|
+
const bangToken = this.tokens[this.pos - 1];
|
|
19363
|
+
const operand = this.parseUnaryExpr();
|
|
19364
|
+
return this.withLoc({ kind: "unary", op: "!", operand }, bangToken);
|
|
19385
19365
|
}
|
|
19386
|
-
if (this.
|
|
19387
|
-
this.
|
|
19366
|
+
if (this.check("-") && !this.isSubtraction()) {
|
|
19367
|
+
const minusToken = this.advance();
|
|
19368
|
+
const operand = this.parseUnaryExpr();
|
|
19369
|
+
return this.withLoc({ kind: "unary", op: "-", operand }, minusToken);
|
|
19388
19370
|
}
|
|
19389
|
-
this.
|
|
19371
|
+
return this.parsePostfixExpr();
|
|
19390
19372
|
}
|
|
19391
|
-
|
|
19392
|
-
const
|
|
19393
|
-
|
|
19394
|
-
|
|
19395
|
-
const decorator = this.parseDecoratorValue(token.value);
|
|
19396
|
-
decorators.push(decorator);
|
|
19373
|
+
parseEntityTypeName() {
|
|
19374
|
+
const token = this.expect("ident");
|
|
19375
|
+
if (ENTITY_TYPE_NAMES.has(token.value)) {
|
|
19376
|
+
return token.value;
|
|
19397
19377
|
}
|
|
19398
|
-
|
|
19378
|
+
this.error(`Unknown entity type '${token.value}'. Valid types: ${[...ENTITY_TYPE_NAMES].slice(0, 6).join(", ")}, ...`);
|
|
19399
19379
|
}
|
|
19400
|
-
|
|
19401
|
-
|
|
19402
|
-
|
|
19403
|
-
|
|
19404
|
-
|
|
19405
|
-
|
|
19406
|
-
|
|
19407
|
-
|
|
19408
|
-
|
|
19409
|
-
|
|
19410
|
-
|
|
19411
|
-
|
|
19412
|
-
|
|
19413
|
-
|
|
19414
|
-
|
|
19415
|
-
|
|
19416
|
-
|
|
19417
|
-
|
|
19418
|
-
return { name, args };
|
|
19419
|
-
}
|
|
19420
|
-
}
|
|
19421
|
-
if (name === "watch" || name === "on_trigger" || name === "on_advancement" || name === "on_craft" || name === "on_join_team") {
|
|
19422
|
-
const strMatch = argsStr.match(/^"([^"]*)"$/);
|
|
19423
|
-
if (strMatch) {
|
|
19424
|
-
if (name === "watch") {
|
|
19425
|
-
args.objective = strMatch[1];
|
|
19426
|
-
} else if (name === "on_trigger") {
|
|
19427
|
-
args.trigger = strMatch[1];
|
|
19428
|
-
} else if (name === "on_advancement") {
|
|
19429
|
-
args.advancement = strMatch[1];
|
|
19430
|
-
} else if (name === "on_craft") {
|
|
19431
|
-
args.item = strMatch[1];
|
|
19432
|
-
} else if (name === "on_join_team") {
|
|
19433
|
-
args.team = strMatch[1];
|
|
19380
|
+
isSubtraction() {
|
|
19381
|
+
if (this.pos === 0)
|
|
19382
|
+
return false;
|
|
19383
|
+
const prev = this.tokens[this.pos - 1];
|
|
19384
|
+
return ["int_lit", "float_lit", "ident", ")", "]"].includes(prev.kind);
|
|
19385
|
+
}
|
|
19386
|
+
parsePostfixExpr() {
|
|
19387
|
+
let expr = this.parsePrimaryExpr();
|
|
19388
|
+
while (true) {
|
|
19389
|
+
if (expr.kind === "ident" && this.check("<")) {
|
|
19390
|
+
const typeArgs = this.tryParseTypeArgs();
|
|
19391
|
+
if (typeArgs !== null && this.check("(")) {
|
|
19392
|
+
const openParenToken = this.peek();
|
|
19393
|
+
this.advance();
|
|
19394
|
+
const args = this.parseArgs();
|
|
19395
|
+
this.expect(")");
|
|
19396
|
+
expr = this.withLoc({ kind: "call", fn: expr.name, args, typeArgs }, this.getLocToken(expr) ?? openParenToken);
|
|
19397
|
+
continue;
|
|
19434
19398
|
}
|
|
19435
|
-
return { name, args };
|
|
19436
|
-
}
|
|
19437
|
-
}
|
|
19438
|
-
if (name === "config") {
|
|
19439
|
-
const configMatch = argsStr.match(/^"([^"]+)"\s*,\s*default\s*:\s*(-?\d+(?:\.\d+)?)$/);
|
|
19440
|
-
if (configMatch) {
|
|
19441
|
-
return { name, args: { configKey: configMatch[1], configDefault: parseFloat(configMatch[2]) } };
|
|
19442
|
-
}
|
|
19443
|
-
const keyOnlyMatch = argsStr.match(/^"([^"]+)"$/);
|
|
19444
|
-
if (keyOnlyMatch) {
|
|
19445
|
-
return { name, args: { configKey: keyOnlyMatch[1] } };
|
|
19446
|
-
}
|
|
19447
|
-
this.error(`Invalid @config syntax. Expected: @config("key", default: value) or @config("key")`);
|
|
19448
|
-
}
|
|
19449
|
-
if (name === "deprecated") {
|
|
19450
|
-
const strMatch = argsStr.match(/^"([^"]*)"$/);
|
|
19451
|
-
if (strMatch) {
|
|
19452
|
-
return { name, args: { message: strMatch[1] } };
|
|
19453
19399
|
}
|
|
19454
|
-
|
|
19455
|
-
|
|
19456
|
-
|
|
19457
|
-
|
|
19458
|
-
|
|
19459
|
-
|
|
19460
|
-
|
|
19461
|
-
|
|
19462
|
-
|
|
19463
|
-
|
|
19464
|
-
|
|
19465
|
-
|
|
19466
|
-
|
|
19467
|
-
|
|
19468
|
-
|
|
19469
|
-
|
|
19470
|
-
|
|
19471
|
-
|
|
19472
|
-
|
|
19473
|
-
|
|
19400
|
+
if (this.match("(")) {
|
|
19401
|
+
const openParenToken = this.tokens[this.pos - 1];
|
|
19402
|
+
if (expr.kind === "ident") {
|
|
19403
|
+
const args2 = this.parseArgs();
|
|
19404
|
+
this.expect(")");
|
|
19405
|
+
expr = this.withLoc({ kind: "call", fn: expr.name, args: args2 }, this.getLocToken(expr) ?? openParenToken);
|
|
19406
|
+
continue;
|
|
19407
|
+
}
|
|
19408
|
+
if (expr.kind === "member") {
|
|
19409
|
+
if (expr.field === "unwrap_or") {
|
|
19410
|
+
const defaultExpr = this.parseExpr();
|
|
19411
|
+
this.expect(")");
|
|
19412
|
+
expr = this.withLoc({ kind: "unwrap_or", opt: expr.obj, default_: defaultExpr }, this.getLocToken(expr) ?? openParenToken);
|
|
19413
|
+
continue;
|
|
19414
|
+
}
|
|
19415
|
+
const methodMap = {
|
|
19416
|
+
"tag": "__entity_tag",
|
|
19417
|
+
"untag": "__entity_untag",
|
|
19418
|
+
"has_tag": "__entity_has_tag",
|
|
19419
|
+
"push": "__array_push",
|
|
19420
|
+
"pop": "__array_pop",
|
|
19421
|
+
"add": "set_add",
|
|
19422
|
+
"contains": "set_contains",
|
|
19423
|
+
"remove": "set_remove",
|
|
19424
|
+
"clear": "set_clear"
|
|
19425
|
+
};
|
|
19426
|
+
const internalFn = methodMap[expr.field];
|
|
19427
|
+
if (internalFn) {
|
|
19428
|
+
const args3 = this.parseArgs();
|
|
19429
|
+
this.expect(")");
|
|
19430
|
+
expr = this.withLoc({ kind: "call", fn: internalFn, args: [expr.obj, ...args3] }, this.getLocToken(expr) ?? openParenToken);
|
|
19431
|
+
continue;
|
|
19474
19432
|
}
|
|
19433
|
+
const args2 = this.parseArgs();
|
|
19434
|
+
this.expect(")");
|
|
19435
|
+
expr = this.withLoc({ kind: "call", fn: expr.field, args: [expr.obj, ...args2] }, this.getLocToken(expr) ?? openParenToken);
|
|
19436
|
+
continue;
|
|
19475
19437
|
}
|
|
19438
|
+
const args = this.parseArgs();
|
|
19439
|
+
this.expect(")");
|
|
19440
|
+
expr = this.withLoc({ kind: "invoke", callee: expr, args }, this.getLocToken(expr) ?? openParenToken);
|
|
19441
|
+
continue;
|
|
19476
19442
|
}
|
|
19477
|
-
|
|
19478
|
-
|
|
19479
|
-
|
|
19480
|
-
|
|
19481
|
-
|
|
19482
|
-
|
|
19483
|
-
|
|
19484
|
-
|
|
19485
|
-
|
|
19486
|
-
|
|
19487
|
-
}
|
|
19488
|
-
|
|
19489
|
-
|
|
19490
|
-
|
|
19491
|
-
|
|
19492
|
-
|
|
19493
|
-
} else if (key === "item") {
|
|
19494
|
-
args.item = val;
|
|
19495
|
-
} else if (key === "team") {
|
|
19496
|
-
args.team = val;
|
|
19497
|
-
} else if (key === "max") {
|
|
19498
|
-
args.max = parseInt(val, 10);
|
|
19443
|
+
if (this.match("[")) {
|
|
19444
|
+
const index = this.parseExpr();
|
|
19445
|
+
this.expect("]");
|
|
19446
|
+
expr = this.withLoc({ kind: "index", obj: expr, index }, this.getLocToken(expr) ?? this.tokens[this.pos - 1]);
|
|
19447
|
+
continue;
|
|
19448
|
+
}
|
|
19449
|
+
if (this.match(".")) {
|
|
19450
|
+
const field = this.expect("ident").value;
|
|
19451
|
+
expr = this.withLoc({ kind: "member", obj: expr, field }, this.getLocToken(expr) ?? this.tokens[this.pos - 1]);
|
|
19452
|
+
continue;
|
|
19453
|
+
}
|
|
19454
|
+
if (this.check("as") && this.isTypeCastAs()) {
|
|
19455
|
+
const asToken = this.advance();
|
|
19456
|
+
const targetType = this.parseType();
|
|
19457
|
+
expr = this.withLoc({ kind: "type_cast", expr, targetType }, this.getLocToken(expr) ?? asToken);
|
|
19458
|
+
continue;
|
|
19499
19459
|
}
|
|
19460
|
+
break;
|
|
19500
19461
|
}
|
|
19501
|
-
return
|
|
19462
|
+
return expr;
|
|
19502
19463
|
}
|
|
19503
|
-
|
|
19504
|
-
const
|
|
19505
|
-
if (!
|
|
19506
|
-
|
|
19507
|
-
|
|
19508
|
-
|
|
19509
|
-
|
|
19510
|
-
|
|
19511
|
-
|
|
19512
|
-
|
|
19513
|
-
this.expect(":");
|
|
19514
|
-
type = this.parseType();
|
|
19515
|
-
}
|
|
19516
|
-
let defaultValue;
|
|
19517
|
-
if (this.match("=")) {
|
|
19518
|
-
defaultValue = this.parseExpr();
|
|
19519
|
-
}
|
|
19520
|
-
params.push(this.withLoc({ name, type, default: defaultValue }, paramToken));
|
|
19521
|
-
} while (this.match(","));
|
|
19522
|
-
}
|
|
19523
|
-
return params;
|
|
19524
|
-
}
|
|
19525
|
-
parseType() {
|
|
19526
|
-
const token = this.peek();
|
|
19527
|
-
let type;
|
|
19528
|
-
if (token.kind === "(") {
|
|
19529
|
-
const saved = this.pos;
|
|
19530
|
-
this.advance();
|
|
19531
|
-
const elements = [];
|
|
19532
|
-
if (!this.check(")")) {
|
|
19533
|
-
do {
|
|
19534
|
-
elements.push(this.parseType());
|
|
19535
|
-
} while (this.match(","));
|
|
19536
|
-
}
|
|
19537
|
-
this.expect(")");
|
|
19538
|
-
if (this.check("->")) {
|
|
19539
|
-
this.pos = saved;
|
|
19540
|
-
return this.parseFunctionType();
|
|
19541
|
-
}
|
|
19542
|
-
return { kind: "tuple", elements };
|
|
19543
|
-
}
|
|
19544
|
-
if (token.kind === "float") {
|
|
19545
|
-
this.advance();
|
|
19546
|
-
const filePart = this.filePath ? `${this.filePath}:` : "";
|
|
19547
|
-
this.warnings.push(`[DeprecatedType] ${filePart}line ${token.line}, col ${token.col}: 'float' is deprecated, use 'fixed' instead (\xD710000 fixed-point)`);
|
|
19548
|
-
type = { kind: "named", name: "float" };
|
|
19549
|
-
} else if (token.kind === "int" || token.kind === "bool" || token.kind === "fixed" || token.kind === "string" || token.kind === "void" || token.kind === "BlockPos") {
|
|
19550
|
-
this.advance();
|
|
19551
|
-
type = { kind: "named", name: token.kind };
|
|
19552
|
-
} else if (token.kind === "ident") {
|
|
19553
|
-
this.advance();
|
|
19554
|
-
if (token.value === "selector" && this.check("<")) {
|
|
19555
|
-
this.advance();
|
|
19556
|
-
const entityType = this.expect("ident").value;
|
|
19557
|
-
this.expect(">");
|
|
19558
|
-
type = { kind: "selector", entityType };
|
|
19559
|
-
} else if (token.value === "selector") {
|
|
19560
|
-
type = { kind: "selector" };
|
|
19561
|
-
} else if (token.value === "Option" && this.check("<")) {
|
|
19562
|
-
this.advance();
|
|
19563
|
-
const inner = this.parseType();
|
|
19564
|
-
this.expect(">");
|
|
19565
|
-
type = { kind: "option", inner };
|
|
19566
|
-
} else if (token.value === "double" || token.value === "byte" || token.value === "short" || token.value === "long" || token.value === "format_string") {
|
|
19567
|
-
type = { kind: "named", name: token.value };
|
|
19568
|
-
} else {
|
|
19569
|
-
type = { kind: "struct", name: token.value };
|
|
19570
|
-
}
|
|
19571
|
-
} else {
|
|
19572
|
-
this.error(`Expected type, got '${token.kind}'`);
|
|
19573
|
-
}
|
|
19574
|
-
while (this.match("[")) {
|
|
19575
|
-
this.expect("]");
|
|
19576
|
-
type = { kind: "array", elem: type };
|
|
19577
|
-
}
|
|
19578
|
-
return type;
|
|
19464
|
+
isTypeCastAs() {
|
|
19465
|
+
const next = this.tokens[this.pos + 1];
|
|
19466
|
+
if (!next)
|
|
19467
|
+
return false;
|
|
19468
|
+
const typeStartTokens = /* @__PURE__ */ new Set(["int", "bool", "float", "fixed", "string", "void", "BlockPos", "("]);
|
|
19469
|
+
if (typeStartTokens.has(next.kind))
|
|
19470
|
+
return true;
|
|
19471
|
+
if (next.kind === "ident" && (next.value === "double" || next.value === "byte" || next.value === "short" || next.value === "long" || next.value === "selector" || next.value === "Option"))
|
|
19472
|
+
return true;
|
|
19473
|
+
return false;
|
|
19579
19474
|
}
|
|
19580
|
-
|
|
19581
|
-
|
|
19582
|
-
const params = [];
|
|
19475
|
+
parseArgs() {
|
|
19476
|
+
const args = [];
|
|
19583
19477
|
if (!this.check(")")) {
|
|
19584
19478
|
do {
|
|
19585
|
-
|
|
19479
|
+
args.push(this.parseExpr());
|
|
19586
19480
|
} while (this.match(","));
|
|
19587
19481
|
}
|
|
19588
|
-
|
|
19589
|
-
this.expect("->");
|
|
19590
|
-
const returnType = this.parseType();
|
|
19591
|
-
return { kind: "function_type", params, return: returnType };
|
|
19482
|
+
return args;
|
|
19592
19483
|
}
|
|
19593
|
-
|
|
19594
|
-
|
|
19595
|
-
|
|
19596
|
-
|
|
19597
|
-
|
|
19598
|
-
|
|
19599
|
-
|
|
19600
|
-
|
|
19601
|
-
|
|
19602
|
-
|
|
19603
|
-
|
|
19604
|
-
this.
|
|
19605
|
-
|
|
19606
|
-
|
|
19607
|
-
|
|
19484
|
+
parsePrimaryExpr() {
|
|
19485
|
+
const token = this.peek();
|
|
19486
|
+
if (token.kind === "ident" && this.peek(1).kind === "::") {
|
|
19487
|
+
const typeToken = this.advance();
|
|
19488
|
+
this.expect("::");
|
|
19489
|
+
const memberToken = this.expect("ident");
|
|
19490
|
+
if (this.check("(")) {
|
|
19491
|
+
const isNamedArgs = this.peek(1).kind === "ident" && this.peek(2).kind === ":";
|
|
19492
|
+
if (isNamedArgs) {
|
|
19493
|
+
this.advance();
|
|
19494
|
+
const args2 = [];
|
|
19495
|
+
while (!this.check(")") && !this.check("eof")) {
|
|
19496
|
+
const fieldName = this.expect("ident").value;
|
|
19497
|
+
this.expect(":");
|
|
19498
|
+
const value = this.parseExpr();
|
|
19499
|
+
args2.push({ name: fieldName, value });
|
|
19500
|
+
if (!this.match(","))
|
|
19501
|
+
break;
|
|
19502
|
+
}
|
|
19503
|
+
this.expect(")");
|
|
19504
|
+
return this.withLoc({ kind: "enum_construct", enumName: typeToken.value, variant: memberToken.value, args: args2 }, typeToken);
|
|
19608
19505
|
}
|
|
19506
|
+
this.advance();
|
|
19507
|
+
const args = this.parseArgs();
|
|
19508
|
+
this.expect(")");
|
|
19509
|
+
return this.withLoc({ kind: "static_call", type: typeToken.value, method: memberToken.value, args }, typeToken);
|
|
19609
19510
|
}
|
|
19511
|
+
return this.withLoc({ kind: "path_expr", enumName: typeToken.value, variant: memberToken.value }, typeToken);
|
|
19610
19512
|
}
|
|
19611
|
-
this.
|
|
19612
|
-
|
|
19613
|
-
}
|
|
19614
|
-
parseStmt() {
|
|
19615
|
-
if (this.check("let")) {
|
|
19616
|
-
return this.parseLetStmt();
|
|
19513
|
+
if (token.kind === "ident" && this.peek(1).kind === "=>") {
|
|
19514
|
+
return this.parseSingleParamLambda();
|
|
19617
19515
|
}
|
|
19618
|
-
if (
|
|
19619
|
-
|
|
19516
|
+
if (token.kind === "int_lit") {
|
|
19517
|
+
this.advance();
|
|
19518
|
+
return this.withLoc({ kind: "int_lit", value: parseInt(token.value, 10) }, token);
|
|
19620
19519
|
}
|
|
19621
|
-
if (
|
|
19622
|
-
|
|
19520
|
+
if (token.kind === "float_lit") {
|
|
19521
|
+
this.advance();
|
|
19522
|
+
return this.withLoc({ kind: "float_lit", value: parseFloat(token.value) }, token);
|
|
19623
19523
|
}
|
|
19624
|
-
if (
|
|
19625
|
-
|
|
19626
|
-
|
|
19627
|
-
const labelToken = this.advance();
|
|
19628
|
-
this.match(";");
|
|
19629
|
-
return this.withLoc({ kind: "break_label", label: labelToken.value }, token);
|
|
19630
|
-
}
|
|
19631
|
-
this.match(";");
|
|
19632
|
-
return this.withLoc({ kind: "break" }, token);
|
|
19524
|
+
if (token.kind === "rel_coord") {
|
|
19525
|
+
this.advance();
|
|
19526
|
+
return this.withLoc({ kind: "rel_coord", value: token.value }, token);
|
|
19633
19527
|
}
|
|
19634
|
-
if (
|
|
19635
|
-
|
|
19636
|
-
|
|
19637
|
-
const labelToken = this.advance();
|
|
19638
|
-
this.match(";");
|
|
19639
|
-
return this.withLoc({ kind: "continue_label", label: labelToken.value }, token);
|
|
19640
|
-
}
|
|
19641
|
-
this.match(";");
|
|
19642
|
-
return this.withLoc({ kind: "continue" }, token);
|
|
19528
|
+
if (token.kind === "local_coord") {
|
|
19529
|
+
this.advance();
|
|
19530
|
+
return this.withLoc({ kind: "local_coord", value: token.value }, token);
|
|
19643
19531
|
}
|
|
19644
|
-
if (
|
|
19645
|
-
|
|
19532
|
+
if (token.kind === "byte_lit") {
|
|
19533
|
+
this.advance();
|
|
19534
|
+
return this.withLoc({ kind: "byte_lit", value: parseInt(token.value.slice(0, -1), 10) }, token);
|
|
19646
19535
|
}
|
|
19647
|
-
if (
|
|
19648
|
-
|
|
19649
|
-
|
|
19650
|
-
let loopStmt;
|
|
19651
|
-
if (this.check("while")) {
|
|
19652
|
-
loopStmt = this.parseWhileStmt();
|
|
19653
|
-
} else if (this.check("for")) {
|
|
19654
|
-
loopStmt = this.parseForStmt();
|
|
19655
|
-
} else if (this.check("foreach")) {
|
|
19656
|
-
loopStmt = this.parseForeachStmt();
|
|
19657
|
-
} else if (this.check("repeat")) {
|
|
19658
|
-
loopStmt = this.parseRepeatStmt();
|
|
19659
|
-
} else {
|
|
19660
|
-
throw new diagnostics_1.DiagnosticError("ParseError", `Expected loop statement after label '${labelToken.value}:', found '${this.peek().kind}'`, { line: labelToken.line, col: labelToken.col });
|
|
19661
|
-
}
|
|
19662
|
-
return this.withLoc({ kind: "labeled_loop", label: labelToken.value, body: loopStmt }, labelToken);
|
|
19536
|
+
if (token.kind === "short_lit") {
|
|
19537
|
+
this.advance();
|
|
19538
|
+
return this.withLoc({ kind: "short_lit", value: parseInt(token.value.slice(0, -1), 10) }, token);
|
|
19663
19539
|
}
|
|
19664
|
-
if (
|
|
19665
|
-
|
|
19540
|
+
if (token.kind === "long_lit") {
|
|
19541
|
+
this.advance();
|
|
19542
|
+
return this.withLoc({ kind: "long_lit", value: parseInt(token.value.slice(0, -1), 10) }, token);
|
|
19666
19543
|
}
|
|
19667
|
-
if (
|
|
19668
|
-
|
|
19544
|
+
if (token.kind === "double_lit") {
|
|
19545
|
+
this.advance();
|
|
19546
|
+
return this.withLoc({ kind: "double_lit", value: parseFloat(token.value.slice(0, -1)) }, token);
|
|
19669
19547
|
}
|
|
19670
|
-
if (
|
|
19671
|
-
|
|
19548
|
+
if (token.kind === "string_lit") {
|
|
19549
|
+
this.advance();
|
|
19550
|
+
return this.parseStringExpr(token);
|
|
19672
19551
|
}
|
|
19673
|
-
if (
|
|
19674
|
-
|
|
19552
|
+
if (token.kind === "f_string") {
|
|
19553
|
+
this.advance();
|
|
19554
|
+
return this.parseFStringExpr(token);
|
|
19675
19555
|
}
|
|
19676
|
-
if (
|
|
19677
|
-
|
|
19556
|
+
if (token.kind === "mc_name") {
|
|
19557
|
+
this.advance();
|
|
19558
|
+
return this.withLoc({ kind: "mc_name", value: token.value.slice(1) }, token);
|
|
19678
19559
|
}
|
|
19679
|
-
if (
|
|
19680
|
-
|
|
19560
|
+
if (token.kind === "true") {
|
|
19561
|
+
this.advance();
|
|
19562
|
+
return this.withLoc({ kind: "bool_lit", value: true }, token);
|
|
19681
19563
|
}
|
|
19682
|
-
if (
|
|
19683
|
-
|
|
19564
|
+
if (token.kind === "false") {
|
|
19565
|
+
this.advance();
|
|
19566
|
+
return this.withLoc({ kind: "bool_lit", value: false }, token);
|
|
19684
19567
|
}
|
|
19685
|
-
if (
|
|
19686
|
-
|
|
19568
|
+
if (token.kind === "range_lit") {
|
|
19569
|
+
this.advance();
|
|
19570
|
+
return this.withLoc({ kind: "range_lit", range: this.parseRangeValue(token.value) }, token);
|
|
19687
19571
|
}
|
|
19688
|
-
if (
|
|
19689
|
-
|
|
19572
|
+
if (token.kind === "selector") {
|
|
19573
|
+
this.advance();
|
|
19574
|
+
return this.withLoc({
|
|
19575
|
+
kind: "selector",
|
|
19576
|
+
raw: token.value,
|
|
19577
|
+
isSingle: computeIsSingle(token.value),
|
|
19578
|
+
sel: this.parseSelectorValue(token.value)
|
|
19579
|
+
}, token);
|
|
19690
19580
|
}
|
|
19691
|
-
if (this.
|
|
19692
|
-
|
|
19693
|
-
|
|
19694
|
-
this.match(";");
|
|
19695
|
-
return this.withLoc({ kind: "raw", cmd }, token);
|
|
19581
|
+
if (token.kind === "ident" && this.peek(1).kind === "{" && this.peek(2).kind === "ident" && this.peek(3).kind === ":") {
|
|
19582
|
+
this.advance();
|
|
19583
|
+
return this.parseStructLit();
|
|
19696
19584
|
}
|
|
19697
|
-
|
|
19698
|
-
}
|
|
19699
|
-
parseLetStmt() {
|
|
19700
|
-
const letToken = this.expect("let");
|
|
19701
|
-
if (this.check("(")) {
|
|
19585
|
+
if (token.kind === "ident" && token.value === "Some" && this.peek(1).kind === "(") {
|
|
19702
19586
|
this.advance();
|
|
19703
|
-
|
|
19704
|
-
|
|
19705
|
-
names.push(this.expect("ident").value);
|
|
19706
|
-
} while (this.match(","));
|
|
19587
|
+
this.advance();
|
|
19588
|
+
const value = this.parseExpr();
|
|
19707
19589
|
this.expect(")");
|
|
19708
|
-
|
|
19709
|
-
if (this.match(":")) {
|
|
19710
|
-
type2 = this.parseType();
|
|
19711
|
-
}
|
|
19712
|
-
this.expect("=");
|
|
19713
|
-
const init2 = this.parseExpr();
|
|
19714
|
-
this.match(";");
|
|
19715
|
-
return this.withLoc({ kind: "let_destruct", names, type: type2, init: init2 }, letToken);
|
|
19590
|
+
return this.withLoc({ kind: "some_lit", value }, token);
|
|
19716
19591
|
}
|
|
19717
|
-
|
|
19718
|
-
let type;
|
|
19719
|
-
if (this.match(":")) {
|
|
19720
|
-
type = this.parseType();
|
|
19721
|
-
}
|
|
19722
|
-
this.expect("=");
|
|
19723
|
-
const init = this.parseExpr();
|
|
19724
|
-
this.match(";");
|
|
19725
|
-
return this.withLoc({ kind: "let", name, type, init }, letToken);
|
|
19726
|
-
}
|
|
19727
|
-
parseLocalConstDecl() {
|
|
19728
|
-
const constToken = this.expect("const");
|
|
19729
|
-
const name = this.expect("ident").value;
|
|
19730
|
-
this.expect(":");
|
|
19731
|
-
const type = this.parseType();
|
|
19732
|
-
this.expect("=");
|
|
19733
|
-
const value = this.parseExpr();
|
|
19734
|
-
this.match(";");
|
|
19735
|
-
return this.withLoc({ kind: "const_decl", name, type, value }, constToken);
|
|
19736
|
-
}
|
|
19737
|
-
parseReturnStmt() {
|
|
19738
|
-
const returnToken = this.expect("return");
|
|
19739
|
-
let value;
|
|
19740
|
-
if (!this.check(";") && !this.check("}") && !this.check("eof")) {
|
|
19741
|
-
value = this.parseExpr();
|
|
19742
|
-
}
|
|
19743
|
-
this.match(";");
|
|
19744
|
-
return this.withLoc({ kind: "return", value }, returnToken);
|
|
19745
|
-
}
|
|
19746
|
-
parseIfStmt() {
|
|
19747
|
-
const ifToken = this.expect("if");
|
|
19748
|
-
if (this.check("let") && this.peek(1).kind === "ident" && this.peek(1).value === "Some") {
|
|
19749
|
-
this.advance();
|
|
19750
|
-
this.advance();
|
|
19751
|
-
this.expect("(");
|
|
19752
|
-
const binding = this.expect("ident").value;
|
|
19753
|
-
this.expect(")");
|
|
19754
|
-
this.expect("=");
|
|
19755
|
-
const init = this.parseExpr();
|
|
19756
|
-
const then2 = this.parseBlock();
|
|
19757
|
-
let else_2;
|
|
19758
|
-
if (this.match("else")) {
|
|
19759
|
-
if (this.check("if")) {
|
|
19760
|
-
else_2 = [this.parseIfStmt()];
|
|
19761
|
-
} else {
|
|
19762
|
-
else_2 = this.parseBlock();
|
|
19763
|
-
}
|
|
19764
|
-
}
|
|
19765
|
-
return this.withLoc({ kind: "if_let_some", binding, init, then: then2, else_: else_2 }, ifToken);
|
|
19766
|
-
}
|
|
19767
|
-
const cond = this.parseParenOptionalCond();
|
|
19768
|
-
const then = this.parseBlock();
|
|
19769
|
-
let else_;
|
|
19770
|
-
if (this.match("else")) {
|
|
19771
|
-
if (this.check("if")) {
|
|
19772
|
-
else_ = [this.parseIfStmt()];
|
|
19773
|
-
} else {
|
|
19774
|
-
else_ = this.parseBlock();
|
|
19775
|
-
}
|
|
19776
|
-
}
|
|
19777
|
-
return this.withLoc({ kind: "if", cond, then, else_ }, ifToken);
|
|
19778
|
-
}
|
|
19779
|
-
parseWhileStmt() {
|
|
19780
|
-
const whileToken = this.expect("while");
|
|
19781
|
-
if (this.check("let") && this.peek(1).kind === "ident" && this.peek(1).value === "Some") {
|
|
19782
|
-
this.advance();
|
|
19592
|
+
if (token.kind === "ident" && token.value === "None") {
|
|
19783
19593
|
this.advance();
|
|
19784
|
-
this.
|
|
19785
|
-
const binding = this.expect("ident").value;
|
|
19786
|
-
this.expect(")");
|
|
19787
|
-
this.expect("=");
|
|
19788
|
-
const init = this.parseExpr();
|
|
19789
|
-
const body2 = this.parseBlock();
|
|
19790
|
-
return this.withLoc({ kind: "while_let_some", binding, init, body: body2 }, whileToken);
|
|
19791
|
-
}
|
|
19792
|
-
const cond = this.parseParenOptionalCond();
|
|
19793
|
-
const body = this.parseBlock();
|
|
19794
|
-
return this.withLoc({ kind: "while", cond, body }, whileToken);
|
|
19795
|
-
}
|
|
19796
|
-
parseDoWhileStmt() {
|
|
19797
|
-
const doToken = this.expect("do");
|
|
19798
|
-
const body = this.parseBlock();
|
|
19799
|
-
this.expect("while");
|
|
19800
|
-
const cond = this.parseParenOptionalCond();
|
|
19801
|
-
this.match(";");
|
|
19802
|
-
return this.withLoc({ kind: "do_while", cond, body }, doToken);
|
|
19803
|
-
}
|
|
19804
|
-
parseRepeatStmt() {
|
|
19805
|
-
const repeatToken = this.expect("repeat");
|
|
19806
|
-
const countToken = this.expect("int_lit");
|
|
19807
|
-
const count = parseInt(countToken.value, 10);
|
|
19808
|
-
const body = this.parseBlock();
|
|
19809
|
-
return this.withLoc({ kind: "repeat", count, body }, repeatToken);
|
|
19810
|
-
}
|
|
19811
|
-
parseParenOptionalCond() {
|
|
19812
|
-
if (this.match("(")) {
|
|
19813
|
-
const cond = this.parseExpr();
|
|
19814
|
-
this.expect(")");
|
|
19815
|
-
return cond;
|
|
19816
|
-
}
|
|
19817
|
-
return this.parseExpr();
|
|
19818
|
-
}
|
|
19819
|
-
parseForStmt() {
|
|
19820
|
-
const forToken = this.expect("for");
|
|
19821
|
-
if (this.check("ident") && this.peek(1).kind === "in") {
|
|
19822
|
-
return this.parseForRangeStmt(forToken);
|
|
19594
|
+
return this.withLoc({ kind: "none_lit" }, token);
|
|
19823
19595
|
}
|
|
19824
|
-
|
|
19825
|
-
if (this.check("let") && this.peek(1).kind === "ident" && this.peek(2).kind === "in" && this.peek(3).kind === "ident" && this.peek(4).kind === ",") {
|
|
19596
|
+
if (token.kind === "ident") {
|
|
19826
19597
|
this.advance();
|
|
19827
|
-
|
|
19828
|
-
this.expect("in");
|
|
19829
|
-
const arrayName = this.expect("ident").value;
|
|
19830
|
-
this.expect(",");
|
|
19831
|
-
const lenExpr = this.parseExpr();
|
|
19832
|
-
this.expect(")");
|
|
19833
|
-
const body2 = this.parseBlock();
|
|
19834
|
-
return this.withLoc({ kind: "for_in_array", binding, arrayName, lenExpr, body: body2 }, forToken);
|
|
19835
|
-
}
|
|
19836
|
-
let init;
|
|
19837
|
-
if (this.check("let")) {
|
|
19838
|
-
const letToken = this.expect("let");
|
|
19839
|
-
const name = this.expect("ident").value;
|
|
19840
|
-
let type;
|
|
19841
|
-
if (this.match(":")) {
|
|
19842
|
-
type = this.parseType();
|
|
19843
|
-
}
|
|
19844
|
-
this.expect("=");
|
|
19845
|
-
const initExpr = this.parseExpr();
|
|
19846
|
-
const initStmt = { kind: "let", name, type, init: initExpr };
|
|
19847
|
-
init = this.withLoc(initStmt, letToken);
|
|
19598
|
+
return this.withLoc({ kind: "ident", name: token.value }, token);
|
|
19848
19599
|
}
|
|
19849
|
-
|
|
19850
|
-
|
|
19851
|
-
|
|
19852
|
-
const step = this.parseExpr();
|
|
19853
|
-
this.expect(")");
|
|
19854
|
-
const body = this.parseBlock();
|
|
19855
|
-
return this.withLoc({ kind: "for", init, cond, step, body }, forToken);
|
|
19856
|
-
}
|
|
19857
|
-
parseForRangeStmt(forToken) {
|
|
19858
|
-
const varName = this.expect("ident").value;
|
|
19859
|
-
this.expect("in");
|
|
19860
|
-
let start;
|
|
19861
|
-
let end;
|
|
19862
|
-
let inclusive = false;
|
|
19863
|
-
if (this.check("range_lit")) {
|
|
19864
|
-
const rangeToken = this.advance();
|
|
19865
|
-
const raw = rangeToken.value;
|
|
19866
|
-
const incl = raw.includes("..=");
|
|
19867
|
-
inclusive = incl;
|
|
19868
|
-
const range = this.parseRangeValue(raw);
|
|
19869
|
-
start = this.withLoc({ kind: "int_lit", value: range.min ?? 0 }, rangeToken);
|
|
19870
|
-
if (range.max !== null && range.max !== void 0) {
|
|
19871
|
-
end = this.withLoc({ kind: "int_lit", value: range.max }, rangeToken);
|
|
19872
|
-
} else {
|
|
19873
|
-
end = this.parseUnaryExpr();
|
|
19600
|
+
if (token.kind === "(") {
|
|
19601
|
+
if (this.isBlockPosLiteral()) {
|
|
19602
|
+
return this.parseBlockPos();
|
|
19874
19603
|
}
|
|
19875
|
-
|
|
19876
|
-
|
|
19877
|
-
if (!this.check("range_lit")) {
|
|
19878
|
-
const body2 = this.parseBlock();
|
|
19879
|
-
return this.withLoc({ kind: "for_each", binding: varName, array: arrayOrStart, body: body2 }, forToken);
|
|
19604
|
+
if (this.isLambdaStart()) {
|
|
19605
|
+
return this.parseLambdaExpr();
|
|
19880
19606
|
}
|
|
19881
|
-
|
|
19882
|
-
|
|
19883
|
-
|
|
19884
|
-
|
|
19885
|
-
|
|
19886
|
-
|
|
19887
|
-
|
|
19888
|
-
|
|
19889
|
-
end = this.parseExpr();
|
|
19607
|
+
this.advance();
|
|
19608
|
+
const first = this.parseExpr();
|
|
19609
|
+
if (this.match(",")) {
|
|
19610
|
+
const elements = [first];
|
|
19611
|
+
if (!this.check(")")) {
|
|
19612
|
+
do {
|
|
19613
|
+
elements.push(this.parseExpr());
|
|
19614
|
+
} while (this.match(","));
|
|
19890
19615
|
}
|
|
19891
|
-
|
|
19892
|
-
this.
|
|
19893
|
-
start = this.withLoc({ kind: "int_lit", value: 0 }, this.peek());
|
|
19894
|
-
end = this.withLoc({ kind: "int_lit", value: 0 }, this.peek());
|
|
19895
|
-
}
|
|
19896
|
-
}
|
|
19897
|
-
const body = this.parseBlock();
|
|
19898
|
-
return this.withLoc({ kind: "for_range", varName, start, end, inclusive, body }, forToken);
|
|
19899
|
-
}
|
|
19900
|
-
parseForeachStmt() {
|
|
19901
|
-
const foreachToken = this.expect("foreach");
|
|
19902
|
-
this.expect("(");
|
|
19903
|
-
const binding = this.expect("ident").value;
|
|
19904
|
-
this.expect("in");
|
|
19905
|
-
const iterable = this.parseExpr();
|
|
19906
|
-
this.expect(")");
|
|
19907
|
-
let executeContext;
|
|
19908
|
-
const execIdentKeywords = ["positioned", "rotated", "facing", "anchored", "align", "on", "summon"];
|
|
19909
|
-
if (this.check("as") || this.check("at") || this.check("in") || this.check("ident") && execIdentKeywords.includes(this.peek().value)) {
|
|
19910
|
-
let context = "";
|
|
19911
|
-
while (!this.check("{") && !this.check("eof")) {
|
|
19912
|
-
context += this.advance().value + " ";
|
|
19616
|
+
this.expect(")");
|
|
19617
|
+
return this.withLoc({ kind: "tuple_lit", elements }, token);
|
|
19913
19618
|
}
|
|
19914
|
-
|
|
19619
|
+
this.expect(")");
|
|
19620
|
+
return first;
|
|
19915
19621
|
}
|
|
19916
|
-
|
|
19917
|
-
|
|
19918
|
-
}
|
|
19919
|
-
parseMatchPattern() {
|
|
19920
|
-
if (this.check("ident") && this.peek().value === "_") {
|
|
19921
|
-
this.advance();
|
|
19922
|
-
return { kind: "PatWild" };
|
|
19622
|
+
if (token.kind === "{") {
|
|
19623
|
+
return this.parseStructLit();
|
|
19923
19624
|
}
|
|
19924
|
-
if (
|
|
19925
|
-
this.
|
|
19926
|
-
return { kind: "PatNone" };
|
|
19625
|
+
if (token.kind === "[") {
|
|
19626
|
+
return this.parseArrayLit();
|
|
19927
19627
|
}
|
|
19928
|
-
|
|
19628
|
+
this.error(`Unexpected token '${token.value || token.kind}'. Expected an expression (identifier, literal, '(', '[', or '{')`);
|
|
19629
|
+
}
|
|
19630
|
+
parseLiteralExpr() {
|
|
19631
|
+
if (this.check("-")) {
|
|
19929
19632
|
this.advance();
|
|
19930
|
-
this.
|
|
19931
|
-
|
|
19932
|
-
this.expect(")");
|
|
19933
|
-
return { kind: "PatSome", binding };
|
|
19934
|
-
}
|
|
19935
|
-
if (this.check("ident") && this.peek(1).kind === "::") {
|
|
19936
|
-
const enumName = this.advance().value;
|
|
19937
|
-
this.expect("::");
|
|
19938
|
-
const variant = this.expect("ident").value;
|
|
19939
|
-
const bindings = [];
|
|
19940
|
-
if (this.check("(")) {
|
|
19633
|
+
const token = this.peek();
|
|
19634
|
+
if (token.kind === "int_lit") {
|
|
19941
19635
|
this.advance();
|
|
19942
|
-
|
|
19943
|
-
bindings.push(this.expect("ident").value);
|
|
19944
|
-
if (!this.match(","))
|
|
19945
|
-
break;
|
|
19946
|
-
}
|
|
19947
|
-
this.expect(")");
|
|
19636
|
+
return this.withLoc({ kind: "int_lit", value: -Number(token.value) }, token);
|
|
19948
19637
|
}
|
|
19949
|
-
|
|
19950
|
-
|
|
19951
|
-
|
|
19952
|
-
|
|
19953
|
-
|
|
19638
|
+
if (token.kind === "float_lit") {
|
|
19639
|
+
this.advance();
|
|
19640
|
+
return this.withLoc({ kind: "float_lit", value: -Number(token.value) }, token);
|
|
19641
|
+
}
|
|
19642
|
+
this.error("Expected number after unary minus (-). Const values must be numeric or string literals");
|
|
19954
19643
|
}
|
|
19955
|
-
|
|
19956
|
-
|
|
19957
|
-
|
|
19958
|
-
return { kind: "PatInt", value: -parseInt(tok.value, 10) };
|
|
19644
|
+
const expr = this.parsePrimaryExpr();
|
|
19645
|
+
if (expr.kind === "int_lit" || expr.kind === "float_lit" || expr.kind === "bool_lit" || expr.kind === "str_lit") {
|
|
19646
|
+
return expr;
|
|
19959
19647
|
}
|
|
19960
|
-
|
|
19961
|
-
return { kind: "PatExpr", expr: e };
|
|
19648
|
+
this.error("Const value must be a literal");
|
|
19962
19649
|
}
|
|
19963
|
-
|
|
19964
|
-
|
|
19965
|
-
|
|
19966
|
-
|
|
19967
|
-
|
|
19968
|
-
|
|
19969
|
-
|
|
19970
|
-
|
|
19971
|
-
|
|
19650
|
+
// -------------------------------------------------------------------------
|
|
19651
|
+
// Lambda
|
|
19652
|
+
// -------------------------------------------------------------------------
|
|
19653
|
+
parseSingleParamLambda() {
|
|
19654
|
+
const paramToken = this.expect("ident");
|
|
19655
|
+
const params = [{ name: paramToken.value }];
|
|
19656
|
+
this.expect("=>");
|
|
19657
|
+
return this.finishLambdaExpr(params, paramToken);
|
|
19658
|
+
}
|
|
19659
|
+
parseLambdaExpr() {
|
|
19660
|
+
const openParenToken = this.expect("(");
|
|
19661
|
+
const params = [];
|
|
19662
|
+
if (!this.check(")")) {
|
|
19663
|
+
do {
|
|
19664
|
+
const name = this.expect("ident").value;
|
|
19665
|
+
let type;
|
|
19666
|
+
if (this.match(":")) {
|
|
19667
|
+
type = this.parseType();
|
|
19668
|
+
}
|
|
19669
|
+
params.push({ name, type });
|
|
19670
|
+
} while (this.match(","));
|
|
19972
19671
|
}
|
|
19973
|
-
this.expect("
|
|
19974
|
-
|
|
19975
|
-
|
|
19976
|
-
|
|
19977
|
-
this.expect("=>");
|
|
19978
|
-
const body = this.parseBlock();
|
|
19979
|
-
this.match(",");
|
|
19980
|
-
arms.push({ pattern, body });
|
|
19672
|
+
this.expect(")");
|
|
19673
|
+
let returnType;
|
|
19674
|
+
if (this.match("->")) {
|
|
19675
|
+
returnType = this.parseType();
|
|
19981
19676
|
}
|
|
19982
|
-
this.expect("
|
|
19983
|
-
return this.
|
|
19677
|
+
this.expect("=>");
|
|
19678
|
+
return this.finishLambdaExpr(params, openParenToken, returnType);
|
|
19984
19679
|
}
|
|
19985
|
-
|
|
19986
|
-
const
|
|
19987
|
-
|
|
19988
|
-
if (this.match("at")) {
|
|
19989
|
-
const at_sel = this.parseSelector();
|
|
19990
|
-
const body2 = this.parseBlock();
|
|
19991
|
-
return this.withLoc({ kind: "as_at", as_sel, at_sel, body: body2 }, asToken);
|
|
19992
|
-
}
|
|
19993
|
-
const body = this.parseBlock();
|
|
19994
|
-
return this.withLoc({ kind: "as_block", selector: as_sel, body }, asToken);
|
|
19680
|
+
finishLambdaExpr(params, token, returnType) {
|
|
19681
|
+
const body = this.check("{") ? this.parseBlock() : this.parseExpr();
|
|
19682
|
+
return this.withLoc({ kind: "lambda", params, returnType, body }, token);
|
|
19995
19683
|
}
|
|
19996
|
-
|
|
19997
|
-
|
|
19998
|
-
|
|
19999
|
-
|
|
20000
|
-
return this.withLoc({ kind: "
|
|
19684
|
+
// -------------------------------------------------------------------------
|
|
19685
|
+
// String interpolation
|
|
19686
|
+
// -------------------------------------------------------------------------
|
|
19687
|
+
parseStringExpr(token) {
|
|
19688
|
+
return this.withLoc({ kind: "str_lit", value: token.value }, token);
|
|
20001
19689
|
}
|
|
20002
|
-
|
|
20003
|
-
const
|
|
20004
|
-
|
|
20005
|
-
|
|
20006
|
-
|
|
20007
|
-
|
|
20008
|
-
|
|
20009
|
-
|
|
20010
|
-
|
|
20011
|
-
subcommands.push({ kind: "at", selector });
|
|
20012
|
-
} else if (this.checkIdent("positioned")) {
|
|
20013
|
-
this.advance();
|
|
20014
|
-
if (this.match("as")) {
|
|
20015
|
-
const selector = this.parseSelector();
|
|
20016
|
-
subcommands.push({ kind: "positioned_as", selector });
|
|
20017
|
-
} else {
|
|
20018
|
-
const x = this.parseCoordToken();
|
|
20019
|
-
const y = this.parseCoordToken();
|
|
20020
|
-
const z = this.parseCoordToken();
|
|
20021
|
-
subcommands.push({ kind: "positioned", x, y, z });
|
|
20022
|
-
}
|
|
20023
|
-
} else if (this.checkIdent("rotated")) {
|
|
20024
|
-
this.advance();
|
|
20025
|
-
if (this.match("as")) {
|
|
20026
|
-
const selector = this.parseSelector();
|
|
20027
|
-
subcommands.push({ kind: "rotated_as", selector });
|
|
20028
|
-
} else {
|
|
20029
|
-
const yaw = this.parseCoordToken();
|
|
20030
|
-
const pitch = this.parseCoordToken();
|
|
20031
|
-
subcommands.push({ kind: "rotated", yaw, pitch });
|
|
20032
|
-
}
|
|
20033
|
-
} else if (this.checkIdent("facing")) {
|
|
20034
|
-
this.advance();
|
|
20035
|
-
if (this.checkIdent("entity")) {
|
|
20036
|
-
this.advance();
|
|
20037
|
-
const selector = this.parseSelector();
|
|
20038
|
-
const anchor = this.checkIdent("eyes") || this.checkIdent("feet") ? this.advance().value : "feet";
|
|
20039
|
-
subcommands.push({ kind: "facing_entity", selector, anchor });
|
|
20040
|
-
} else {
|
|
20041
|
-
const x = this.parseCoordToken();
|
|
20042
|
-
const y = this.parseCoordToken();
|
|
20043
|
-
const z = this.parseCoordToken();
|
|
20044
|
-
subcommands.push({ kind: "facing", x, y, z });
|
|
19690
|
+
parseFStringExpr(token) {
|
|
19691
|
+
const parts = [];
|
|
19692
|
+
let current = "";
|
|
19693
|
+
let index = 0;
|
|
19694
|
+
while (index < token.value.length) {
|
|
19695
|
+
if (token.value[index] === "{") {
|
|
19696
|
+
if (current) {
|
|
19697
|
+
parts.push({ kind: "text", value: current });
|
|
19698
|
+
current = "";
|
|
20045
19699
|
}
|
|
20046
|
-
|
|
20047
|
-
|
|
20048
|
-
|
|
20049
|
-
|
|
20050
|
-
|
|
20051
|
-
|
|
20052
|
-
|
|
20053
|
-
|
|
20054
|
-
} else if (this.checkIdent("on")) {
|
|
20055
|
-
this.advance();
|
|
20056
|
-
const relation = this.advance().value;
|
|
20057
|
-
subcommands.push({ kind: "on", relation });
|
|
20058
|
-
} else if (this.checkIdent("summon")) {
|
|
20059
|
-
this.advance();
|
|
20060
|
-
const entity = this.advance().value;
|
|
20061
|
-
subcommands.push({ kind: "summon", entity });
|
|
20062
|
-
} else if (this.checkIdent("store")) {
|
|
20063
|
-
this.advance();
|
|
20064
|
-
const storeType = this.advance().value;
|
|
20065
|
-
if (this.checkIdent("score")) {
|
|
20066
|
-
this.advance();
|
|
20067
|
-
const target = this.advance().value;
|
|
20068
|
-
const targetObj = this.advance().value;
|
|
20069
|
-
if (storeType === "result") {
|
|
20070
|
-
subcommands.push({ kind: "store_result", target, targetObj });
|
|
20071
|
-
} else {
|
|
20072
|
-
subcommands.push({ kind: "store_success", target, targetObj });
|
|
19700
|
+
index++;
|
|
19701
|
+
let depth = 1;
|
|
19702
|
+
let exprSource = "";
|
|
19703
|
+
let inString = false;
|
|
19704
|
+
while (index < token.value.length && depth > 0) {
|
|
19705
|
+
const char = token.value[index];
|
|
19706
|
+
if (char === '"' && token.value[index - 1] !== "\\") {
|
|
19707
|
+
inString = !inString;
|
|
20073
19708
|
}
|
|
20074
|
-
|
|
20075
|
-
|
|
20076
|
-
|
|
20077
|
-
|
|
20078
|
-
|
|
20079
|
-
|
|
20080
|
-
|
|
20081
|
-
|
|
20082
|
-
|
|
20083
|
-
|
|
20084
|
-
|
|
19709
|
+
if (!inString) {
|
|
19710
|
+
if (char === "{")
|
|
19711
|
+
depth++;
|
|
19712
|
+
else if (char === "}") {
|
|
19713
|
+
depth--;
|
|
19714
|
+
if (depth === 0) {
|
|
19715
|
+
index++;
|
|
19716
|
+
break;
|
|
19717
|
+
}
|
|
19718
|
+
}
|
|
19719
|
+
}
|
|
19720
|
+
if (depth > 0)
|
|
19721
|
+
exprSource += char;
|
|
19722
|
+
index++;
|
|
20085
19723
|
}
|
|
20086
|
-
|
|
20087
|
-
|
|
20088
|
-
|
|
19724
|
+
if (depth !== 0)
|
|
19725
|
+
this.error("Unterminated f-string interpolation");
|
|
19726
|
+
parts.push({ kind: "expr", expr: this.parseEmbeddedExpr(exprSource) });
|
|
19727
|
+
continue;
|
|
20089
19728
|
}
|
|
19729
|
+
current += token.value[index];
|
|
19730
|
+
index++;
|
|
20090
19731
|
}
|
|
20091
|
-
|
|
20092
|
-
|
|
20093
|
-
return this.withLoc({ kind: "
|
|
19732
|
+
if (current)
|
|
19733
|
+
parts.push({ kind: "text", value: current });
|
|
19734
|
+
return this.withLoc({ kind: "f_string", parts }, token);
|
|
20094
19735
|
}
|
|
20095
|
-
|
|
20096
|
-
|
|
20097
|
-
|
|
20098
|
-
|
|
20099
|
-
|
|
20100
|
-
|
|
20101
|
-
|
|
20102
|
-
|
|
20103
|
-
|
|
20104
|
-
|
|
20105
|
-
|
|
20106
|
-
|
|
20107
|
-
|
|
20108
|
-
|
|
20109
|
-
|
|
20110
|
-
|
|
20111
|
-
|
|
20112
|
-
|
|
20113
|
-
this.
|
|
20114
|
-
|
|
20115
|
-
|
|
20116
|
-
|
|
20117
|
-
|
|
20118
|
-
const source = this.advance().value;
|
|
20119
|
-
const sourceObj = this.advance().value;
|
|
20120
|
-
subcommands.push({
|
|
20121
|
-
kind: type === "if" ? "if_score" : "unless_score",
|
|
20122
|
-
target,
|
|
20123
|
-
targetObj,
|
|
20124
|
-
op,
|
|
20125
|
-
source,
|
|
20126
|
-
sourceObj
|
|
20127
|
-
});
|
|
20128
|
-
}
|
|
20129
|
-
} else {
|
|
20130
|
-
this.error(`Unknown condition type after ${type}`);
|
|
19736
|
+
parseEmbeddedExpr(source) {
|
|
19737
|
+
const { Parser } = require_parser();
|
|
19738
|
+
const tokens = new lexer_1.Lexer(source, this.filePath).tokenize();
|
|
19739
|
+
const parser = new Parser(tokens, source, this.filePath);
|
|
19740
|
+
const expr = parser.parseExpr();
|
|
19741
|
+
if (!parser.check("eof")) {
|
|
19742
|
+
parser.error(`Unexpected token '${parser.peek().kind}' in string interpolation`);
|
|
19743
|
+
}
|
|
19744
|
+
return expr;
|
|
19745
|
+
}
|
|
19746
|
+
// -------------------------------------------------------------------------
|
|
19747
|
+
// Struct / Array / BlockPos literals
|
|
19748
|
+
// -------------------------------------------------------------------------
|
|
19749
|
+
parseStructLit() {
|
|
19750
|
+
const braceToken = this.expect("{");
|
|
19751
|
+
const fields = [];
|
|
19752
|
+
if (!this.check("}")) {
|
|
19753
|
+
do {
|
|
19754
|
+
const name = this.expect("ident").value;
|
|
19755
|
+
this.expect(":");
|
|
19756
|
+
const value = this.parseExpr();
|
|
19757
|
+
fields.push({ name, value });
|
|
19758
|
+
} while (this.match(","));
|
|
20131
19759
|
}
|
|
19760
|
+
this.expect("}");
|
|
19761
|
+
return this.withLoc({ kind: "struct_lit", fields }, braceToken);
|
|
20132
19762
|
}
|
|
20133
|
-
|
|
20134
|
-
const
|
|
20135
|
-
|
|
20136
|
-
|
|
19763
|
+
parseArrayLit() {
|
|
19764
|
+
const bracketToken = this.expect("[");
|
|
19765
|
+
const elements = [];
|
|
19766
|
+
if (!this.check("]")) {
|
|
19767
|
+
do {
|
|
19768
|
+
elements.push(this.parseExpr());
|
|
19769
|
+
} while (this.match(","));
|
|
20137
19770
|
}
|
|
20138
|
-
this.
|
|
20139
|
-
return "
|
|
19771
|
+
this.expect("]");
|
|
19772
|
+
return this.withLoc({ kind: "array_lit", elements }, bracketToken);
|
|
20140
19773
|
}
|
|
20141
|
-
|
|
20142
|
-
|
|
20143
|
-
|
|
20144
|
-
|
|
20145
|
-
|
|
20146
|
-
|
|
20147
|
-
|
|
20148
|
-
|
|
20149
|
-
|
|
19774
|
+
isBlockPosLiteral() {
|
|
19775
|
+
if (!this.check("("))
|
|
19776
|
+
return false;
|
|
19777
|
+
let offset = 1;
|
|
19778
|
+
for (let i = 0; i < 3; i++) {
|
|
19779
|
+
const consumed = this.coordComponentTokenLength(offset);
|
|
19780
|
+
if (consumed === 0)
|
|
19781
|
+
return false;
|
|
19782
|
+
offset += consumed;
|
|
19783
|
+
if (i < 2) {
|
|
19784
|
+
if (this.peek(offset).kind !== ",")
|
|
19785
|
+
return false;
|
|
19786
|
+
offset += 1;
|
|
20150
19787
|
}
|
|
20151
|
-
id += this.advance().value;
|
|
20152
19788
|
}
|
|
20153
|
-
return
|
|
20154
|
-
}
|
|
20155
|
-
checkIdent(value) {
|
|
20156
|
-
return this.check("ident") && this.peek().value === value;
|
|
19789
|
+
return this.peek(offset).kind === ")";
|
|
20157
19790
|
}
|
|
20158
|
-
|
|
20159
|
-
const
|
|
20160
|
-
|
|
20161
|
-
|
|
20162
|
-
|
|
19791
|
+
coordComponentTokenLength(offset) {
|
|
19792
|
+
const token = this.peek(offset);
|
|
19793
|
+
if (token.kind === "int_lit")
|
|
19794
|
+
return 1;
|
|
19795
|
+
if (token.kind === "-") {
|
|
19796
|
+
return this.peek(offset + 1).kind === "int_lit" ? 2 : 0;
|
|
19797
|
+
}
|
|
19798
|
+
if (token.kind === "rel_coord" || token.kind === "local_coord")
|
|
19799
|
+
return 1;
|
|
19800
|
+
return 0;
|
|
20163
19801
|
}
|
|
20164
|
-
|
|
20165
|
-
|
|
20166
|
-
|
|
20167
|
-
|
|
20168
|
-
|
|
19802
|
+
parseBlockPos() {
|
|
19803
|
+
const openParenToken = this.expect("(");
|
|
19804
|
+
const x = this.parseCoordComponent();
|
|
19805
|
+
this.expect(",");
|
|
19806
|
+
const y = this.parseCoordComponent();
|
|
19807
|
+
this.expect(",");
|
|
19808
|
+
const z = this.parseCoordComponent();
|
|
19809
|
+
this.expect(")");
|
|
19810
|
+
return this.withLoc({ kind: "blockpos", x, y, z }, openParenToken);
|
|
20169
19811
|
}
|
|
20170
|
-
|
|
20171
|
-
const left = this.parseBinaryExpr(1);
|
|
19812
|
+
parseCoordComponent() {
|
|
20172
19813
|
const token = this.peek();
|
|
20173
|
-
if (token.kind === "
|
|
20174
|
-
|
|
20175
|
-
|
|
20176
|
-
const value = this.parseAssignment();
|
|
20177
|
-
return this.withLoc({ kind: "assign", target: left.name, op, value }, this.getLocToken(left) ?? token);
|
|
20178
|
-
}
|
|
20179
|
-
if (left.kind === "member") {
|
|
20180
|
-
const value = this.parseAssignment();
|
|
20181
|
-
return this.withLoc({ kind: "member_assign", obj: left.obj, field: left.field, op, value }, this.getLocToken(left) ?? token);
|
|
20182
|
-
}
|
|
20183
|
-
if (left.kind === "index") {
|
|
20184
|
-
const value = this.parseAssignment();
|
|
20185
|
-
return this.withLoc({ kind: "index_assign", obj: left.obj, index: left.index, op, value }, this.getLocToken(left) ?? token);
|
|
20186
|
-
}
|
|
19814
|
+
if (token.kind === "rel_coord") {
|
|
19815
|
+
this.advance();
|
|
19816
|
+
return { kind: "relative", offset: this.parseCoordOffsetFromValue(token.value.slice(1)) };
|
|
20187
19817
|
}
|
|
20188
|
-
|
|
20189
|
-
|
|
20190
|
-
|
|
20191
|
-
let left = this.parseUnaryExpr();
|
|
20192
|
-
while (true) {
|
|
20193
|
-
const op = this.peek().kind;
|
|
20194
|
-
if (!BINARY_OPS.has(op))
|
|
20195
|
-
break;
|
|
20196
|
-
const prec = PRECEDENCE[op];
|
|
20197
|
-
if (prec < minPrec)
|
|
20198
|
-
break;
|
|
20199
|
-
const opToken = this.advance();
|
|
20200
|
-
if (op === "is") {
|
|
20201
|
-
const entityType = this.parseEntityTypeName();
|
|
20202
|
-
left = this.withLoc({ kind: "is_check", expr: left, entityType }, this.getLocToken(left) ?? opToken);
|
|
20203
|
-
continue;
|
|
20204
|
-
}
|
|
20205
|
-
const right = this.parseBinaryExpr(prec + 1);
|
|
20206
|
-
left = this.withLoc({ kind: "binary", op, left, right }, this.getLocToken(left) ?? opToken);
|
|
19818
|
+
if (token.kind === "local_coord") {
|
|
19819
|
+
this.advance();
|
|
19820
|
+
return { kind: "local", offset: this.parseCoordOffsetFromValue(token.value.slice(1)) };
|
|
20207
19821
|
}
|
|
20208
|
-
return
|
|
19822
|
+
return { kind: "absolute", value: this.parseSignedCoordOffset(true) };
|
|
20209
19823
|
}
|
|
20210
|
-
|
|
20211
|
-
if (
|
|
20212
|
-
|
|
20213
|
-
|
|
20214
|
-
return this.withLoc({ kind: "unary", op: "!", operand }, bangToken);
|
|
20215
|
-
}
|
|
20216
|
-
if (this.check("-") && !this.isSubtraction()) {
|
|
20217
|
-
const minusToken = this.advance();
|
|
20218
|
-
const operand = this.parseUnaryExpr();
|
|
20219
|
-
return this.withLoc({ kind: "unary", op: "-", operand }, minusToken);
|
|
20220
|
-
}
|
|
20221
|
-
return this.parsePostfixExpr();
|
|
19824
|
+
parseCoordOffsetFromValue(value) {
|
|
19825
|
+
if (value === "" || value === void 0)
|
|
19826
|
+
return 0;
|
|
19827
|
+
return parseFloat(value);
|
|
20222
19828
|
}
|
|
20223
|
-
|
|
20224
|
-
|
|
20225
|
-
if (
|
|
20226
|
-
|
|
20227
|
-
|
|
20228
|
-
|
|
19829
|
+
parseSignedCoordOffset(requireValue = false) {
|
|
19830
|
+
let sign = 1;
|
|
19831
|
+
if (this.match("-"))
|
|
19832
|
+
sign = -1;
|
|
19833
|
+
if (this.check("int_lit"))
|
|
19834
|
+
return sign * parseInt(this.advance().value, 10);
|
|
19835
|
+
if (requireValue)
|
|
19836
|
+
this.error("Expected integer coordinate component");
|
|
19837
|
+
return 0;
|
|
20229
19838
|
}
|
|
20230
|
-
|
|
20231
|
-
|
|
20232
|
-
|
|
20233
|
-
|
|
20234
|
-
|
|
19839
|
+
// -------------------------------------------------------------------------
|
|
19840
|
+
// Selector parsing (also used by stmt-parser)
|
|
19841
|
+
// -------------------------------------------------------------------------
|
|
19842
|
+
parseSelector() {
|
|
19843
|
+
const token = this.expect("selector");
|
|
19844
|
+
return this.parseSelectorValue(token.value);
|
|
20235
19845
|
}
|
|
20236
|
-
|
|
20237
|
-
|
|
20238
|
-
|
|
20239
|
-
* Does NOT consume any tokens if it returns null.
|
|
20240
|
-
*/
|
|
20241
|
-
tryParseTypeArgs() {
|
|
20242
|
-
const saved = this.pos;
|
|
20243
|
-
this.advance();
|
|
20244
|
-
const typeArgs = [];
|
|
20245
|
-
try {
|
|
20246
|
-
do {
|
|
20247
|
-
typeArgs.push(this.parseType());
|
|
20248
|
-
} while (this.match(","));
|
|
20249
|
-
if (!this.check(">")) {
|
|
20250
|
-
this.pos = saved;
|
|
20251
|
-
return null;
|
|
20252
|
-
}
|
|
20253
|
-
this.advance();
|
|
20254
|
-
return typeArgs;
|
|
20255
|
-
} catch {
|
|
20256
|
-
this.pos = saved;
|
|
20257
|
-
return null;
|
|
19846
|
+
parseSelectorOrVarSelector() {
|
|
19847
|
+
if (this.check("selector")) {
|
|
19848
|
+
return { selector: this.parseSelector() };
|
|
20258
19849
|
}
|
|
20259
|
-
|
|
20260
|
-
|
|
20261
|
-
|
|
20262
|
-
|
|
20263
|
-
|
|
20264
|
-
|
|
20265
|
-
|
|
20266
|
-
|
|
19850
|
+
const varToken = this.expect("ident");
|
|
19851
|
+
const varName = varToken.value;
|
|
19852
|
+
if (this.check("[")) {
|
|
19853
|
+
this.advance();
|
|
19854
|
+
let filterStr = "";
|
|
19855
|
+
let depth = 1;
|
|
19856
|
+
while (depth > 0 && !this.check("eof")) {
|
|
19857
|
+
if (this.check("["))
|
|
19858
|
+
depth++;
|
|
19859
|
+
else if (this.check("]"))
|
|
19860
|
+
depth--;
|
|
19861
|
+
if (depth > 0) {
|
|
19862
|
+
filterStr += this.peek().value ?? this.peek().kind;
|
|
20267
19863
|
this.advance();
|
|
20268
|
-
const args = this.parseArgs();
|
|
20269
|
-
this.expect(")");
|
|
20270
|
-
expr = this.withLoc({ kind: "call", fn: expr.name, args, typeArgs }, this.getLocToken(expr) ?? openParenToken);
|
|
20271
|
-
continue;
|
|
20272
|
-
}
|
|
20273
|
-
}
|
|
20274
|
-
if (this.match("(")) {
|
|
20275
|
-
const openParenToken = this.tokens[this.pos - 1];
|
|
20276
|
-
if (expr.kind === "ident") {
|
|
20277
|
-
const args2 = this.parseArgs();
|
|
20278
|
-
this.expect(")");
|
|
20279
|
-
expr = this.withLoc({ kind: "call", fn: expr.name, args: args2 }, this.getLocToken(expr) ?? openParenToken);
|
|
20280
|
-
continue;
|
|
20281
|
-
}
|
|
20282
|
-
if (expr.kind === "member") {
|
|
20283
|
-
if (expr.field === "unwrap_or") {
|
|
20284
|
-
const defaultExpr = this.parseExpr();
|
|
20285
|
-
this.expect(")");
|
|
20286
|
-
expr = this.withLoc({ kind: "unwrap_or", opt: expr.obj, default_: defaultExpr }, this.getLocToken(expr) ?? openParenToken);
|
|
20287
|
-
continue;
|
|
20288
|
-
}
|
|
20289
|
-
const methodMap = {
|
|
20290
|
-
"tag": "__entity_tag",
|
|
20291
|
-
"untag": "__entity_untag",
|
|
20292
|
-
"has_tag": "__entity_has_tag",
|
|
20293
|
-
"push": "__array_push",
|
|
20294
|
-
"pop": "__array_pop",
|
|
20295
|
-
"add": "set_add",
|
|
20296
|
-
"contains": "set_contains",
|
|
20297
|
-
"remove": "set_remove",
|
|
20298
|
-
"clear": "set_clear"
|
|
20299
|
-
};
|
|
20300
|
-
const internalFn = methodMap[expr.field];
|
|
20301
|
-
if (internalFn) {
|
|
20302
|
-
const args3 = this.parseArgs();
|
|
20303
|
-
this.expect(")");
|
|
20304
|
-
expr = this.withLoc({ kind: "call", fn: internalFn, args: [expr.obj, ...args3] }, this.getLocToken(expr) ?? openParenToken);
|
|
20305
|
-
continue;
|
|
20306
|
-
}
|
|
20307
|
-
const args2 = this.parseArgs();
|
|
20308
|
-
this.expect(")");
|
|
20309
|
-
expr = this.withLoc({ kind: "call", fn: expr.field, args: [expr.obj, ...args2] }, this.getLocToken(expr) ?? openParenToken);
|
|
20310
|
-
continue;
|
|
20311
19864
|
}
|
|
20312
|
-
const args = this.parseArgs();
|
|
20313
|
-
this.expect(")");
|
|
20314
|
-
expr = this.withLoc({ kind: "invoke", callee: expr, args }, this.getLocToken(expr) ?? openParenToken);
|
|
20315
|
-
continue;
|
|
20316
19865
|
}
|
|
20317
|
-
|
|
20318
|
-
|
|
20319
|
-
|
|
20320
|
-
|
|
20321
|
-
|
|
20322
|
-
|
|
20323
|
-
|
|
20324
|
-
|
|
20325
|
-
|
|
19866
|
+
this.expect("]");
|
|
19867
|
+
const filters = this.parseSelectorFilters(filterStr);
|
|
19868
|
+
return { varName, filters };
|
|
19869
|
+
}
|
|
19870
|
+
return { varName };
|
|
19871
|
+
}
|
|
19872
|
+
parseSelectorValue(value) {
|
|
19873
|
+
const bracketIndex = value.indexOf("[");
|
|
19874
|
+
if (bracketIndex === -1) {
|
|
19875
|
+
return { kind: value };
|
|
19876
|
+
}
|
|
19877
|
+
const kind = value.slice(0, bracketIndex);
|
|
19878
|
+
const paramsStr = value.slice(bracketIndex + 1, -1);
|
|
19879
|
+
const filters = this.parseSelectorFilters(paramsStr);
|
|
19880
|
+
return { kind, filters };
|
|
19881
|
+
}
|
|
19882
|
+
parseSelectorFilters(paramsStr) {
|
|
19883
|
+
const filters = {};
|
|
19884
|
+
const parts = this.splitSelectorParams(paramsStr);
|
|
19885
|
+
for (const part of parts) {
|
|
19886
|
+
const eqIndex = part.indexOf("=");
|
|
19887
|
+
if (eqIndex === -1)
|
|
20326
19888
|
continue;
|
|
19889
|
+
const key = part.slice(0, eqIndex).trim();
|
|
19890
|
+
const val = part.slice(eqIndex + 1).trim();
|
|
19891
|
+
switch (key) {
|
|
19892
|
+
case "type":
|
|
19893
|
+
filters.type = val;
|
|
19894
|
+
break;
|
|
19895
|
+
case "distance":
|
|
19896
|
+
filters.distance = this.parseRangeValue(val);
|
|
19897
|
+
break;
|
|
19898
|
+
case "tag":
|
|
19899
|
+
if (val.startsWith("!")) {
|
|
19900
|
+
filters.notTag = filters.notTag ?? [];
|
|
19901
|
+
filters.notTag.push(val.slice(1));
|
|
19902
|
+
} else {
|
|
19903
|
+
filters.tag = filters.tag ?? [];
|
|
19904
|
+
filters.tag.push(val);
|
|
19905
|
+
}
|
|
19906
|
+
break;
|
|
19907
|
+
case "limit":
|
|
19908
|
+
filters.limit = parseInt(val, 10);
|
|
19909
|
+
break;
|
|
19910
|
+
case "sort":
|
|
19911
|
+
filters.sort = val;
|
|
19912
|
+
break;
|
|
19913
|
+
case "nbt":
|
|
19914
|
+
filters.nbt = val;
|
|
19915
|
+
break;
|
|
19916
|
+
case "gamemode":
|
|
19917
|
+
filters.gamemode = val;
|
|
19918
|
+
break;
|
|
19919
|
+
case "scores":
|
|
19920
|
+
filters.scores = this.parseScoresFilter(val);
|
|
19921
|
+
break;
|
|
19922
|
+
case "x":
|
|
19923
|
+
filters.x = this.parseRangeValue(val);
|
|
19924
|
+
break;
|
|
19925
|
+
case "y":
|
|
19926
|
+
filters.y = this.parseRangeValue(val);
|
|
19927
|
+
break;
|
|
19928
|
+
case "z":
|
|
19929
|
+
filters.z = this.parseRangeValue(val);
|
|
19930
|
+
break;
|
|
19931
|
+
case "x_rotation":
|
|
19932
|
+
filters.x_rotation = this.parseRangeValue(val);
|
|
19933
|
+
break;
|
|
19934
|
+
case "y_rotation":
|
|
19935
|
+
filters.y_rotation = this.parseRangeValue(val);
|
|
19936
|
+
break;
|
|
20327
19937
|
}
|
|
20328
|
-
|
|
20329
|
-
|
|
20330
|
-
|
|
20331
|
-
|
|
19938
|
+
}
|
|
19939
|
+
return filters;
|
|
19940
|
+
}
|
|
19941
|
+
splitSelectorParams(str) {
|
|
19942
|
+
const parts = [];
|
|
19943
|
+
let current = "";
|
|
19944
|
+
let depth = 0;
|
|
19945
|
+
for (const char of str) {
|
|
19946
|
+
if (char === "{" || char === "[")
|
|
19947
|
+
depth++;
|
|
19948
|
+
else if (char === "}" || char === "]")
|
|
19949
|
+
depth--;
|
|
19950
|
+
else if (char === "," && depth === 0) {
|
|
19951
|
+
parts.push(current.trim());
|
|
19952
|
+
current = "";
|
|
20332
19953
|
continue;
|
|
20333
19954
|
}
|
|
20334
|
-
|
|
19955
|
+
current += char;
|
|
20335
19956
|
}
|
|
20336
|
-
|
|
19957
|
+
if (current.trim())
|
|
19958
|
+
parts.push(current.trim());
|
|
19959
|
+
return parts;
|
|
20337
19960
|
}
|
|
20338
|
-
|
|
20339
|
-
|
|
20340
|
-
const
|
|
20341
|
-
|
|
20342
|
-
|
|
20343
|
-
|
|
20344
|
-
|
|
20345
|
-
|
|
20346
|
-
|
|
20347
|
-
return true;
|
|
20348
|
-
return false;
|
|
19961
|
+
parseScoresFilter(val) {
|
|
19962
|
+
const scores = {};
|
|
19963
|
+
const inner = val.slice(1, -1);
|
|
19964
|
+
const parts = inner.split(",");
|
|
19965
|
+
for (const part of parts) {
|
|
19966
|
+
const [name, range] = part.split("=").map((s) => s.trim());
|
|
19967
|
+
scores[name] = this.parseRangeValue(range);
|
|
19968
|
+
}
|
|
19969
|
+
return scores;
|
|
20349
19970
|
}
|
|
20350
|
-
|
|
20351
|
-
|
|
20352
|
-
|
|
20353
|
-
|
|
20354
|
-
|
|
20355
|
-
|
|
19971
|
+
parseRangeValue(value) {
|
|
19972
|
+
if (value.startsWith("..=")) {
|
|
19973
|
+
const rest = value.slice(3);
|
|
19974
|
+
if (!rest)
|
|
19975
|
+
return {};
|
|
19976
|
+
return { max: parseInt(rest, 10) };
|
|
20356
19977
|
}
|
|
20357
|
-
|
|
19978
|
+
if (value.startsWith("..")) {
|
|
19979
|
+
const rest = value.slice(2);
|
|
19980
|
+
if (!rest)
|
|
19981
|
+
return {};
|
|
19982
|
+
return { max: parseInt(rest, 10) };
|
|
19983
|
+
}
|
|
19984
|
+
const inclIdx = value.indexOf("..=");
|
|
19985
|
+
if (inclIdx !== -1) {
|
|
19986
|
+
const min = parseInt(value.slice(0, inclIdx), 10);
|
|
19987
|
+
const rest = value.slice(inclIdx + 3);
|
|
19988
|
+
if (!rest)
|
|
19989
|
+
return { min };
|
|
19990
|
+
return { min, max: parseInt(rest, 10) };
|
|
19991
|
+
}
|
|
19992
|
+
const dotIndex = value.indexOf("..");
|
|
19993
|
+
if (dotIndex !== -1) {
|
|
19994
|
+
const min = parseInt(value.slice(0, dotIndex), 10);
|
|
19995
|
+
const rest = value.slice(dotIndex + 2);
|
|
19996
|
+
if (!rest)
|
|
19997
|
+
return { min };
|
|
19998
|
+
return { min, max: parseInt(rest, 10) };
|
|
19999
|
+
}
|
|
20000
|
+
const val = parseInt(value, 10);
|
|
20001
|
+
return { min: val, max: val };
|
|
20358
20002
|
}
|
|
20359
|
-
|
|
20003
|
+
// -------------------------------------------------------------------------
|
|
20004
|
+
// Coord token (used by stmt-parser for execute subcommands)
|
|
20005
|
+
// -------------------------------------------------------------------------
|
|
20006
|
+
parseCoordToken() {
|
|
20360
20007
|
const token = this.peek();
|
|
20361
|
-
if (token.kind === "
|
|
20362
|
-
|
|
20363
|
-
|
|
20364
|
-
|
|
20365
|
-
|
|
20366
|
-
|
|
20367
|
-
|
|
20368
|
-
|
|
20369
|
-
|
|
20370
|
-
|
|
20371
|
-
|
|
20372
|
-
|
|
20373
|
-
|
|
20374
|
-
|
|
20375
|
-
|
|
20376
|
-
|
|
20377
|
-
|
|
20378
|
-
|
|
20379
|
-
|
|
20008
|
+
if (token.kind === "rel_coord" || token.kind === "local_coord" || token.kind === "int_lit" || token.kind === "float_lit" || token.kind === "-" || token.kind === "ident") {
|
|
20009
|
+
return this.advance().value;
|
|
20010
|
+
}
|
|
20011
|
+
return this.error(`Expected coordinate, got ${token.kind}`);
|
|
20012
|
+
}
|
|
20013
|
+
parseBlockId() {
|
|
20014
|
+
let id = this.advance().value;
|
|
20015
|
+
if (this.match(":"))
|
|
20016
|
+
id += ":" + this.advance().value;
|
|
20017
|
+
if (this.check("[")) {
|
|
20018
|
+
id += this.advance().value;
|
|
20019
|
+
while (!this.check("]") && !this.check("eof"))
|
|
20020
|
+
id += this.advance().value;
|
|
20021
|
+
id += this.advance().value;
|
|
20022
|
+
}
|
|
20023
|
+
return id;
|
|
20024
|
+
}
|
|
20025
|
+
};
|
|
20026
|
+
exports2.ExprParser = ExprParser;
|
|
20027
|
+
}
|
|
20028
|
+
});
|
|
20029
|
+
|
|
20030
|
+
// ../../dist/src/parser/stmt-parser.js
|
|
20031
|
+
var require_stmt_parser = __commonJS({
|
|
20032
|
+
"../../dist/src/parser/stmt-parser.js"(exports2) {
|
|
20033
|
+
"use strict";
|
|
20034
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
20035
|
+
exports2.StmtParser = void 0;
|
|
20036
|
+
var diagnostics_1 = require_diagnostics();
|
|
20037
|
+
var expr_parser_1 = require_expr_parser();
|
|
20038
|
+
var StmtParser = class extends expr_parser_1.ExprParser {
|
|
20039
|
+
// -------------------------------------------------------------------------
|
|
20040
|
+
// Block
|
|
20041
|
+
// -------------------------------------------------------------------------
|
|
20042
|
+
parseBlock() {
|
|
20043
|
+
this.expect("{");
|
|
20044
|
+
const stmts = [];
|
|
20045
|
+
while (!this.check("}") && !this.check("eof")) {
|
|
20046
|
+
try {
|
|
20047
|
+
stmts.push(this.parseStmt());
|
|
20048
|
+
} catch (err) {
|
|
20049
|
+
if (err instanceof diagnostics_1.DiagnosticError) {
|
|
20050
|
+
this.parseErrors.push(err);
|
|
20051
|
+
this.syncToNextStmt();
|
|
20052
|
+
} else {
|
|
20053
|
+
throw err;
|
|
20380
20054
|
}
|
|
20381
|
-
this.advance();
|
|
20382
|
-
const args = this.parseArgs();
|
|
20383
|
-
this.expect(")");
|
|
20384
|
-
return this.withLoc({ kind: "static_call", type: typeToken.value, method: memberToken.value, args }, typeToken);
|
|
20385
20055
|
}
|
|
20386
|
-
return this.withLoc({ kind: "path_expr", enumName: typeToken.value, variant: memberToken.value }, typeToken);
|
|
20387
|
-
}
|
|
20388
|
-
if (token.kind === "ident" && this.peek(1).kind === "=>") {
|
|
20389
|
-
return this.parseSingleParamLambda();
|
|
20390
20056
|
}
|
|
20391
|
-
|
|
20392
|
-
|
|
20393
|
-
|
|
20057
|
+
this.expect("}");
|
|
20058
|
+
return stmts;
|
|
20059
|
+
}
|
|
20060
|
+
// -------------------------------------------------------------------------
|
|
20061
|
+
// Statement dispatch
|
|
20062
|
+
// -------------------------------------------------------------------------
|
|
20063
|
+
parseStmt() {
|
|
20064
|
+
if (this.check("let"))
|
|
20065
|
+
return this.parseLetStmt();
|
|
20066
|
+
if (this.check("const"))
|
|
20067
|
+
return this.parseLocalConstDecl();
|
|
20068
|
+
if (this.check("return"))
|
|
20069
|
+
return this.parseReturnStmt();
|
|
20070
|
+
if (this.check("break")) {
|
|
20071
|
+
const token = this.advance();
|
|
20072
|
+
if (this.check("ident")) {
|
|
20073
|
+
const labelToken = this.advance();
|
|
20074
|
+
this.match(";");
|
|
20075
|
+
return this.withLoc({ kind: "break_label", label: labelToken.value }, token);
|
|
20076
|
+
}
|
|
20077
|
+
this.match(";");
|
|
20078
|
+
return this.withLoc({ kind: "break" }, token);
|
|
20394
20079
|
}
|
|
20395
|
-
if (
|
|
20396
|
-
this.advance();
|
|
20397
|
-
|
|
20080
|
+
if (this.check("continue")) {
|
|
20081
|
+
const token = this.advance();
|
|
20082
|
+
if (this.check("ident")) {
|
|
20083
|
+
const labelToken = this.advance();
|
|
20084
|
+
this.match(";");
|
|
20085
|
+
return this.withLoc({ kind: "continue_label", label: labelToken.value }, token);
|
|
20086
|
+
}
|
|
20087
|
+
this.match(";");
|
|
20088
|
+
return this.withLoc({ kind: "continue" }, token);
|
|
20398
20089
|
}
|
|
20399
|
-
if (
|
|
20090
|
+
if (this.check("if"))
|
|
20091
|
+
return this.parseIfStmt();
|
|
20092
|
+
if (this.check("ident") && this.peek(1).kind === ":") {
|
|
20093
|
+
const labelToken = this.advance();
|
|
20400
20094
|
this.advance();
|
|
20401
|
-
|
|
20095
|
+
let loopStmt;
|
|
20096
|
+
if (this.check("while")) {
|
|
20097
|
+
loopStmt = this.parseWhileStmt();
|
|
20098
|
+
} else if (this.check("for")) {
|
|
20099
|
+
loopStmt = this.parseForStmt();
|
|
20100
|
+
} else if (this.check("foreach")) {
|
|
20101
|
+
loopStmt = this.parseForeachStmt();
|
|
20102
|
+
} else if (this.check("repeat")) {
|
|
20103
|
+
loopStmt = this.parseRepeatStmt();
|
|
20104
|
+
} else {
|
|
20105
|
+
throw new diagnostics_1.DiagnosticError("ParseError", `Expected loop statement after label '${labelToken.value}:', found '${this.peek().kind}'`, { line: labelToken.line, col: labelToken.col });
|
|
20106
|
+
}
|
|
20107
|
+
return this.withLoc({ kind: "labeled_loop", label: labelToken.value, body: loopStmt }, labelToken);
|
|
20402
20108
|
}
|
|
20403
|
-
if (
|
|
20404
|
-
this.
|
|
20405
|
-
|
|
20109
|
+
if (this.check("while"))
|
|
20110
|
+
return this.parseWhileStmt();
|
|
20111
|
+
if (this.check("do"))
|
|
20112
|
+
return this.parseDoWhileStmt();
|
|
20113
|
+
if (this.check("repeat"))
|
|
20114
|
+
return this.parseRepeatStmt();
|
|
20115
|
+
if (this.check("for"))
|
|
20116
|
+
return this.parseForStmt();
|
|
20117
|
+
if (this.check("foreach"))
|
|
20118
|
+
return this.parseForeachStmt();
|
|
20119
|
+
if (this.check("match"))
|
|
20120
|
+
return this.parseMatchStmt();
|
|
20121
|
+
if (this.check("as"))
|
|
20122
|
+
return this.parseAsStmt();
|
|
20123
|
+
if (this.check("at"))
|
|
20124
|
+
return this.parseAtStmt();
|
|
20125
|
+
if (this.check("execute"))
|
|
20126
|
+
return this.parseExecuteStmt();
|
|
20127
|
+
if (this.check("raw_cmd")) {
|
|
20128
|
+
const token = this.advance();
|
|
20129
|
+
const cmd = token.value;
|
|
20130
|
+
this.match(";");
|
|
20131
|
+
return this.withLoc({ kind: "raw", cmd }, token);
|
|
20406
20132
|
}
|
|
20407
|
-
|
|
20133
|
+
return this.parseExprStmt();
|
|
20134
|
+
}
|
|
20135
|
+
// -------------------------------------------------------------------------
|
|
20136
|
+
// Individual statement parsers
|
|
20137
|
+
// -------------------------------------------------------------------------
|
|
20138
|
+
parseLetStmt() {
|
|
20139
|
+
const letToken = this.expect("let");
|
|
20140
|
+
if (this.check("(")) {
|
|
20408
20141
|
this.advance();
|
|
20409
|
-
|
|
20142
|
+
const names = [];
|
|
20143
|
+
do {
|
|
20144
|
+
names.push(this.expect("ident").value);
|
|
20145
|
+
} while (this.match(","));
|
|
20146
|
+
this.expect(")");
|
|
20147
|
+
let type2;
|
|
20148
|
+
if (this.match(":"))
|
|
20149
|
+
type2 = this.parseType();
|
|
20150
|
+
this.expect("=");
|
|
20151
|
+
const init2 = this.parseExpr();
|
|
20152
|
+
this.match(";");
|
|
20153
|
+
return this.withLoc({ kind: "let_destruct", names, type: type2, init: init2 }, letToken);
|
|
20410
20154
|
}
|
|
20411
|
-
|
|
20412
|
-
|
|
20413
|
-
|
|
20155
|
+
const name = this.expect("ident").value;
|
|
20156
|
+
let type;
|
|
20157
|
+
if (this.match(":"))
|
|
20158
|
+
type = this.parseType();
|
|
20159
|
+
this.expect("=");
|
|
20160
|
+
const init = this.parseExpr();
|
|
20161
|
+
this.match(";");
|
|
20162
|
+
return this.withLoc({ kind: "let", name, type, init }, letToken);
|
|
20163
|
+
}
|
|
20164
|
+
parseLocalConstDecl() {
|
|
20165
|
+
const constToken = this.expect("const");
|
|
20166
|
+
const name = this.expect("ident").value;
|
|
20167
|
+
this.expect(":");
|
|
20168
|
+
const type = this.parseType();
|
|
20169
|
+
this.expect("=");
|
|
20170
|
+
const value = this.parseExpr();
|
|
20171
|
+
this.match(";");
|
|
20172
|
+
return this.withLoc({ kind: "const_decl", name, type, value }, constToken);
|
|
20173
|
+
}
|
|
20174
|
+
parseReturnStmt() {
|
|
20175
|
+
const returnToken = this.expect("return");
|
|
20176
|
+
let value;
|
|
20177
|
+
if (!this.check(";") && !this.check("}") && !this.check("eof")) {
|
|
20178
|
+
value = this.parseExpr();
|
|
20414
20179
|
}
|
|
20415
|
-
|
|
20180
|
+
this.match(";");
|
|
20181
|
+
return this.withLoc({ kind: "return", value }, returnToken);
|
|
20182
|
+
}
|
|
20183
|
+
parseIfStmt() {
|
|
20184
|
+
const ifToken = this.expect("if");
|
|
20185
|
+
if (this.check("let") && this.peek(1).kind === "ident" && this.peek(1).value === "Some") {
|
|
20416
20186
|
this.advance();
|
|
20417
|
-
return this.withLoc({ kind: "long_lit", value: parseInt(token.value.slice(0, -1), 10) }, token);
|
|
20418
|
-
}
|
|
20419
|
-
if (token.kind === "double_lit") {
|
|
20420
20187
|
this.advance();
|
|
20421
|
-
|
|
20188
|
+
this.expect("(");
|
|
20189
|
+
const binding = this.expect("ident").value;
|
|
20190
|
+
this.expect(")");
|
|
20191
|
+
this.expect("=");
|
|
20192
|
+
const init = this.parseExpr();
|
|
20193
|
+
const then2 = this.parseBlock();
|
|
20194
|
+
let else_2;
|
|
20195
|
+
if (this.match("else")) {
|
|
20196
|
+
else_2 = this.check("if") ? [this.parseIfStmt()] : this.parseBlock();
|
|
20197
|
+
}
|
|
20198
|
+
return this.withLoc({ kind: "if_let_some", binding, init, then: then2, else_: else_2 }, ifToken);
|
|
20422
20199
|
}
|
|
20423
|
-
|
|
20424
|
-
|
|
20425
|
-
|
|
20200
|
+
const cond = this.parseParenOptionalCond();
|
|
20201
|
+
const then = this.parseBlock();
|
|
20202
|
+
let else_;
|
|
20203
|
+
if (this.match("else")) {
|
|
20204
|
+
else_ = this.check("if") ? [this.parseIfStmt()] : this.parseBlock();
|
|
20426
20205
|
}
|
|
20427
|
-
|
|
20206
|
+
return this.withLoc({ kind: "if", cond, then, else_ }, ifToken);
|
|
20207
|
+
}
|
|
20208
|
+
parseWhileStmt() {
|
|
20209
|
+
const whileToken = this.expect("while");
|
|
20210
|
+
if (this.check("let") && this.peek(1).kind === "ident" && this.peek(1).value === "Some") {
|
|
20428
20211
|
this.advance();
|
|
20429
|
-
return this.parseFStringExpr(token);
|
|
20430
|
-
}
|
|
20431
|
-
if (token.kind === "mc_name") {
|
|
20432
20212
|
this.advance();
|
|
20433
|
-
|
|
20213
|
+
this.expect("(");
|
|
20214
|
+
const binding = this.expect("ident").value;
|
|
20215
|
+
this.expect(")");
|
|
20216
|
+
this.expect("=");
|
|
20217
|
+
const init = this.parseExpr();
|
|
20218
|
+
const body2 = this.parseBlock();
|
|
20219
|
+
return this.withLoc({ kind: "while_let_some", binding, init, body: body2 }, whileToken);
|
|
20434
20220
|
}
|
|
20435
|
-
|
|
20436
|
-
|
|
20437
|
-
|
|
20221
|
+
const cond = this.parseParenOptionalCond();
|
|
20222
|
+
const body = this.parseBlock();
|
|
20223
|
+
return this.withLoc({ kind: "while", cond, body }, whileToken);
|
|
20224
|
+
}
|
|
20225
|
+
parseDoWhileStmt() {
|
|
20226
|
+
const doToken = this.expect("do");
|
|
20227
|
+
const body = this.parseBlock();
|
|
20228
|
+
this.expect("while");
|
|
20229
|
+
const cond = this.parseParenOptionalCond();
|
|
20230
|
+
this.match(";");
|
|
20231
|
+
return this.withLoc({ kind: "do_while", cond, body }, doToken);
|
|
20232
|
+
}
|
|
20233
|
+
parseRepeatStmt() {
|
|
20234
|
+
const repeatToken = this.expect("repeat");
|
|
20235
|
+
const countToken = this.expect("int_lit");
|
|
20236
|
+
const count = parseInt(countToken.value, 10);
|
|
20237
|
+
const body = this.parseBlock();
|
|
20238
|
+
return this.withLoc({ kind: "repeat", count, body }, repeatToken);
|
|
20239
|
+
}
|
|
20240
|
+
parseParenOptionalCond() {
|
|
20241
|
+
if (this.match("(")) {
|
|
20242
|
+
const cond = this.parseExpr();
|
|
20243
|
+
this.expect(")");
|
|
20244
|
+
return cond;
|
|
20438
20245
|
}
|
|
20439
|
-
|
|
20440
|
-
|
|
20441
|
-
|
|
20246
|
+
return this.parseExpr();
|
|
20247
|
+
}
|
|
20248
|
+
parseForStmt() {
|
|
20249
|
+
const forToken = this.expect("for");
|
|
20250
|
+
if (this.check("ident") && this.peek(1).kind === "in") {
|
|
20251
|
+
return this.parseForRangeStmt(forToken);
|
|
20442
20252
|
}
|
|
20443
|
-
|
|
20253
|
+
this.expect("(");
|
|
20254
|
+
if (this.check("let") && this.peek(1).kind === "ident" && this.peek(2).kind === "in" && this.peek(3).kind === "ident" && this.peek(4).kind === ",") {
|
|
20444
20255
|
this.advance();
|
|
20445
|
-
|
|
20256
|
+
const binding = this.expect("ident").value;
|
|
20257
|
+
this.expect("in");
|
|
20258
|
+
const arrayName = this.expect("ident").value;
|
|
20259
|
+
this.expect(",");
|
|
20260
|
+
const lenExpr = this.parseExpr();
|
|
20261
|
+
this.expect(")");
|
|
20262
|
+
const body2 = this.parseBlock();
|
|
20263
|
+
return this.withLoc({ kind: "for_in_array", binding, arrayName, lenExpr, body: body2 }, forToken);
|
|
20446
20264
|
}
|
|
20447
|
-
|
|
20448
|
-
|
|
20449
|
-
|
|
20450
|
-
|
|
20451
|
-
|
|
20452
|
-
|
|
20453
|
-
|
|
20454
|
-
|
|
20265
|
+
let init;
|
|
20266
|
+
if (this.check("let")) {
|
|
20267
|
+
const letToken = this.expect("let");
|
|
20268
|
+
const name = this.expect("ident").value;
|
|
20269
|
+
let type;
|
|
20270
|
+
if (this.match(":"))
|
|
20271
|
+
type = this.parseType();
|
|
20272
|
+
this.expect("=");
|
|
20273
|
+
const initExpr = this.parseExpr();
|
|
20274
|
+
const initStmt = { kind: "let", name, type, init: initExpr };
|
|
20275
|
+
init = this.withLoc(initStmt, letToken);
|
|
20455
20276
|
}
|
|
20456
|
-
|
|
20457
|
-
|
|
20458
|
-
|
|
20277
|
+
this.expect(";");
|
|
20278
|
+
const cond = this.parseExpr();
|
|
20279
|
+
this.expect(";");
|
|
20280
|
+
const step = this.parseExpr();
|
|
20281
|
+
this.expect(")");
|
|
20282
|
+
const body = this.parseBlock();
|
|
20283
|
+
return this.withLoc({ kind: "for", init, cond, step, body }, forToken);
|
|
20284
|
+
}
|
|
20285
|
+
parseForRangeStmt(forToken) {
|
|
20286
|
+
const varName = this.expect("ident").value;
|
|
20287
|
+
this.expect("in");
|
|
20288
|
+
let start;
|
|
20289
|
+
let end;
|
|
20290
|
+
let inclusive = false;
|
|
20291
|
+
if (this.check("range_lit")) {
|
|
20292
|
+
const rangeToken = this.advance();
|
|
20293
|
+
const raw = rangeToken.value;
|
|
20294
|
+
inclusive = raw.includes("..=");
|
|
20295
|
+
const range = this.parseRangeValue(raw);
|
|
20296
|
+
start = this.withLoc({ kind: "int_lit", value: range.min ?? 0 }, rangeToken);
|
|
20297
|
+
if (range.max !== null && range.max !== void 0) {
|
|
20298
|
+
end = this.withLoc({ kind: "int_lit", value: range.max }, rangeToken);
|
|
20299
|
+
} else {
|
|
20300
|
+
end = this.parseUnaryExpr();
|
|
20301
|
+
}
|
|
20302
|
+
} else {
|
|
20303
|
+
const arrayOrStart = this.parseExpr();
|
|
20304
|
+
if (!this.check("range_lit")) {
|
|
20305
|
+
const body2 = this.parseBlock();
|
|
20306
|
+
return this.withLoc({ kind: "for_each", binding: varName, array: arrayOrStart, body: body2 }, forToken);
|
|
20307
|
+
}
|
|
20308
|
+
start = arrayOrStart;
|
|
20309
|
+
if (this.check("range_lit")) {
|
|
20310
|
+
const rangeOp = this.advance();
|
|
20311
|
+
inclusive = rangeOp.value.includes("=");
|
|
20312
|
+
const afterOp = rangeOp.value.replace(/^\.\.=?/, "");
|
|
20313
|
+
if (afterOp.length > 0) {
|
|
20314
|
+
end = this.withLoc({ kind: "int_lit", value: parseInt(afterOp, 10) }, rangeOp);
|
|
20315
|
+
} else {
|
|
20316
|
+
end = this.parseExpr();
|
|
20317
|
+
}
|
|
20318
|
+
} else {
|
|
20319
|
+
this.error("Expected .. or ..= in for-range expression. Example: for i in 0..10 { ... }");
|
|
20320
|
+
}
|
|
20459
20321
|
}
|
|
20460
|
-
|
|
20461
|
-
|
|
20462
|
-
|
|
20463
|
-
|
|
20464
|
-
|
|
20465
|
-
|
|
20322
|
+
const body = this.parseBlock();
|
|
20323
|
+
return this.withLoc({ kind: "for_range", varName, start, end, inclusive, body }, forToken);
|
|
20324
|
+
}
|
|
20325
|
+
parseForeachStmt() {
|
|
20326
|
+
const foreachToken = this.expect("foreach");
|
|
20327
|
+
this.expect("(");
|
|
20328
|
+
const binding = this.expect("ident").value;
|
|
20329
|
+
this.expect("in");
|
|
20330
|
+
const iterable = this.parseExpr();
|
|
20331
|
+
this.expect(")");
|
|
20332
|
+
let executeContext;
|
|
20333
|
+
const execIdentKeywords = ["positioned", "rotated", "facing", "anchored", "align", "on", "summon"];
|
|
20334
|
+
if (this.check("as") || this.check("at") || this.check("in") || this.check("ident") && execIdentKeywords.includes(this.peek().value)) {
|
|
20335
|
+
let context = "";
|
|
20336
|
+
while (!this.check("{") && !this.check("eof")) {
|
|
20337
|
+
context += this.advance().value + " ";
|
|
20338
|
+
}
|
|
20339
|
+
executeContext = context.trim();
|
|
20466
20340
|
}
|
|
20467
|
-
|
|
20341
|
+
const body = this.parseBlock();
|
|
20342
|
+
return this.withLoc({ kind: "foreach", binding, iterable, body, executeContext }, foreachToken);
|
|
20343
|
+
}
|
|
20344
|
+
// -------------------------------------------------------------------------
|
|
20345
|
+
// Match
|
|
20346
|
+
// -------------------------------------------------------------------------
|
|
20347
|
+
parseMatchPattern() {
|
|
20348
|
+
if (this.check("ident") && this.peek().value === "_") {
|
|
20468
20349
|
this.advance();
|
|
20469
|
-
return
|
|
20350
|
+
return { kind: "PatWild" };
|
|
20470
20351
|
}
|
|
20471
|
-
if (
|
|
20352
|
+
if (this.check("ident") && this.peek().value === "None") {
|
|
20472
20353
|
this.advance();
|
|
20473
|
-
return
|
|
20354
|
+
return { kind: "PatNone" };
|
|
20474
20355
|
}
|
|
20475
|
-
if (
|
|
20476
|
-
if (this.isBlockPosLiteral()) {
|
|
20477
|
-
return this.parseBlockPos();
|
|
20478
|
-
}
|
|
20479
|
-
if (this.isLambdaStart()) {
|
|
20480
|
-
return this.parseLambdaExpr();
|
|
20481
|
-
}
|
|
20356
|
+
if (this.check("ident") && this.peek().value === "Some") {
|
|
20482
20357
|
this.advance();
|
|
20483
|
-
|
|
20484
|
-
|
|
20485
|
-
|
|
20486
|
-
|
|
20487
|
-
|
|
20488
|
-
|
|
20489
|
-
|
|
20358
|
+
this.expect("(");
|
|
20359
|
+
const binding = this.expect("ident").value;
|
|
20360
|
+
this.expect(")");
|
|
20361
|
+
return { kind: "PatSome", binding };
|
|
20362
|
+
}
|
|
20363
|
+
if (this.check("ident") && this.peek(1).kind === "::") {
|
|
20364
|
+
const enumName = this.advance().value;
|
|
20365
|
+
this.expect("::");
|
|
20366
|
+
const variant = this.expect("ident").value;
|
|
20367
|
+
const bindings = [];
|
|
20368
|
+
if (this.check("(")) {
|
|
20369
|
+
this.advance();
|
|
20370
|
+
while (!this.check(")") && !this.check("eof")) {
|
|
20371
|
+
bindings.push(this.expect("ident").value);
|
|
20372
|
+
if (!this.match(","))
|
|
20373
|
+
break;
|
|
20490
20374
|
}
|
|
20491
20375
|
this.expect(")");
|
|
20492
|
-
return this.withLoc({ kind: "tuple_lit", elements }, token);
|
|
20493
20376
|
}
|
|
20494
|
-
|
|
20495
|
-
return first;
|
|
20377
|
+
return { kind: "PatEnum", enumName, variant, bindings };
|
|
20496
20378
|
}
|
|
20497
|
-
if (
|
|
20498
|
-
|
|
20379
|
+
if (this.check("int_lit")) {
|
|
20380
|
+
const tok = this.advance();
|
|
20381
|
+
return { kind: "PatInt", value: parseInt(tok.value, 10) };
|
|
20499
20382
|
}
|
|
20500
|
-
if (
|
|
20501
|
-
|
|
20383
|
+
if (this.check("-") && this.peek(1).kind === "int_lit") {
|
|
20384
|
+
this.advance();
|
|
20385
|
+
const tok = this.advance();
|
|
20386
|
+
return { kind: "PatInt", value: -parseInt(tok.value, 10) };
|
|
20502
20387
|
}
|
|
20503
|
-
this.
|
|
20388
|
+
const e = this.parseExpr();
|
|
20389
|
+
return { kind: "PatExpr", expr: e };
|
|
20504
20390
|
}
|
|
20505
|
-
|
|
20506
|
-
|
|
20391
|
+
parseMatchStmt() {
|
|
20392
|
+
const matchToken = this.expect("match");
|
|
20393
|
+
let expr;
|
|
20394
|
+
if (this.check("(")) {
|
|
20507
20395
|
this.advance();
|
|
20508
|
-
|
|
20509
|
-
|
|
20510
|
-
|
|
20511
|
-
|
|
20512
|
-
}
|
|
20513
|
-
if (token.kind === "float_lit") {
|
|
20514
|
-
this.advance();
|
|
20515
|
-
return this.withLoc({ kind: "float_lit", value: -Number(token.value) }, token);
|
|
20516
|
-
}
|
|
20517
|
-
this.error("Expected number after unary -");
|
|
20396
|
+
expr = this.parseExpr();
|
|
20397
|
+
this.expect(")");
|
|
20398
|
+
} else {
|
|
20399
|
+
expr = this.parseExpr();
|
|
20518
20400
|
}
|
|
20519
|
-
|
|
20520
|
-
|
|
20521
|
-
|
|
20401
|
+
this.expect("{");
|
|
20402
|
+
const arms = [];
|
|
20403
|
+
while (!this.check("}") && !this.check("eof")) {
|
|
20404
|
+
const pattern = this.parseMatchPattern();
|
|
20405
|
+
this.expect("=>");
|
|
20406
|
+
const body = this.parseBlock();
|
|
20407
|
+
this.match(",");
|
|
20408
|
+
arms.push({ pattern, body });
|
|
20522
20409
|
}
|
|
20523
|
-
this.
|
|
20524
|
-
|
|
20525
|
-
parseSingleParamLambda() {
|
|
20526
|
-
const paramToken = this.expect("ident");
|
|
20527
|
-
const params = [{ name: paramToken.value }];
|
|
20528
|
-
this.expect("=>");
|
|
20529
|
-
return this.finishLambdaExpr(params, paramToken);
|
|
20410
|
+
this.expect("}");
|
|
20411
|
+
return this.withLoc({ kind: "match", expr, arms }, matchToken);
|
|
20530
20412
|
}
|
|
20531
|
-
|
|
20532
|
-
|
|
20533
|
-
|
|
20534
|
-
|
|
20535
|
-
|
|
20536
|
-
|
|
20537
|
-
|
|
20538
|
-
|
|
20539
|
-
|
|
20540
|
-
|
|
20541
|
-
params.push({ name, type });
|
|
20542
|
-
} while (this.match(","));
|
|
20543
|
-
}
|
|
20544
|
-
this.expect(")");
|
|
20545
|
-
let returnType;
|
|
20546
|
-
if (this.match("->")) {
|
|
20547
|
-
returnType = this.parseType();
|
|
20413
|
+
// -------------------------------------------------------------------------
|
|
20414
|
+
// As / At / Execute
|
|
20415
|
+
// -------------------------------------------------------------------------
|
|
20416
|
+
parseAsStmt() {
|
|
20417
|
+
const asToken = this.expect("as");
|
|
20418
|
+
const as_sel = this.parseSelector();
|
|
20419
|
+
if (this.match("at")) {
|
|
20420
|
+
const at_sel = this.parseSelector();
|
|
20421
|
+
const body2 = this.parseBlock();
|
|
20422
|
+
return this.withLoc({ kind: "as_at", as_sel, at_sel, body: body2 }, asToken);
|
|
20548
20423
|
}
|
|
20549
|
-
this.
|
|
20550
|
-
return this.
|
|
20424
|
+
const body = this.parseBlock();
|
|
20425
|
+
return this.withLoc({ kind: "as_block", selector: as_sel, body }, asToken);
|
|
20551
20426
|
}
|
|
20552
|
-
|
|
20553
|
-
const
|
|
20554
|
-
|
|
20427
|
+
parseAtStmt() {
|
|
20428
|
+
const atToken = this.expect("at");
|
|
20429
|
+
const selector = this.parseSelector();
|
|
20430
|
+
const body = this.parseBlock();
|
|
20431
|
+
return this.withLoc({ kind: "at_block", selector, body }, atToken);
|
|
20555
20432
|
}
|
|
20556
|
-
|
|
20557
|
-
|
|
20558
|
-
|
|
20559
|
-
|
|
20560
|
-
|
|
20561
|
-
|
|
20562
|
-
|
|
20563
|
-
|
|
20564
|
-
|
|
20565
|
-
|
|
20566
|
-
|
|
20567
|
-
|
|
20568
|
-
|
|
20569
|
-
|
|
20570
|
-
|
|
20571
|
-
|
|
20572
|
-
|
|
20573
|
-
|
|
20574
|
-
const
|
|
20575
|
-
|
|
20576
|
-
inString = !inString;
|
|
20577
|
-
}
|
|
20578
|
-
if (!inString) {
|
|
20579
|
-
if (char === "{") {
|
|
20580
|
-
depth++;
|
|
20581
|
-
} else if (char === "}") {
|
|
20582
|
-
depth--;
|
|
20583
|
-
if (depth === 0) {
|
|
20584
|
-
index++;
|
|
20585
|
-
break;
|
|
20586
|
-
}
|
|
20587
|
-
}
|
|
20588
|
-
}
|
|
20589
|
-
if (depth > 0) {
|
|
20590
|
-
exprSource += char;
|
|
20591
|
-
}
|
|
20592
|
-
index++;
|
|
20433
|
+
parseExecuteStmt() {
|
|
20434
|
+
const executeToken = this.expect("execute");
|
|
20435
|
+
const subcommands = [];
|
|
20436
|
+
while (!this.check("run") && !this.check("eof")) {
|
|
20437
|
+
if (this.match("as")) {
|
|
20438
|
+
const selector = this.parseSelector();
|
|
20439
|
+
subcommands.push({ kind: "as", selector });
|
|
20440
|
+
} else if (this.match("at")) {
|
|
20441
|
+
const selector = this.parseSelector();
|
|
20442
|
+
subcommands.push({ kind: "at", selector });
|
|
20443
|
+
} else if (this.checkIdent("positioned")) {
|
|
20444
|
+
this.advance();
|
|
20445
|
+
if (this.match("as")) {
|
|
20446
|
+
const selector = this.parseSelector();
|
|
20447
|
+
subcommands.push({ kind: "positioned_as", selector });
|
|
20448
|
+
} else {
|
|
20449
|
+
const x = this.parseCoordToken();
|
|
20450
|
+
const y = this.parseCoordToken();
|
|
20451
|
+
const z = this.parseCoordToken();
|
|
20452
|
+
subcommands.push({ kind: "positioned", x, y, z });
|
|
20593
20453
|
}
|
|
20594
|
-
|
|
20595
|
-
|
|
20454
|
+
} else if (this.checkIdent("rotated")) {
|
|
20455
|
+
this.advance();
|
|
20456
|
+
if (this.match("as")) {
|
|
20457
|
+
const selector = this.parseSelector();
|
|
20458
|
+
subcommands.push({ kind: "rotated_as", selector });
|
|
20459
|
+
} else {
|
|
20460
|
+
const yaw = this.parseCoordToken();
|
|
20461
|
+
const pitch = this.parseCoordToken();
|
|
20462
|
+
subcommands.push({ kind: "rotated", yaw, pitch });
|
|
20596
20463
|
}
|
|
20597
|
-
|
|
20598
|
-
|
|
20599
|
-
|
|
20600
|
-
|
|
20601
|
-
|
|
20602
|
-
|
|
20603
|
-
|
|
20604
|
-
|
|
20605
|
-
|
|
20606
|
-
|
|
20607
|
-
|
|
20608
|
-
|
|
20609
|
-
const parts = [];
|
|
20610
|
-
let current = "";
|
|
20611
|
-
let index = 0;
|
|
20612
|
-
while (index < token.value.length) {
|
|
20613
|
-
if (token.value[index] === "{") {
|
|
20614
|
-
if (current) {
|
|
20615
|
-
parts.push({ kind: "text", value: current });
|
|
20616
|
-
current = "";
|
|
20464
|
+
} else if (this.checkIdent("facing")) {
|
|
20465
|
+
this.advance();
|
|
20466
|
+
if (this.checkIdent("entity")) {
|
|
20467
|
+
this.advance();
|
|
20468
|
+
const selector = this.parseSelector();
|
|
20469
|
+
const anchor = this.checkIdent("eyes") || this.checkIdent("feet") ? this.advance().value : "feet";
|
|
20470
|
+
subcommands.push({ kind: "facing_entity", selector, anchor });
|
|
20471
|
+
} else {
|
|
20472
|
+
const x = this.parseCoordToken();
|
|
20473
|
+
const y = this.parseCoordToken();
|
|
20474
|
+
const z = this.parseCoordToken();
|
|
20475
|
+
subcommands.push({ kind: "facing", x, y, z });
|
|
20617
20476
|
}
|
|
20618
|
-
|
|
20619
|
-
|
|
20620
|
-
|
|
20621
|
-
|
|
20622
|
-
|
|
20623
|
-
|
|
20624
|
-
|
|
20625
|
-
|
|
20626
|
-
|
|
20627
|
-
|
|
20628
|
-
|
|
20629
|
-
|
|
20630
|
-
|
|
20631
|
-
|
|
20632
|
-
|
|
20633
|
-
|
|
20634
|
-
|
|
20635
|
-
|
|
20636
|
-
|
|
20637
|
-
|
|
20638
|
-
|
|
20639
|
-
|
|
20477
|
+
} else if (this.checkIdent("anchored")) {
|
|
20478
|
+
this.advance();
|
|
20479
|
+
const anchor = this.advance().value;
|
|
20480
|
+
subcommands.push({ kind: "anchored", anchor });
|
|
20481
|
+
} else if (this.checkIdent("align")) {
|
|
20482
|
+
this.advance();
|
|
20483
|
+
const axes = this.advance().value;
|
|
20484
|
+
subcommands.push({ kind: "align", axes });
|
|
20485
|
+
} else if (this.checkIdent("on")) {
|
|
20486
|
+
this.advance();
|
|
20487
|
+
const relation = this.advance().value;
|
|
20488
|
+
subcommands.push({ kind: "on", relation });
|
|
20489
|
+
} else if (this.checkIdent("summon")) {
|
|
20490
|
+
this.advance();
|
|
20491
|
+
const entity = this.advance().value;
|
|
20492
|
+
subcommands.push({ kind: "summon", entity });
|
|
20493
|
+
} else if (this.checkIdent("store")) {
|
|
20494
|
+
this.advance();
|
|
20495
|
+
const storeType = this.advance().value;
|
|
20496
|
+
if (this.checkIdent("score")) {
|
|
20497
|
+
this.advance();
|
|
20498
|
+
const target = this.advance().value;
|
|
20499
|
+
const targetObj = this.advance().value;
|
|
20500
|
+
if (storeType === "result") {
|
|
20501
|
+
subcommands.push({ kind: "store_result", target, targetObj });
|
|
20502
|
+
} else {
|
|
20503
|
+
subcommands.push({ kind: "store_success", target, targetObj });
|
|
20640
20504
|
}
|
|
20641
|
-
|
|
20642
|
-
|
|
20643
|
-
if (depth !== 0) {
|
|
20644
|
-
this.error("Unterminated f-string interpolation");
|
|
20505
|
+
} else {
|
|
20506
|
+
this.error("store currently only supports score target");
|
|
20645
20507
|
}
|
|
20646
|
-
|
|
20647
|
-
|
|
20508
|
+
} else if (this.match("if")) {
|
|
20509
|
+
this.parseExecuteCondition(subcommands, "if");
|
|
20510
|
+
} else if (this.match("unless")) {
|
|
20511
|
+
this.parseExecuteCondition(subcommands, "unless");
|
|
20512
|
+
} else if (this.match("in")) {
|
|
20513
|
+
let dim = this.advance().value;
|
|
20514
|
+
if (this.match(":"))
|
|
20515
|
+
dim += ":" + this.advance().value;
|
|
20516
|
+
subcommands.push({ kind: "in", dimension: dim });
|
|
20517
|
+
} else {
|
|
20518
|
+
this.error(`Unexpected token in execute statement: '${this.peek().value || this.peek().kind}'. Valid subcommands: as, at, positioned, align, facing, rotated, anchored, if, unless, in, store`);
|
|
20648
20519
|
}
|
|
20649
|
-
current += token.value[index];
|
|
20650
|
-
index++;
|
|
20651
|
-
}
|
|
20652
|
-
if (current) {
|
|
20653
|
-
parts.push({ kind: "text", value: current });
|
|
20654
20520
|
}
|
|
20655
|
-
|
|
20521
|
+
this.expect("run");
|
|
20522
|
+
const body = this.parseBlock();
|
|
20523
|
+
return this.withLoc({ kind: "execute", subcommands, body }, executeToken);
|
|
20656
20524
|
}
|
|
20657
|
-
|
|
20658
|
-
|
|
20659
|
-
|
|
20660
|
-
|
|
20661
|
-
|
|
20662
|
-
|
|
20525
|
+
parseExecuteCondition(subcommands, type) {
|
|
20526
|
+
if (this.checkIdent("entity") || this.check("selector")) {
|
|
20527
|
+
if (this.checkIdent("entity"))
|
|
20528
|
+
this.advance();
|
|
20529
|
+
const selectorOrVar = this.parseSelectorOrVarSelector();
|
|
20530
|
+
subcommands.push({ kind: type === "if" ? "if_entity" : "unless_entity", ...selectorOrVar });
|
|
20531
|
+
} else if (this.checkIdent("block")) {
|
|
20532
|
+
this.advance();
|
|
20533
|
+
const x = this.parseCoordToken();
|
|
20534
|
+
const y = this.parseCoordToken();
|
|
20535
|
+
const z = this.parseCoordToken();
|
|
20536
|
+
const block = this.parseBlockId();
|
|
20537
|
+
subcommands.push({ kind: type === "if" ? "if_block" : "unless_block", pos: [x, y, z], block });
|
|
20538
|
+
} else if (this.checkIdent("score")) {
|
|
20539
|
+
this.advance();
|
|
20540
|
+
const target = this.advance().value;
|
|
20541
|
+
const targetObj = this.advance().value;
|
|
20542
|
+
if (this.checkIdent("matches")) {
|
|
20543
|
+
this.advance();
|
|
20544
|
+
const range = this.advance().value;
|
|
20545
|
+
subcommands.push({ kind: type === "if" ? "if_score_range" : "unless_score_range", target, targetObj, range });
|
|
20546
|
+
} else {
|
|
20547
|
+
const op = this.advance().value;
|
|
20548
|
+
const source = this.advance().value;
|
|
20549
|
+
const sourceObj = this.advance().value;
|
|
20550
|
+
subcommands.push({
|
|
20551
|
+
kind: type === "if" ? "if_score" : "unless_score",
|
|
20552
|
+
target,
|
|
20553
|
+
targetObj,
|
|
20554
|
+
op,
|
|
20555
|
+
source,
|
|
20556
|
+
sourceObj
|
|
20557
|
+
});
|
|
20558
|
+
}
|
|
20559
|
+
} else {
|
|
20560
|
+
this.error(`Unknown condition type after ${type}`);
|
|
20663
20561
|
}
|
|
20664
|
-
return expr;
|
|
20665
20562
|
}
|
|
20666
|
-
|
|
20667
|
-
|
|
20563
|
+
// -------------------------------------------------------------------------
|
|
20564
|
+
// Expression statement
|
|
20565
|
+
// -------------------------------------------------------------------------
|
|
20566
|
+
parseExprStmt() {
|
|
20567
|
+
const expr = this.parseExpr();
|
|
20568
|
+
this.match(";");
|
|
20569
|
+
const exprToken = this.getLocToken(expr) ?? this.peek();
|
|
20570
|
+
return this.withLoc({ kind: "expr", expr }, exprToken);
|
|
20571
|
+
}
|
|
20572
|
+
};
|
|
20573
|
+
exports2.StmtParser = StmtParser;
|
|
20574
|
+
}
|
|
20575
|
+
});
|
|
20576
|
+
|
|
20577
|
+
// ../../dist/src/parser/decl-parser.js
|
|
20578
|
+
var require_decl_parser = __commonJS({
|
|
20579
|
+
"../../dist/src/parser/decl-parser.js"(exports2) {
|
|
20580
|
+
"use strict";
|
|
20581
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
20582
|
+
exports2.DeclParser = void 0;
|
|
20583
|
+
var stmt_parser_1 = require_stmt_parser();
|
|
20584
|
+
var DeclParser = class extends stmt_parser_1.StmtParser {
|
|
20585
|
+
// -------------------------------------------------------------------------
|
|
20586
|
+
// Struct
|
|
20587
|
+
// -------------------------------------------------------------------------
|
|
20588
|
+
parseStructDecl() {
|
|
20589
|
+
const structToken = this.expect("struct");
|
|
20590
|
+
const name = this.expect("ident").value;
|
|
20591
|
+
const extendsName = this.match("extends") ? this.expect("ident").value : void 0;
|
|
20592
|
+
this.expect("{");
|
|
20668
20593
|
const fields = [];
|
|
20669
|
-
|
|
20670
|
-
|
|
20671
|
-
|
|
20672
|
-
|
|
20673
|
-
|
|
20674
|
-
|
|
20675
|
-
} while (this.match(","));
|
|
20594
|
+
while (!this.check("}") && !this.check("eof")) {
|
|
20595
|
+
const fieldName = this.expect("ident").value;
|
|
20596
|
+
this.expect(":");
|
|
20597
|
+
const fieldType = this.parseType();
|
|
20598
|
+
fields.push({ name: fieldName, type: fieldType });
|
|
20599
|
+
this.match(",");
|
|
20676
20600
|
}
|
|
20677
20601
|
this.expect("}");
|
|
20678
|
-
return this.withLoc({
|
|
20679
|
-
}
|
|
20680
|
-
parseArrayLit() {
|
|
20681
|
-
const bracketToken = this.expect("[");
|
|
20682
|
-
const elements = [];
|
|
20683
|
-
if (!this.check("]")) {
|
|
20684
|
-
do {
|
|
20685
|
-
elements.push(this.parseExpr());
|
|
20686
|
-
} while (this.match(","));
|
|
20687
|
-
}
|
|
20688
|
-
this.expect("]");
|
|
20689
|
-
return this.withLoc({ kind: "array_lit", elements }, bracketToken);
|
|
20602
|
+
return this.withLoc({ name, extends: extendsName, fields }, structToken);
|
|
20690
20603
|
}
|
|
20691
|
-
|
|
20692
|
-
|
|
20693
|
-
|
|
20694
|
-
|
|
20695
|
-
|
|
20696
|
-
|
|
20697
|
-
|
|
20698
|
-
|
|
20699
|
-
|
|
20700
|
-
|
|
20701
|
-
|
|
20702
|
-
|
|
20703
|
-
|
|
20704
|
-
|
|
20705
|
-
|
|
20706
|
-
|
|
20707
|
-
|
|
20708
|
-
|
|
20709
|
-
|
|
20710
|
-
|
|
20711
|
-
|
|
20604
|
+
// -------------------------------------------------------------------------
|
|
20605
|
+
// Enum
|
|
20606
|
+
// -------------------------------------------------------------------------
|
|
20607
|
+
parseEnumDecl() {
|
|
20608
|
+
const enumToken = this.expect("enum");
|
|
20609
|
+
const name = this.expect("ident").value;
|
|
20610
|
+
this.expect("{");
|
|
20611
|
+
const variants = [];
|
|
20612
|
+
let nextValue = 0;
|
|
20613
|
+
while (!this.check("}") && !this.check("eof")) {
|
|
20614
|
+
const variantToken = this.expect("ident");
|
|
20615
|
+
const variant = { name: variantToken.value };
|
|
20616
|
+
if (this.check("(")) {
|
|
20617
|
+
this.advance();
|
|
20618
|
+
const fields = [];
|
|
20619
|
+
while (!this.check(")") && !this.check("eof")) {
|
|
20620
|
+
const fieldName = this.expect("ident").value;
|
|
20621
|
+
this.expect(":");
|
|
20622
|
+
const fieldType = this.parseType();
|
|
20623
|
+
fields.push({ name: fieldName, type: fieldType });
|
|
20624
|
+
if (!this.match(","))
|
|
20625
|
+
break;
|
|
20712
20626
|
}
|
|
20713
|
-
|
|
20627
|
+
this.expect(")");
|
|
20628
|
+
variant.fields = fields;
|
|
20714
20629
|
}
|
|
20715
|
-
|
|
20716
|
-
|
|
20717
|
-
|
|
20718
|
-
|
|
20719
|
-
|
|
20720
|
-
|
|
20721
|
-
return true;
|
|
20722
|
-
}
|
|
20723
|
-
if (this.peek(offset).kind === "->") {
|
|
20724
|
-
offset += 1;
|
|
20725
|
-
const consumed = this.typeTokenLength(offset);
|
|
20726
|
-
if (consumed === 0) {
|
|
20727
|
-
return false;
|
|
20630
|
+
if (this.match("=")) {
|
|
20631
|
+
const valueToken = this.expect("int_lit");
|
|
20632
|
+
variant.value = parseInt(valueToken.value, 10);
|
|
20633
|
+
nextValue = variant.value + 1;
|
|
20634
|
+
} else {
|
|
20635
|
+
variant.value = nextValue++;
|
|
20728
20636
|
}
|
|
20729
|
-
|
|
20730
|
-
|
|
20637
|
+
variants.push(variant);
|
|
20638
|
+
if (!this.match(","))
|
|
20639
|
+
break;
|
|
20731
20640
|
}
|
|
20732
|
-
|
|
20641
|
+
this.expect("}");
|
|
20642
|
+
return this.withLoc({ name, variants }, enumToken);
|
|
20733
20643
|
}
|
|
20734
|
-
|
|
20735
|
-
|
|
20736
|
-
|
|
20737
|
-
|
|
20738
|
-
|
|
20739
|
-
|
|
20740
|
-
|
|
20741
|
-
|
|
20742
|
-
|
|
20743
|
-
|
|
20744
|
-
|
|
20745
|
-
|
|
20746
|
-
|
|
20747
|
-
continue;
|
|
20748
|
-
}
|
|
20749
|
-
break;
|
|
20750
|
-
}
|
|
20751
|
-
}
|
|
20752
|
-
if (this.peek(inner).kind !== ")") {
|
|
20753
|
-
return 0;
|
|
20754
|
-
}
|
|
20755
|
-
inner += 1;
|
|
20756
|
-
if (this.peek(inner).kind !== "->") {
|
|
20757
|
-
return 0;
|
|
20758
|
-
}
|
|
20759
|
-
inner += 1;
|
|
20760
|
-
const returnLen = this.typeTokenLength(inner);
|
|
20761
|
-
return returnLen === 0 ? 0 : inner + returnLen - offset;
|
|
20762
|
-
}
|
|
20763
|
-
const isNamedType = token.kind === "int" || token.kind === "bool" || token.kind === "float" || token.kind === "fixed" || token.kind === "string" || token.kind === "void" || token.kind === "BlockPos" || token.kind === "ident";
|
|
20764
|
-
if (!isNamedType) {
|
|
20765
|
-
return 0;
|
|
20766
|
-
}
|
|
20767
|
-
let length = 1;
|
|
20768
|
-
while (this.peek(offset + length).kind === "[" && this.peek(offset + length + 1).kind === "]") {
|
|
20769
|
-
length += 2;
|
|
20644
|
+
// -------------------------------------------------------------------------
|
|
20645
|
+
// Impl Block
|
|
20646
|
+
// -------------------------------------------------------------------------
|
|
20647
|
+
parseImplBlock() {
|
|
20648
|
+
const implToken = this.expect("impl");
|
|
20649
|
+
let traitName;
|
|
20650
|
+
let typeName;
|
|
20651
|
+
const firstName = this.expect("ident").value;
|
|
20652
|
+
if (this.match("for")) {
|
|
20653
|
+
traitName = firstName;
|
|
20654
|
+
typeName = this.expect("ident").value;
|
|
20655
|
+
} else {
|
|
20656
|
+
typeName = firstName;
|
|
20770
20657
|
}
|
|
20771
|
-
|
|
20772
|
-
|
|
20773
|
-
|
|
20774
|
-
|
|
20775
|
-
return false;
|
|
20776
|
-
let offset = 1;
|
|
20777
|
-
for (let i = 0; i < 3; i++) {
|
|
20778
|
-
const consumed = this.coordComponentTokenLength(offset);
|
|
20779
|
-
if (consumed === 0)
|
|
20780
|
-
return false;
|
|
20781
|
-
offset += consumed;
|
|
20782
|
-
if (i < 2) {
|
|
20783
|
-
if (this.peek(offset).kind !== ",")
|
|
20784
|
-
return false;
|
|
20785
|
-
offset += 1;
|
|
20786
|
-
}
|
|
20658
|
+
this.expect("{");
|
|
20659
|
+
const methods = [];
|
|
20660
|
+
while (!this.check("}") && !this.check("eof")) {
|
|
20661
|
+
methods.push(this.parseFnDecl(typeName));
|
|
20787
20662
|
}
|
|
20788
|
-
|
|
20663
|
+
this.expect("}");
|
|
20664
|
+
return this.withLoc({ kind: "impl_block", traitName, typeName, methods }, implToken);
|
|
20789
20665
|
}
|
|
20790
|
-
|
|
20791
|
-
|
|
20792
|
-
|
|
20793
|
-
|
|
20794
|
-
|
|
20795
|
-
|
|
20796
|
-
|
|
20666
|
+
// -------------------------------------------------------------------------
|
|
20667
|
+
// Interface
|
|
20668
|
+
// -------------------------------------------------------------------------
|
|
20669
|
+
parseInterfaceDecl() {
|
|
20670
|
+
const ifaceToken = this.expect("interface");
|
|
20671
|
+
const name = this.expect("ident").value;
|
|
20672
|
+
this.expect("{");
|
|
20673
|
+
const methods = [];
|
|
20674
|
+
while (!this.check("}") && !this.check("eof")) {
|
|
20675
|
+
const fnToken = this.expect("fn");
|
|
20676
|
+
const methodName = this.expect("ident").value;
|
|
20677
|
+
this.expect("(");
|
|
20678
|
+
const params = this.parseInterfaceParams();
|
|
20679
|
+
this.expect(")");
|
|
20680
|
+
let returnType;
|
|
20681
|
+
if (this.match(":"))
|
|
20682
|
+
returnType = this.parseType();
|
|
20683
|
+
methods.push(this.withLoc({ name: methodName, params, returnType }, fnToken));
|
|
20797
20684
|
}
|
|
20798
|
-
|
|
20799
|
-
|
|
20685
|
+
this.expect("}");
|
|
20686
|
+
return this.withLoc({ name, methods }, ifaceToken);
|
|
20687
|
+
}
|
|
20688
|
+
// -------------------------------------------------------------------------
|
|
20689
|
+
// Const / Global
|
|
20690
|
+
// -------------------------------------------------------------------------
|
|
20691
|
+
parseConstDecl() {
|
|
20692
|
+
const constToken = this.expect("const");
|
|
20693
|
+
const name = this.expect("ident").value;
|
|
20694
|
+
let type;
|
|
20695
|
+
if (this.match(":"))
|
|
20696
|
+
type = this.parseType();
|
|
20697
|
+
this.expect("=");
|
|
20698
|
+
const value = this.parseLiteralExpr();
|
|
20699
|
+
this.match(";");
|
|
20700
|
+
const inferredType = type ?? (value.kind === "str_lit" ? { kind: "named", name: "string" } : value.kind === "bool_lit" ? { kind: "named", name: "bool" } : value.kind === "float_lit" ? { kind: "named", name: "fixed" } : { kind: "named", name: "int" });
|
|
20701
|
+
return this.withLoc({ name, type: inferredType, value }, constToken);
|
|
20702
|
+
}
|
|
20703
|
+
parseGlobalDecl(mutable) {
|
|
20704
|
+
const token = this.advance();
|
|
20705
|
+
const name = this.expect("ident").value;
|
|
20706
|
+
this.expect(":");
|
|
20707
|
+
const type = this.parseType();
|
|
20708
|
+
let init;
|
|
20709
|
+
if (this.match("=")) {
|
|
20710
|
+
init = this.parseExpr();
|
|
20711
|
+
} else {
|
|
20712
|
+
init = { kind: "int_lit", value: 0 };
|
|
20800
20713
|
}
|
|
20801
|
-
|
|
20714
|
+
this.match(";");
|
|
20715
|
+
return this.withLoc({ kind: "global", name, type, init, mutable }, token);
|
|
20802
20716
|
}
|
|
20803
|
-
|
|
20804
|
-
|
|
20805
|
-
|
|
20806
|
-
|
|
20807
|
-
|
|
20808
|
-
this.
|
|
20809
|
-
|
|
20810
|
-
|
|
20811
|
-
return this.withLoc({ kind: "blockpos", x, y, z }, openParenToken);
|
|
20717
|
+
// -------------------------------------------------------------------------
|
|
20718
|
+
// Function
|
|
20719
|
+
// -------------------------------------------------------------------------
|
|
20720
|
+
parseExportedFnDecl() {
|
|
20721
|
+
this.expect("export");
|
|
20722
|
+
const fn = this.parseFnDecl();
|
|
20723
|
+
fn.isExported = true;
|
|
20724
|
+
return fn;
|
|
20812
20725
|
}
|
|
20813
|
-
|
|
20814
|
-
const
|
|
20815
|
-
|
|
20726
|
+
parseFnDecl(implTypeName) {
|
|
20727
|
+
const decorators = this.parseDecorators();
|
|
20728
|
+
const watchObjective = decorators.find((decorator) => decorator.name === "watch")?.args?.objective;
|
|
20729
|
+
let isExported;
|
|
20730
|
+
const filteredDecorators = decorators.filter((d) => {
|
|
20731
|
+
if (d.name === "keep") {
|
|
20732
|
+
isExported = true;
|
|
20733
|
+
return false;
|
|
20734
|
+
}
|
|
20735
|
+
return true;
|
|
20736
|
+
});
|
|
20737
|
+
const fnToken = this.expect("fn");
|
|
20738
|
+
const name = this.expect("ident").value;
|
|
20739
|
+
let typeParams;
|
|
20740
|
+
if (this.check("<")) {
|
|
20816
20741
|
this.advance();
|
|
20817
|
-
|
|
20818
|
-
|
|
20742
|
+
typeParams = [];
|
|
20743
|
+
do {
|
|
20744
|
+
typeParams.push(this.expect("ident").value);
|
|
20745
|
+
} while (this.match(","));
|
|
20746
|
+
this.expect(">");
|
|
20819
20747
|
}
|
|
20820
|
-
|
|
20821
|
-
|
|
20822
|
-
|
|
20823
|
-
|
|
20748
|
+
this.expect("(");
|
|
20749
|
+
const params = this.parseParams(implTypeName);
|
|
20750
|
+
this.expect(")");
|
|
20751
|
+
let returnType = { kind: "named", name: "void" };
|
|
20752
|
+
if (this.match("->") || this.match(":")) {
|
|
20753
|
+
returnType = this.parseType();
|
|
20824
20754
|
}
|
|
20825
|
-
|
|
20826
|
-
|
|
20827
|
-
|
|
20828
|
-
|
|
20829
|
-
|
|
20830
|
-
|
|
20755
|
+
const body = this.parseBlock();
|
|
20756
|
+
const closingBraceLine = this.tokens[this.pos - 1]?.line;
|
|
20757
|
+
const fn = this.withLoc({
|
|
20758
|
+
name,
|
|
20759
|
+
typeParams,
|
|
20760
|
+
params,
|
|
20761
|
+
returnType,
|
|
20762
|
+
decorators: filteredDecorators,
|
|
20763
|
+
body,
|
|
20764
|
+
isLibraryFn: this.inLibraryMode || void 0,
|
|
20765
|
+
isExported,
|
|
20766
|
+
watchObjective
|
|
20767
|
+
}, fnToken);
|
|
20768
|
+
if (fn.span && closingBraceLine)
|
|
20769
|
+
fn.span.endLine = closingBraceLine;
|
|
20770
|
+
return fn;
|
|
20831
20771
|
}
|
|
20832
|
-
|
|
20833
|
-
|
|
20834
|
-
|
|
20835
|
-
|
|
20836
|
-
|
|
20837
|
-
|
|
20838
|
-
|
|
20772
|
+
parseDeclareStub() {
|
|
20773
|
+
this.expect("fn");
|
|
20774
|
+
this.expect("ident");
|
|
20775
|
+
this.expect("(");
|
|
20776
|
+
let depth = 1;
|
|
20777
|
+
while (!this.check("eof") && depth > 0) {
|
|
20778
|
+
const t = this.advance();
|
|
20779
|
+
if (t.kind === "(")
|
|
20780
|
+
depth++;
|
|
20781
|
+
else if (t.kind === ")")
|
|
20782
|
+
depth--;
|
|
20839
20783
|
}
|
|
20840
|
-
if (
|
|
20841
|
-
this.
|
|
20784
|
+
if (this.match(":") || this.match("->")) {
|
|
20785
|
+
this.parseType();
|
|
20842
20786
|
}
|
|
20843
|
-
|
|
20787
|
+
this.match(";");
|
|
20844
20788
|
}
|
|
20845
20789
|
// -------------------------------------------------------------------------
|
|
20846
|
-
//
|
|
20790
|
+
// Decorators
|
|
20847
20791
|
// -------------------------------------------------------------------------
|
|
20848
|
-
|
|
20849
|
-
const
|
|
20850
|
-
|
|
20851
|
-
|
|
20852
|
-
|
|
20853
|
-
|
|
20854
|
-
parseSelectorOrVarSelector() {
|
|
20855
|
-
if (this.check("selector")) {
|
|
20856
|
-
return { selector: this.parseSelector() };
|
|
20857
|
-
}
|
|
20858
|
-
const varToken = this.expect("ident");
|
|
20859
|
-
const varName = varToken.value;
|
|
20860
|
-
if (this.check("[")) {
|
|
20861
|
-
this.advance();
|
|
20862
|
-
let filterStr = "";
|
|
20863
|
-
let depth = 1;
|
|
20864
|
-
while (depth > 0 && !this.check("eof")) {
|
|
20865
|
-
if (this.check("["))
|
|
20866
|
-
depth++;
|
|
20867
|
-
else if (this.check("]"))
|
|
20868
|
-
depth--;
|
|
20869
|
-
if (depth > 0) {
|
|
20870
|
-
filterStr += this.peek().value ?? this.peek().kind;
|
|
20871
|
-
this.advance();
|
|
20872
|
-
}
|
|
20873
|
-
}
|
|
20874
|
-
this.expect("]");
|
|
20875
|
-
const filters = this.parseSelectorFilters(filterStr);
|
|
20876
|
-
return { varName, filters };
|
|
20792
|
+
parseDecorators() {
|
|
20793
|
+
const decorators = [];
|
|
20794
|
+
while (this.check("decorator")) {
|
|
20795
|
+
const token = this.advance();
|
|
20796
|
+
const decorator = this.parseDecoratorValue(token.value);
|
|
20797
|
+
decorators.push(decorator);
|
|
20877
20798
|
}
|
|
20878
|
-
return
|
|
20799
|
+
return decorators;
|
|
20879
20800
|
}
|
|
20880
|
-
|
|
20881
|
-
const
|
|
20882
|
-
if (
|
|
20883
|
-
|
|
20801
|
+
parseDecoratorValue(value) {
|
|
20802
|
+
const match = value.match(/^@([A-Za-z_][A-Za-z0-9_-]*)(?:\((.*)\))?$/s);
|
|
20803
|
+
if (!match) {
|
|
20804
|
+
this.error(`Invalid decorator: ${value}`);
|
|
20884
20805
|
}
|
|
20885
|
-
const
|
|
20886
|
-
const
|
|
20887
|
-
|
|
20888
|
-
|
|
20889
|
-
|
|
20890
|
-
|
|
20891
|
-
|
|
20892
|
-
const
|
|
20893
|
-
|
|
20894
|
-
const
|
|
20895
|
-
if (
|
|
20896
|
-
|
|
20897
|
-
|
|
20898
|
-
const val = part.slice(eqIndex + 1).trim();
|
|
20899
|
-
switch (key) {
|
|
20900
|
-
case "type":
|
|
20901
|
-
filters.type = val;
|
|
20902
|
-
break;
|
|
20903
|
-
case "distance":
|
|
20904
|
-
filters.distance = this.parseRangeValue(val);
|
|
20905
|
-
break;
|
|
20906
|
-
case "tag":
|
|
20907
|
-
if (val.startsWith("!")) {
|
|
20908
|
-
filters.notTag = filters.notTag ?? [];
|
|
20909
|
-
filters.notTag.push(val.slice(1));
|
|
20910
|
-
} else {
|
|
20911
|
-
filters.tag = filters.tag ?? [];
|
|
20912
|
-
filters.tag.push(val);
|
|
20913
|
-
}
|
|
20914
|
-
break;
|
|
20915
|
-
case "limit":
|
|
20916
|
-
filters.limit = parseInt(val, 10);
|
|
20917
|
-
break;
|
|
20918
|
-
case "sort":
|
|
20919
|
-
filters.sort = val;
|
|
20920
|
-
break;
|
|
20921
|
-
case "nbt":
|
|
20922
|
-
filters.nbt = val;
|
|
20923
|
-
break;
|
|
20924
|
-
case "gamemode":
|
|
20925
|
-
filters.gamemode = val;
|
|
20926
|
-
break;
|
|
20927
|
-
case "scores":
|
|
20928
|
-
filters.scores = this.parseScoresFilter(val);
|
|
20929
|
-
break;
|
|
20930
|
-
case "x":
|
|
20931
|
-
filters.x = this.parseRangeValue(val);
|
|
20932
|
-
break;
|
|
20933
|
-
case "y":
|
|
20934
|
-
filters.y = this.parseRangeValue(val);
|
|
20935
|
-
break;
|
|
20936
|
-
case "z":
|
|
20937
|
-
filters.z = this.parseRangeValue(val);
|
|
20938
|
-
break;
|
|
20939
|
-
case "x_rotation":
|
|
20940
|
-
filters.x_rotation = this.parseRangeValue(val);
|
|
20941
|
-
break;
|
|
20942
|
-
case "y_rotation":
|
|
20943
|
-
filters.y_rotation = this.parseRangeValue(val);
|
|
20944
|
-
break;
|
|
20806
|
+
const name = match[1];
|
|
20807
|
+
const argsStr = match[2];
|
|
20808
|
+
if (!argsStr)
|
|
20809
|
+
return { name };
|
|
20810
|
+
if (name === "profile" || name === "benchmark" || name === "memoize") {
|
|
20811
|
+
this.error(`@${name} decorator does not accept arguments`);
|
|
20812
|
+
}
|
|
20813
|
+
const args = {};
|
|
20814
|
+
if (name === "on") {
|
|
20815
|
+
const eventTypeMatch = argsStr.match(/^([A-Za-z_][A-Za-z0-9_]*)$/);
|
|
20816
|
+
if (eventTypeMatch) {
|
|
20817
|
+
args.eventType = eventTypeMatch[1];
|
|
20818
|
+
return { name, args };
|
|
20945
20819
|
}
|
|
20946
20820
|
}
|
|
20947
|
-
|
|
20948
|
-
|
|
20949
|
-
|
|
20950
|
-
|
|
20951
|
-
|
|
20952
|
-
|
|
20953
|
-
|
|
20954
|
-
|
|
20955
|
-
|
|
20956
|
-
|
|
20957
|
-
|
|
20958
|
-
|
|
20959
|
-
|
|
20960
|
-
|
|
20961
|
-
continue;
|
|
20821
|
+
if (name === "watch" || name === "on_trigger" || name === "on_advancement" || name === "on_craft" || name === "on_join_team") {
|
|
20822
|
+
const strMatch = argsStr.match(/^"([^"]*)"$/);
|
|
20823
|
+
if (strMatch) {
|
|
20824
|
+
if (name === "watch")
|
|
20825
|
+
args.objective = strMatch[1];
|
|
20826
|
+
else if (name === "on_trigger")
|
|
20827
|
+
args.trigger = strMatch[1];
|
|
20828
|
+
else if (name === "on_advancement")
|
|
20829
|
+
args.advancement = strMatch[1];
|
|
20830
|
+
else if (name === "on_craft")
|
|
20831
|
+
args.item = strMatch[1];
|
|
20832
|
+
else if (name === "on_join_team")
|
|
20833
|
+
args.team = strMatch[1];
|
|
20834
|
+
return { name, args };
|
|
20962
20835
|
}
|
|
20963
|
-
current += char;
|
|
20964
20836
|
}
|
|
20965
|
-
if (
|
|
20966
|
-
|
|
20837
|
+
if (name === "config") {
|
|
20838
|
+
const configMatch = argsStr.match(/^"([^"]+)"\s*,\s*default\s*:\s*(-?\d+(?:\.\d+)?)$/);
|
|
20839
|
+
if (configMatch) {
|
|
20840
|
+
return { name, args: { configKey: configMatch[1], configDefault: parseFloat(configMatch[2]) } };
|
|
20841
|
+
}
|
|
20842
|
+
const keyOnlyMatch = argsStr.match(/^"([^"]+)"$/);
|
|
20843
|
+
if (keyOnlyMatch) {
|
|
20844
|
+
return { name, args: { configKey: keyOnlyMatch[1] } };
|
|
20845
|
+
}
|
|
20846
|
+
this.error(`Invalid @config syntax. Expected: @config("key", default: value) or @config("key")`);
|
|
20967
20847
|
}
|
|
20968
|
-
|
|
20969
|
-
|
|
20970
|
-
|
|
20971
|
-
|
|
20972
|
-
|
|
20973
|
-
const parts = inner.split(",");
|
|
20974
|
-
for (const part of parts) {
|
|
20975
|
-
const [name, range] = part.split("=").map((s) => s.trim());
|
|
20976
|
-
scores[name] = this.parseRangeValue(range);
|
|
20848
|
+
if (name === "deprecated") {
|
|
20849
|
+
const strMatch = argsStr.match(/^"([^"]*)"$/);
|
|
20850
|
+
if (strMatch)
|
|
20851
|
+
return { name, args: { message: strMatch[1] } };
|
|
20852
|
+
return { name, args: {} };
|
|
20977
20853
|
}
|
|
20978
|
-
|
|
20979
|
-
|
|
20980
|
-
|
|
20981
|
-
|
|
20982
|
-
|
|
20983
|
-
if (!rest)
|
|
20984
|
-
return {};
|
|
20985
|
-
const max = parseInt(rest, 10);
|
|
20986
|
-
return { max };
|
|
20854
|
+
if (name === "test") {
|
|
20855
|
+
const strMatch = argsStr.match(/^"([^"]*)"$/);
|
|
20856
|
+
if (strMatch)
|
|
20857
|
+
return { name, args: { testLabel: strMatch[1] } };
|
|
20858
|
+
return { name, args: { testLabel: "" } };
|
|
20987
20859
|
}
|
|
20988
|
-
if (
|
|
20989
|
-
const
|
|
20990
|
-
|
|
20991
|
-
|
|
20992
|
-
|
|
20993
|
-
|
|
20860
|
+
if (name === "require_on_load") {
|
|
20861
|
+
const rawArgs = [];
|
|
20862
|
+
for (const part of argsStr.split(",")) {
|
|
20863
|
+
const trimmed = part.trim();
|
|
20864
|
+
const identMatch = trimmed.match(/^([A-Za-z_][A-Za-z0-9_]*)$/);
|
|
20865
|
+
if (identMatch) {
|
|
20866
|
+
rawArgs.push({ kind: "string", value: identMatch[1] });
|
|
20867
|
+
} else {
|
|
20868
|
+
const strMatch = trimmed.match(/^"([^"]*)"$/);
|
|
20869
|
+
if (strMatch)
|
|
20870
|
+
rawArgs.push({ kind: "string", value: strMatch[1] });
|
|
20871
|
+
}
|
|
20872
|
+
}
|
|
20873
|
+
return { name, rawArgs };
|
|
20994
20874
|
}
|
|
20995
|
-
const
|
|
20996
|
-
|
|
20997
|
-
|
|
20998
|
-
|
|
20999
|
-
if (
|
|
21000
|
-
|
|
21001
|
-
|
|
21002
|
-
|
|
20875
|
+
for (const part of argsStr.split(",")) {
|
|
20876
|
+
const [key, val] = part.split("=").map((s) => s.trim());
|
|
20877
|
+
if (key === "rate")
|
|
20878
|
+
args.rate = parseInt(val, 10);
|
|
20879
|
+
else if (key === "ticks")
|
|
20880
|
+
args.ticks = parseInt(val, 10);
|
|
20881
|
+
else if (key === "batch")
|
|
20882
|
+
args.batch = parseInt(val, 10);
|
|
20883
|
+
else if (key === "onDone")
|
|
20884
|
+
args.onDone = val.replace(/^["']|["']$/g, "");
|
|
20885
|
+
else if (key === "trigger")
|
|
20886
|
+
args.trigger = val;
|
|
20887
|
+
else if (key === "advancement")
|
|
20888
|
+
args.advancement = val;
|
|
20889
|
+
else if (key === "item")
|
|
20890
|
+
args.item = val;
|
|
20891
|
+
else if (key === "team")
|
|
20892
|
+
args.team = val;
|
|
20893
|
+
else if (key === "max")
|
|
20894
|
+
args.max = parseInt(val, 10);
|
|
21003
20895
|
}
|
|
21004
|
-
|
|
21005
|
-
|
|
21006
|
-
|
|
21007
|
-
|
|
21008
|
-
|
|
21009
|
-
|
|
21010
|
-
|
|
21011
|
-
|
|
20896
|
+
return { name, args };
|
|
20897
|
+
}
|
|
20898
|
+
};
|
|
20899
|
+
exports2.DeclParser = DeclParser;
|
|
20900
|
+
}
|
|
20901
|
+
});
|
|
20902
|
+
|
|
20903
|
+
// ../../dist/src/parser/index.js
|
|
20904
|
+
var require_parser = __commonJS({
|
|
20905
|
+
"../../dist/src/parser/index.js"(exports2) {
|
|
20906
|
+
"use strict";
|
|
20907
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
20908
|
+
exports2.Parser = void 0;
|
|
20909
|
+
var diagnostics_1 = require_diagnostics();
|
|
20910
|
+
var decl_parser_1 = require_decl_parser();
|
|
20911
|
+
var Parser = class extends decl_parser_1.DeclParser {
|
|
20912
|
+
// -------------------------------------------------------------------------
|
|
20913
|
+
// Program (top-level entry point)
|
|
20914
|
+
// -------------------------------------------------------------------------
|
|
20915
|
+
parse(defaultNamespace = "redscript") {
|
|
20916
|
+
let namespace = defaultNamespace;
|
|
20917
|
+
const globals = [];
|
|
20918
|
+
const declarations = [];
|
|
20919
|
+
const structs = [];
|
|
20920
|
+
const implBlocks = [];
|
|
20921
|
+
const enums = [];
|
|
20922
|
+
const consts = [];
|
|
20923
|
+
const imports = [];
|
|
20924
|
+
const interfaces = [];
|
|
20925
|
+
let isLibrary = false;
|
|
20926
|
+
let moduleName;
|
|
20927
|
+
if (this.check("namespace")) {
|
|
20928
|
+
this.advance();
|
|
20929
|
+
const name = this.expect("ident");
|
|
20930
|
+
namespace = name.value;
|
|
20931
|
+
this.match(";");
|
|
21012
20932
|
}
|
|
21013
|
-
|
|
21014
|
-
|
|
20933
|
+
if (this.check("module")) {
|
|
20934
|
+
this.advance();
|
|
20935
|
+
const modKind = this.expect("ident");
|
|
20936
|
+
if (modKind.value === "library") {
|
|
20937
|
+
isLibrary = true;
|
|
20938
|
+
this.inLibraryMode = true;
|
|
20939
|
+
} else {
|
|
20940
|
+
moduleName = modKind.value;
|
|
20941
|
+
}
|
|
20942
|
+
this.match(";");
|
|
20943
|
+
}
|
|
20944
|
+
while (!this.check("eof")) {
|
|
20945
|
+
try {
|
|
20946
|
+
if (this.check("decorator") && this.peek().value.startsWith("@config")) {
|
|
20947
|
+
const decorToken = this.advance();
|
|
20948
|
+
const decorator = this.parseDecoratorValue(decorToken.value);
|
|
20949
|
+
if (!this.check("let")) {
|
|
20950
|
+
this.error("@config decorator must be followed by a let declaration");
|
|
20951
|
+
}
|
|
20952
|
+
const g = this.parseGlobalDecl(true);
|
|
20953
|
+
g.configKey = decorator.args?.configKey;
|
|
20954
|
+
g.configDefault = decorator.args?.configDefault;
|
|
20955
|
+
globals.push(g);
|
|
20956
|
+
} else if (this.check("let")) {
|
|
20957
|
+
globals.push(this.parseGlobalDecl(true));
|
|
20958
|
+
} else if (this.check("decorator") && this.peek().value === "@singleton") {
|
|
20959
|
+
this.advance();
|
|
20960
|
+
if (!this.check("struct")) {
|
|
20961
|
+
this.error("@singleton decorator must be followed by a struct declaration");
|
|
20962
|
+
}
|
|
20963
|
+
const s = this.parseStructDecl();
|
|
20964
|
+
s.isSingleton = true;
|
|
20965
|
+
structs.push(s);
|
|
20966
|
+
} else if (this.check("struct")) {
|
|
20967
|
+
structs.push(this.parseStructDecl());
|
|
20968
|
+
} else if (this.check("impl")) {
|
|
20969
|
+
implBlocks.push(this.parseImplBlock());
|
|
20970
|
+
} else if (this.check("interface")) {
|
|
20971
|
+
interfaces.push(this.parseInterfaceDecl());
|
|
20972
|
+
} else if (this.check("enum")) {
|
|
20973
|
+
enums.push(this.parseEnumDecl());
|
|
20974
|
+
} else if (this.check("const")) {
|
|
20975
|
+
consts.push(this.parseConstDecl());
|
|
20976
|
+
} else if (this.check("declare")) {
|
|
20977
|
+
this.advance();
|
|
20978
|
+
this.parseDeclareStub();
|
|
20979
|
+
} else if (this.check("export")) {
|
|
20980
|
+
declarations.push(this.parseExportedFnDecl());
|
|
20981
|
+
} else if (this.check("import") || this.check("ident") && this.peek().value === "import") {
|
|
20982
|
+
this.advance();
|
|
20983
|
+
const importToken = this.peek();
|
|
20984
|
+
const modName = this.expect("ident").value;
|
|
20985
|
+
if (this.check("::")) {
|
|
20986
|
+
this.advance();
|
|
20987
|
+
let symbol;
|
|
20988
|
+
if (this.check("*")) {
|
|
20989
|
+
this.advance();
|
|
20990
|
+
symbol = "*";
|
|
20991
|
+
} else {
|
|
20992
|
+
symbol = this.expect("ident").value;
|
|
20993
|
+
}
|
|
20994
|
+
this.match(";");
|
|
20995
|
+
imports.push(this.withLoc({ moduleName: modName, symbol }, importToken));
|
|
20996
|
+
} else {
|
|
20997
|
+
this.match(";");
|
|
20998
|
+
imports.push(this.withLoc({ moduleName: modName, symbol: void 0 }, importToken));
|
|
20999
|
+
}
|
|
21000
|
+
} else {
|
|
21001
|
+
declarations.push(this.parseFnDecl());
|
|
21002
|
+
}
|
|
21003
|
+
} catch (err) {
|
|
21004
|
+
if (err instanceof diagnostics_1.DiagnosticError) {
|
|
21005
|
+
this.parseErrors.push(err);
|
|
21006
|
+
this.syncToNextDecl();
|
|
21007
|
+
} else {
|
|
21008
|
+
throw err;
|
|
21009
|
+
}
|
|
21010
|
+
}
|
|
21011
|
+
}
|
|
21012
|
+
return { namespace, moduleName, globals, declarations, structs, implBlocks, enums, consts, imports, interfaces, isLibrary };
|
|
21015
21013
|
}
|
|
21016
21014
|
};
|
|
21017
21015
|
exports2.Parser = Parser;
|
|
@@ -22779,16 +22777,17 @@ var require_lower2 = __commonJS({
|
|
|
22779
22777
|
else if (c.value.kind === "float_lit")
|
|
22780
22778
|
constValues.set(c.name, Math.round(c.value.value * 1e4));
|
|
22781
22779
|
}
|
|
22780
|
+
const globalVarNames = new Set(hir.globals.map((g) => g.name));
|
|
22782
22781
|
const allFunctions = [];
|
|
22783
22782
|
for (const f of hir.functions) {
|
|
22784
|
-
const { fn, helpers } = lowerFunction(f, hir.namespace, structDefs, implMethods, macroInfo, fnParamInfo, enumDefs, sourceFile, timerCounter, void 0, hirFnMap, specializedFnsRegistry, void 0, enumPayloads, constValues, singletonStructs, displayImpls);
|
|
22783
|
+
const { fn, helpers } = lowerFunction(f, hir.namespace, structDefs, implMethods, macroInfo, fnParamInfo, enumDefs, sourceFile, timerCounter, void 0, hirFnMap, specializedFnsRegistry, void 0, enumPayloads, constValues, singletonStructs, displayImpls, globalVarNames);
|
|
22785
22784
|
allFunctions.push(fn, ...helpers);
|
|
22786
22785
|
}
|
|
22787
22786
|
for (const ib of hir.implBlocks) {
|
|
22788
22787
|
if (ib.traitName === "Display")
|
|
22789
22788
|
continue;
|
|
22790
22789
|
for (const m of ib.methods) {
|
|
22791
|
-
const { fn, helpers } = lowerImplMethod(m, ib.typeName, hir.namespace, structDefs, implMethods, macroInfo, fnParamInfo, enumDefs, sourceFile, timerCounter, enumPayloads, constValues);
|
|
22790
|
+
const { fn, helpers } = lowerImplMethod(m, ib.typeName, hir.namespace, structDefs, implMethods, macroInfo, fnParamInfo, enumDefs, sourceFile, timerCounter, enumPayloads, constValues, globalVarNames);
|
|
22792
22791
|
allFunctions.push(fn, ...helpers);
|
|
22793
22792
|
}
|
|
22794
22793
|
}
|
|
@@ -22825,6 +22824,7 @@ var require_lower2 = __commonJS({
|
|
|
22825
22824
|
this.constValues = /* @__PURE__ */ new Map();
|
|
22826
22825
|
this.singletonStructs = /* @__PURE__ */ new Set();
|
|
22827
22826
|
this.displayImpls = /* @__PURE__ */ new Map();
|
|
22827
|
+
this.globalVarNames = /* @__PURE__ */ new Set();
|
|
22828
22828
|
this.namespace = namespace;
|
|
22829
22829
|
this.fnName = fnName;
|
|
22830
22830
|
this.structDefs = structDefs;
|
|
@@ -22912,13 +22912,14 @@ var require_lower2 = __commonJS({
|
|
|
22912
22912
|
return `${this.namespace}_${this.fnName}_${varName}_${this.stringVarCount++}`;
|
|
22913
22913
|
}
|
|
22914
22914
|
};
|
|
22915
|
-
function lowerFunction(fn, namespace, structDefs = /* @__PURE__ */ new Map(), implMethods = /* @__PURE__ */ new Map(), macroInfo = /* @__PURE__ */ new Map(), fnParamInfo = /* @__PURE__ */ new Map(), enumDefs = /* @__PURE__ */ new Map(), sourceFile, timerCounter = { count: 0, timerId: 0 }, arrayArgBindings, hirFnMap, specializedFnsRegistry, overrideName, enumPayloads = /* @__PURE__ */ new Map(), constValues = /* @__PURE__ */ new Map(), singletonStructs = /* @__PURE__ */ new Set(), displayImpls = /* @__PURE__ */ new Map()) {
|
|
22915
|
+
function lowerFunction(fn, namespace, structDefs = /* @__PURE__ */ new Map(), implMethods = /* @__PURE__ */ new Map(), macroInfo = /* @__PURE__ */ new Map(), fnParamInfo = /* @__PURE__ */ new Map(), enumDefs = /* @__PURE__ */ new Map(), sourceFile, timerCounter = { count: 0, timerId: 0 }, arrayArgBindings, hirFnMap, specializedFnsRegistry, overrideName, enumPayloads = /* @__PURE__ */ new Map(), constValues = /* @__PURE__ */ new Map(), singletonStructs = /* @__PURE__ */ new Set(), displayImpls = /* @__PURE__ */ new Map(), globalVarNames = /* @__PURE__ */ new Set()) {
|
|
22916
22916
|
const mirFnName = overrideName ?? fn.name;
|
|
22917
22917
|
const ctx = new FnContext(namespace, mirFnName, structDefs, implMethods, macroInfo, fnParamInfo, enumDefs, timerCounter, enumPayloads);
|
|
22918
22918
|
ctx.sourceFile = fn.sourceFile ?? sourceFile;
|
|
22919
22919
|
ctx.constValues = constValues;
|
|
22920
22920
|
ctx.singletonStructs = singletonStructs;
|
|
22921
22921
|
ctx.displayImpls = displayImpls;
|
|
22922
|
+
ctx.globalVarNames = globalVarNames;
|
|
22922
22923
|
if (hirFnMap)
|
|
22923
22924
|
ctx.hirFunctions = hirFnMap;
|
|
22924
22925
|
if (specializedFnsRegistry)
|
|
@@ -22969,11 +22970,12 @@ var require_lower2 = __commonJS({
|
|
|
22969
22970
|
};
|
|
22970
22971
|
return { fn: result, helpers: ctx.helperFunctions };
|
|
22971
22972
|
}
|
|
22972
|
-
function lowerImplMethod(method, typeName, namespace, structDefs, implMethods, macroInfo = /* @__PURE__ */ new Map(), fnParamInfo = /* @__PURE__ */ new Map(), enumDefs = /* @__PURE__ */ new Map(), sourceFile, timerCounter = { count: 0, timerId: 0 }, enumPayloads = /* @__PURE__ */ new Map(), constValues = /* @__PURE__ */ new Map()) {
|
|
22973
|
+
function lowerImplMethod(method, typeName, namespace, structDefs, implMethods, macroInfo = /* @__PURE__ */ new Map(), fnParamInfo = /* @__PURE__ */ new Map(), enumDefs = /* @__PURE__ */ new Map(), sourceFile, timerCounter = { count: 0, timerId: 0 }, enumPayloads = /* @__PURE__ */ new Map(), constValues = /* @__PURE__ */ new Map(), globalVarNames = /* @__PURE__ */ new Set()) {
|
|
22973
22974
|
const fnName = `${typeName}::${method.name}`;
|
|
22974
22975
|
const ctx = new FnContext(namespace, fnName, structDefs, implMethods, macroInfo, fnParamInfo, enumDefs, timerCounter, enumPayloads);
|
|
22975
22976
|
ctx.sourceFile = method.sourceFile ?? sourceFile;
|
|
22976
22977
|
ctx.constValues = constValues;
|
|
22978
|
+
ctx.globalVarNames = globalVarNames;
|
|
22977
22979
|
const fields = structDefs.get(typeName) ?? [];
|
|
22978
22980
|
const hasSelf = method.params.length > 0 && method.params[0].name === "self";
|
|
22979
22981
|
const params = [];
|
|
@@ -23674,7 +23676,7 @@ var require_lower2 = __commonJS({
|
|
|
23674
23676
|
}
|
|
23675
23677
|
case "raw": {
|
|
23676
23678
|
const ns = ctx.getNamespace();
|
|
23677
|
-
const rawCmd = stmt.cmd.replace(/__NS__/g, ns).replace(/__OBJ__/g, `__${ns}`);
|
|
23679
|
+
const rawCmd = stmt.cmd.replace(/__NS__/g, ns).replace(/__OBJ__/g, `__${ns}`).replace(/__RS__/g, "rs");
|
|
23678
23680
|
ctx.emit({ kind: "call", dst: null, fn: `__raw:${rawCmd}`, args: [] });
|
|
23679
23681
|
break;
|
|
23680
23682
|
}
|
|
@@ -23828,6 +23830,12 @@ var require_lower2 = __commonJS({
|
|
|
23828
23830
|
if (ctx.constValues.has(expr.name)) {
|
|
23829
23831
|
return { kind: "const", value: ctx.constValues.get(expr.name) };
|
|
23830
23832
|
}
|
|
23833
|
+
if (ctx.globalVarNames.has(expr.name)) {
|
|
23834
|
+
const t2 = ctx.freshTemp();
|
|
23835
|
+
ctx.emit({ kind: "score_read", dst: t2, player: expr.name, obj: `__${ctx.getNamespace()}` });
|
|
23836
|
+
scope.set(expr.name, t2);
|
|
23837
|
+
return { kind: "temp", name: t2 };
|
|
23838
|
+
}
|
|
23831
23839
|
const t = ctx.freshTemp();
|
|
23832
23840
|
ctx.emit({ kind: "copy", dst: t, src: { kind: "const", value: 0 } });
|
|
23833
23841
|
scope.set(expr.name, t);
|
|
@@ -23921,6 +23929,25 @@ var require_lower2 = __commonJS({
|
|
|
23921
23929
|
}
|
|
23922
23930
|
case "assign": {
|
|
23923
23931
|
const val = lowerExpr(expr.value, ctx, scope);
|
|
23932
|
+
const sv = ctx.structVars.get(expr.target);
|
|
23933
|
+
if (sv) {
|
|
23934
|
+
const fields = ctx.structDefs.get(sv.typeName) ?? [];
|
|
23935
|
+
for (const fieldName of fields) {
|
|
23936
|
+
const existingFieldTemp = sv.fields.get(fieldName);
|
|
23937
|
+
const fieldTemp = existingFieldTemp ?? ctx.freshTemp();
|
|
23938
|
+
ctx.emit({ kind: "copy", dst: fieldTemp, src: { kind: "temp", name: `__rf_${fieldName}` } });
|
|
23939
|
+
sv.fields.set(fieldName, fieldTemp);
|
|
23940
|
+
}
|
|
23941
|
+
return val;
|
|
23942
|
+
}
|
|
23943
|
+
if (ctx.globalVarNames.has(expr.target)) {
|
|
23944
|
+
const globalObj = `__${ctx.getNamespace()}`;
|
|
23945
|
+
ctx.emit({ kind: "score_write", player: expr.target, obj: globalObj, src: val });
|
|
23946
|
+
const t2 = ctx.freshTemp();
|
|
23947
|
+
ctx.emit({ kind: "score_read", dst: t2, player: expr.target, obj: globalObj });
|
|
23948
|
+
scope.set(expr.target, t2);
|
|
23949
|
+
return val;
|
|
23950
|
+
}
|
|
23924
23951
|
const existing = scope.get(expr.target);
|
|
23925
23952
|
const t = existing ?? ctx.freshTemp();
|
|
23926
23953
|
ctx.emit({ kind: "copy", dst: t, src: val });
|
|
@@ -24259,6 +24286,59 @@ var require_lower2 = __commonJS({
|
|
|
24259
24286
|
return { kind: "temp", name: t2 };
|
|
24260
24287
|
}
|
|
24261
24288
|
if (macro_1.BUILTIN_SET.has(expr.fn)) {
|
|
24289
|
+
if (expr.fn === "say" && expr.args[0]?.kind === "f_string") {
|
|
24290
|
+
const fstr = precomputeFStringParts(expr.args[0], ctx, scope);
|
|
24291
|
+
if (fstr.kind === "f_string") {
|
|
24292
|
+
const ns = ctx.getNamespace();
|
|
24293
|
+
const obj = `__${ns}`;
|
|
24294
|
+
const helperName = `${ctx.getFnName()}__say_macro_${ctx.freshTemp()}`;
|
|
24295
|
+
let template = "say ";
|
|
24296
|
+
const macroVarNames = [];
|
|
24297
|
+
for (const part of fstr.parts) {
|
|
24298
|
+
if (part.kind === "text") {
|
|
24299
|
+
template += part.value;
|
|
24300
|
+
} else {
|
|
24301
|
+
const inner = part.expr;
|
|
24302
|
+
if (inner.kind === "ident") {
|
|
24303
|
+
const varName = inner.name.startsWith("$") ? inner.name.slice(1) : inner.name;
|
|
24304
|
+
template += `$(${varName})`;
|
|
24305
|
+
macroVarNames.push(inner.name);
|
|
24306
|
+
} else if (inner.kind === "int_lit") {
|
|
24307
|
+
template += String(inner.value);
|
|
24308
|
+
} else {
|
|
24309
|
+
template += "?";
|
|
24310
|
+
}
|
|
24311
|
+
}
|
|
24312
|
+
}
|
|
24313
|
+
for (const varName of macroVarNames) {
|
|
24314
|
+
const cleanName = varName.startsWith("$") ? varName.slice(1) : varName;
|
|
24315
|
+
ctx.emit({
|
|
24316
|
+
kind: "call",
|
|
24317
|
+
dst: null,
|
|
24318
|
+
fn: `__raw:execute store result storage rs:macro_args ${cleanName} int 1 run scoreboard players get ${varName} ${obj}`,
|
|
24319
|
+
args: []
|
|
24320
|
+
});
|
|
24321
|
+
}
|
|
24322
|
+
const helperCtx = new FnContext(ns, helperName, ctx.structDefs, ctx.implMethods);
|
|
24323
|
+
helperCtx.emit({ kind: "call", dst: null, fn: `__raw:$${template}`, args: [] });
|
|
24324
|
+
helperCtx.terminate({ kind: "return", value: null });
|
|
24325
|
+
const helperReachable = computeReachable(helperCtx.blocks, "entry");
|
|
24326
|
+
const helperBlocks = helperCtx.blocks.filter((b) => helperReachable.has(b.id));
|
|
24327
|
+
computePreds(helperBlocks);
|
|
24328
|
+
ctx.helperFunctions.push({
|
|
24329
|
+
name: helperName,
|
|
24330
|
+
params: [],
|
|
24331
|
+
blocks: helperBlocks,
|
|
24332
|
+
entry: "entry",
|
|
24333
|
+
isMacro: true,
|
|
24334
|
+
sourceSnippet: "say macro helper"
|
|
24335
|
+
});
|
|
24336
|
+
ctx.emit({ kind: "call", dst: null, fn: `__raw:function ${ns}:${helperName} with storage rs:macro_args`, args: [] });
|
|
24337
|
+
const t3 = ctx.freshTemp();
|
|
24338
|
+
ctx.emit({ kind: "const", dst: t3, value: 0 });
|
|
24339
|
+
return { kind: "temp", name: t3 };
|
|
24340
|
+
}
|
|
24341
|
+
}
|
|
24262
24342
|
const TEXT_BUILTINS_SET = /* @__PURE__ */ new Set(["tell", "tellraw", "title", "subtitle", "actionbar", "announce"]);
|
|
24263
24343
|
let resolvedArgs = expr.args;
|
|
24264
24344
|
if (TEXT_BUILTINS_SET.has(expr.fn)) {
|
|
@@ -24389,7 +24469,7 @@ var require_lower2 = __commonJS({
|
|
|
24389
24469
|
const specializedName = `${expr.fn}__arr_${bindingKey}`;
|
|
24390
24470
|
if (!ctx.specializedFnsRegistry.has(specializedName)) {
|
|
24391
24471
|
ctx.specializedFnsRegistry.set(specializedName, []);
|
|
24392
|
-
const { fn: specFn, helpers: specHelpers } = lowerFunction(targetHirFn, ctx.getNamespace(), ctx.structDefs, ctx.implMethods, ctx.macroInfo, ctx.fnParamInfo, ctx.enumDefs, ctx.sourceFile, ctx.timerCounter, arrayArgBindings, ctx.hirFunctions, ctx.specializedFnsRegistry, specializedName, ctx.enumPayloads, ctx.constValues, ctx.singletonStructs, ctx.displayImpls);
|
|
24472
|
+
const { fn: specFn, helpers: specHelpers } = lowerFunction(targetHirFn, ctx.getNamespace(), ctx.structDefs, ctx.implMethods, ctx.macroInfo, ctx.fnParamInfo, ctx.enumDefs, ctx.sourceFile, ctx.timerCounter, arrayArgBindings, ctx.hirFunctions, ctx.specializedFnsRegistry, specializedName, ctx.enumPayloads, ctx.constValues, ctx.singletonStructs, ctx.displayImpls, ctx.globalVarNames);
|
|
24393
24473
|
ctx.specializedFnsRegistry.set(specializedName, [specFn, ...specHelpers]);
|
|
24394
24474
|
}
|
|
24395
24475
|
const nonArrayArgs = [];
|
|
@@ -26616,7 +26696,7 @@ var require_interprocedural = __commonJS({
|
|
|
26616
26696
|
const mangledName = mangleName(instr.fn, constArgs.map((a) => a.value));
|
|
26617
26697
|
if (fnMap.has(mangledName) || added.has(mangledName))
|
|
26618
26698
|
continue;
|
|
26619
|
-
const specialized = specialize(callee, constArgs.map((a) => a.value), mangledName);
|
|
26699
|
+
const specialized = specialize(callee, constArgs.map((a) => a.value), mangledName, mod.objective);
|
|
26620
26700
|
newFunctions.push(specialized);
|
|
26621
26701
|
added.add(mangledName);
|
|
26622
26702
|
fnMap.set(mangledName, specialized);
|
|
@@ -26642,12 +26722,37 @@ var require_interprocedural = __commonJS({
|
|
|
26642
26722
|
function mangleName(name, args) {
|
|
26643
26723
|
return `${name}__const_${args.map((v) => v < 0 ? `n${Math.abs(v)}` : String(v)).join("_")}`;
|
|
26644
26724
|
}
|
|
26645
|
-
function
|
|
26725
|
+
function hasRawParamRefs(fn, paramCount) {
|
|
26726
|
+
for (let i = 0; i < paramCount; i++) {
|
|
26727
|
+
const pattern = `$p${i}`;
|
|
26728
|
+
for (const block of fn.blocks) {
|
|
26729
|
+
for (const instr of block.instrs) {
|
|
26730
|
+
if (instr.kind === "call" && instr.fn.startsWith("__raw:") && instr.fn.includes(pattern)) {
|
|
26731
|
+
return true;
|
|
26732
|
+
}
|
|
26733
|
+
}
|
|
26734
|
+
}
|
|
26735
|
+
}
|
|
26736
|
+
return false;
|
|
26737
|
+
}
|
|
26738
|
+
function specialize(fn, args, newName, objective) {
|
|
26646
26739
|
const sub = /* @__PURE__ */ new Map();
|
|
26647
26740
|
for (let i = 0; i < fn.params.length; i++) {
|
|
26648
26741
|
sub.set(fn.params[i].name, { kind: "const", value: args[i] });
|
|
26649
26742
|
}
|
|
26650
26743
|
const newBlocks = fn.blocks.map((block) => substituteBlock(block, sub));
|
|
26744
|
+
if (hasRawParamRefs(fn, args.length)) {
|
|
26745
|
+
const entryBlock = newBlocks.find((b) => b.id === fn.entry);
|
|
26746
|
+
if (entryBlock) {
|
|
26747
|
+
const scoreWrites = args.map((value, i) => ({
|
|
26748
|
+
kind: "score_write",
|
|
26749
|
+
player: `$p${i}`,
|
|
26750
|
+
obj: objective,
|
|
26751
|
+
src: { kind: "const", value }
|
|
26752
|
+
}));
|
|
26753
|
+
entryBlock.instrs = [...scoreWrites, ...entryBlock.instrs];
|
|
26754
|
+
}
|
|
26755
|
+
}
|
|
26651
26756
|
const specialized = {
|
|
26652
26757
|
...fn,
|
|
26653
26758
|
name: newName,
|