@bitcobblers/wod-wiki-lang 0.10.42 → 0.35.2115
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/dist/{browserRuntimeNow-je1Vb5bU.d.cts → browserRuntimeNow-CoR7dCNU.d.cts} +146 -134
- package/dist/{browserRuntimeNow-je1Vb5bU.d.ts → browserRuntimeNow-CoR7dCNU.d.ts} +146 -134
- package/dist/index.cjs +632 -108
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +194 -42
- package/dist/index.d.ts +194 -42
- package/dist/index.mjs +626 -106
- package/dist/index.mjs.map +1 -1
- package/dist/react.cjs +16 -21
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +3 -3
- package/dist/react.d.ts +3 -3
- package/dist/react.mjs +16 -21
- package/dist/react.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { wallClockNow, formatDurationSmart } from './chunk-PFQDVQQO.mjs';
|
|
2
2
|
export { createBrowserRuntimeNow, frozenNow, getRuntimeNowMs, wallClockNow } from './chunk-PFQDVQQO.mjs';
|
|
3
|
-
import { MetricType, MetricContainer, BlockKey, ParsedCodeStatement, OutputStatement } from '@bitcobblers/wod-wiki-core';
|
|
3
|
+
import { MetricType, MetricContainer, BlockKey, ParsedCodeStatement, OutputStatement, valueKindOf, normalizeFieldPath } from '@bitcobblers/wod-wiki-core';
|
|
4
4
|
import { LRParser } from '@lezer/lr';
|
|
5
5
|
import { LRLanguage, LanguageSupport } from '@codemirror/language';
|
|
6
6
|
import { NodeProp } from '@lezer/common';
|
|
@@ -74,8 +74,8 @@ function metricsOf(source) {
|
|
|
74
74
|
if (Array.isArray(m)) return m;
|
|
75
75
|
return m.rawMetrics ?? [];
|
|
76
76
|
}
|
|
77
|
-
function hintMetric(hint, origin = "dialect") {
|
|
78
|
-
return { type: MetricType.Hint, value: hint, image: hint, origin };
|
|
77
|
+
function hintMetric(hint, origin = "dialect", icon) {
|
|
78
|
+
return { type: MetricType.Hint, value: hint, image: hint, origin, ...icon ? { icon } : {} };
|
|
79
79
|
}
|
|
80
80
|
function hintsToContainer(hints, existing, origin = "dialect") {
|
|
81
81
|
const container = existing ?? MetricContainer.empty("dialect");
|
|
@@ -456,6 +456,19 @@ var ChoiceGroupMetric = class {
|
|
|
456
456
|
value;
|
|
457
457
|
image;
|
|
458
458
|
};
|
|
459
|
+
var IntensityMetric = class {
|
|
460
|
+
constructor(value, unit = "%") {
|
|
461
|
+
this.unit = unit;
|
|
462
|
+
this.value = { amount: value, unit };
|
|
463
|
+
this.image = value !== void 0 ? `${value}${unit}` : `?${unit}`;
|
|
464
|
+
this.origin = value === void 0 ? "hinted" : "parser";
|
|
465
|
+
}
|
|
466
|
+
unit;
|
|
467
|
+
value;
|
|
468
|
+
image;
|
|
469
|
+
origin;
|
|
470
|
+
type = MetricType.Intensity;
|
|
471
|
+
};
|
|
459
472
|
|
|
460
473
|
// src/dialects/units/fuseUnits.ts
|
|
461
474
|
function isBareNumber(m) {
|
|
@@ -614,6 +627,17 @@ function fusePairs(pairs, units) {
|
|
|
614
627
|
}
|
|
615
628
|
}
|
|
616
629
|
}
|
|
630
|
+
if (next && isBareNumber(cur.metric)) {
|
|
631
|
+
const text = effortText(next.metric);
|
|
632
|
+
if (text !== null && text.trim() === "%") {
|
|
633
|
+
out.push({
|
|
634
|
+
metric: new IntensityMetric(cur.metric.value),
|
|
635
|
+
meta: fusedMeta(cur.meta, next.meta, "%")
|
|
636
|
+
});
|
|
637
|
+
i++;
|
|
638
|
+
continue;
|
|
639
|
+
}
|
|
640
|
+
}
|
|
617
641
|
if (next) {
|
|
618
642
|
const fusable = isBareNumber(cur.metric) || hasEmptyUnit(cur.metric);
|
|
619
643
|
if (fusable) {
|
|
@@ -1128,6 +1152,11 @@ var ClimbDialect = class {
|
|
|
1128
1152
|
}
|
|
1129
1153
|
};
|
|
1130
1154
|
|
|
1155
|
+
// src/logger.ts
|
|
1156
|
+
function langWarn(message) {
|
|
1157
|
+
console.warn(message);
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1131
1160
|
// src/dialects/DialectStack.ts
|
|
1132
1161
|
var UNITS_DIALECT_ID = "units";
|
|
1133
1162
|
var SPORT_ALIASES = {
|
|
@@ -1170,7 +1199,7 @@ var DialectStack = class {
|
|
|
1170
1199
|
if (!all.some((d) => d.id === id)) {
|
|
1171
1200
|
if (!warnedSports.has(sport)) {
|
|
1172
1201
|
warnedSports.add(sport);
|
|
1173
|
-
|
|
1202
|
+
langWarn(
|
|
1174
1203
|
`[DialectStack] Unknown :sport suffix "${sport}" \u2014 falling back to the full dialect stack. Known dialect ids: ${all.map((d) => d.id).join(", ")}.`
|
|
1175
1204
|
);
|
|
1176
1205
|
}
|
|
@@ -1352,8 +1381,20 @@ var PropertyMetric = class {
|
|
|
1352
1381
|
this.image = options.image ?? `${key}: ${formatPropertyValue(value)}`;
|
|
1353
1382
|
this.origin = options.origin ?? "parser";
|
|
1354
1383
|
this.type = options.type ?? MetricType.Custom;
|
|
1384
|
+
const kind = valueKindOf(value);
|
|
1385
|
+
this.metadata = {
|
|
1386
|
+
originalKey: key,
|
|
1387
|
+
...kind !== "object" && kind !== "undefined" ? {
|
|
1388
|
+
fieldRef: {
|
|
1389
|
+
path: normalizeFieldPath(key),
|
|
1390
|
+
kind,
|
|
1391
|
+
...options.dimension ? { dimension: options.dimension } : {}
|
|
1392
|
+
}
|
|
1393
|
+
} : {}
|
|
1394
|
+
};
|
|
1355
1395
|
}
|
|
1356
1396
|
type;
|
|
1397
|
+
metadata;
|
|
1357
1398
|
};
|
|
1358
1399
|
var RepMetric = class {
|
|
1359
1400
|
constructor(reps) {
|
|
@@ -1456,6 +1497,12 @@ function classifyPrimitive(primitive) {
|
|
|
1456
1497
|
}
|
|
1457
1498
|
return primitive.label ? [{ metrics: new RoundsMetric(primitive.label), meta: primitive.meta }] : [];
|
|
1458
1499
|
}
|
|
1500
|
+
case "round_scheme": {
|
|
1501
|
+
return [
|
|
1502
|
+
{ metrics: new RoundsMetric(primitive.rounds), meta: primitive.meta },
|
|
1503
|
+
{ metrics: new RepMetric(primitive.reps), meta: primitive.meta }
|
|
1504
|
+
];
|
|
1505
|
+
}
|
|
1459
1506
|
case "action": {
|
|
1460
1507
|
const actionText = primitive.hasColonPrefix ? primitive.raw.substring(2, primitive.raw.length - 1).trim() : primitive.raw.substring(1, primitive.raw.length - 1).trim();
|
|
1461
1508
|
return [{ metrics: new ActionMetric(actionText, { raw: actionText }), meta: primitive.meta }];
|
|
@@ -1567,17 +1614,17 @@ function mergeFragments(pairs) {
|
|
|
1567
1614
|
}
|
|
1568
1615
|
var parser = LRParser.deserialize({
|
|
1569
1616
|
version: 14,
|
|
1570
|
-
states: "(
|
|
1571
|
-
stateData: "*
|
|
1572
|
-
goto: "$
|
|
1573
|
-
nodeNames: "\u26A0 Program Property Identifier String Number Block Lap Fragment Duration Trend CollectibleTimer Timer Rounds Sequence Action Text Heading Quantity AtSign Question Slash Pipe Effort MetricObject True False Null",
|
|
1574
|
-
maxTerm:
|
|
1617
|
+
states: "(WQVQPOOO!jQPO'#C}O#}QPO'#CcOOQO'#Cc'#CcOOQO'#Cf'#CfOOQO'#Cg'#CgOOQO'#Ce'#CeO%_QPO'#CeO%gQPO'#CiOOQO'#Ck'#CkOOQO'#C}'#C}OOQO'#Ct'#CtO%oQPO'#ClOOQO'#Cm'#CmOOQO'#Cn'#CnOOQO'#Cp'#CpOOQO'#Cq'#CqOOQO'#Co'#CoO%tQPO'#CoOOQO'#Cr'#CrOOQO'#Cs'#CsO&kQPO'#CuOOQO'#Cd'#CdOOQO'#Cz'#CzO(PQPO'#CbO&rQPO'#CbOOQO'#Cy'#CyQVQPOOO(WQPO,58xOOQO,59P,59PO(cQPO'#CjOOQO'#C{'#C{O(qQPO,59TOOQO-E6{-E6{O(|QPO,59WOOQO,59Z,59ZOOQO'#DO'#DOO)XQPO,59aOOQO,59a,59aOOQO-E6x-E6xOOQO,58|,58|O)`QPO,58|OOQO-E6w-E6wOOQO1G.d1G.dO)gQPO'#C|O)lQPO,59UOOQO-E6y-E6yOOQO1G.o1G.oO)zQPO1G.rOOQO-E6|-E6|OOQO1G.{1G.{OOQO1G.h1G.hOOQO,59h,59hOOQO-E6z-E6zOOQO7+$^7+$^",
|
|
1618
|
+
stateData: "*u~OuOS~ORPOTaO[UOwQOxROySOzVO{TO|WO!OXO!PXO!Q[O!RYO!T]O!U^O!V_O!W`O!XcO!YdO!ZeO!^jO~OvlORqXTqX[qXwqXyqXzqX{qX|qX!OqX!PqX!QqX!RqX!TqX!UqX!VqX!WqX!XqX!YqX!ZqX!^qX~ORVXTVX[VXwVXyVXzVX{VX|VX!OVX!PVX!QVX!RVX!TVX!UVX!VVX!WVX!XVX!YVX!ZVX!^qX~O[mO{TO~ORoOTnO~OvrO~OTsO!W`O~ORtOStOTtOjtOktOltOvtO!RtO![tO~O!]vO~P%|ORYOTaO[UOwYOySOzVO{TO|WO!OXO!PXO!Q[O!RYO!T]O!U^O!V_O!W`O!XcO!YdO!ZeO~O!^xO~P&rOR{OS{OT{O~Ow|OR^XT^X}^X~ORoOTnO}!PO~ORYOwYO!RYO~O!]!SO~P%|O!^!TO~P&rOT!UO~Ow|OR^aT^a}^a~ORYOwYO!RYO!S!WO~O!T!U!O!P{[!Vyzv!X!Y!R!Z!]![jklRwxT!^u!R~",
|
|
1619
|
+
goto: "$UsPPtPPPtx|!T![!cP!T!m!T!T!T!T!T!q!x!T!T!T!TPPP#S#Y#e#k#q$OTjOkTiOkZgOhikyZfOhikyZVOhikyYUOhikyRmVToWpZbOhikyYaOhikyRsbQkORzkShOkSwhyRyiQpWR!OpQ}nR!V}YZOhikyQq!QR!QrQueR!Ru",
|
|
1620
|
+
nodeNames: "\u26A0 Program Property Identifier String Number Block Lap Fragment Duration Trend CollectibleTimer Timer Rounds Sequence RoundScheme Action Text Heading Quantity AtSign Question Slash Pipe Effort MetricObject True False Null",
|
|
1621
|
+
maxTerm: 60,
|
|
1575
1622
|
skippedNodes: [0],
|
|
1576
1623
|
repeatNodeCount: 6,
|
|
1577
|
-
tokenData: "
|
|
1624
|
+
tokenData: "6k~RvXY#iYZ#z]^$Ppq#iqr$Vrs$}st'dtu$Vuv$Vvw$Vxy(Oyz(Tz{(Y{|)S|})X}!O*R!O!P*W!P!Q+Z!Q![+}![!].Q!_!`$V!a!b.j!b!c.o!c!}/i!}#O/w#O#P$V#P#Q/|#Q#R0R#T#Y/i#Y#Z0{#Z#b/i#b#c2|#c#h/i#h#i4l#i#o/i#o#p6[#p#q6a#q#r6f~#nSu~XY#iYZ#z]^$Ppq#i~$PO!^~~$SPYZ#z~$[Z!R~qr$Vtu$Vuv$Vvw$Vz{$V|}$V!O!P$V!_!`$V!b!c$V#O#P$V#Q#R$V~%QXOY$}Z]$}^r$}rs%ms#O$}#O#P&_#P;'S$};'S;=`'^<%lO$}~%rXS~OY$}Z]$}^r$}rs%ms#O$}#O#P&_#P;'S$};'S;=`'^<%lO$}~&bRO;'S$};'S;=`&k;=`O$}~&nYOY$}Z]$}^r$}rs%ms#O$}#O#P&_#P;'S$};'S;=`'^;=`<%l$}<%lO$}~'aP;=`<%l$}~'iT!U~OY'dZ]'d^;'S'd;'S;=`'x<%lO'd~'{P;=`<%l'd~(TO|~~(YO}~~(aZz~!R~qr$Vtu$Vuv$Vvw$Vz{$V|}$V!O!P$V!_!`$V!b!c$V#O#P$V#Q#R$V~)XOx~~)`Z!R~![~qr$Vtu$Vuv$Vvw$Vz{$V|}$V!O!P$V!_!`$V!b!c$V#O#P$V#Q#R$V~*WOw~~*][!R~qr$Vtu$Vuv$Vvw$Vz{$V|}$V!O!P$V!Q![+R!_!`$V!b!c$V#O#P$V#Q#R$V~+WPT~!Q![+R~+`P!X~!P!Q+c~+hT!T~OY+cZ]+c^;'S+c;'S;=`+w<%lO+c~+zP;=`<%l+c~,SUT~pq,f!O!P-Z!Q![+}![!]-a!z!{-r#l#m-r~,iRpq,f!z!{,r#l#m,r~,uPpq,x~,{Qpq,x!Q![-R~-WP!P~!Q![-R~-^P!Q![+R~-dP!Q![-g~-lQ[~!Q![-g![!]-a~-uP!Q![-x~-}P!O~!Q![-x~.VQv~!Q![.]!a!b.e~.bP[~!Q![.]~.jO{~~.oO!W~~.vZ!V~!R~qr$Vtu$Vuv$Vvw$Vz{$V|}$V!O!P$V!_!`$V!b!c$V#O#P$V#Q#R$V~/nRR~!Q![/i!c!}/i#T#o/i~/|O!Q~~0RO!S~~0YZy~!R~qr$Vtu$Vuv$Vvw$Vz{$V|}$V!O!P$V!_!`$V!b!c$V#O#P$V#Q#R$V~1QSR~!Q![/i!c!}/i#T#U1^#U#o/i~1cTR~!Q![/i!c!}/i#T#`/i#`#a1r#a#o/i~1wTR~!Q![/i!c!}/i#T#g/i#g#h2W#h#o/i~2]TR~!Q![/i!c!}/i#T#X/i#X#Y2l#Y#o/i~2sRk~R~!Q![/i!c!}/i#T#o/i~3RTR~!Q![/i!c!}/i#T#i/i#i#j3b#j#o/i~3gTR~!Q![/i!c!}/i#T#`/i#`#a3v#a#o/i~3{TR~!Q![/i!c!}/i#T#`/i#`#a4[#a#o/i~4cRl~R~!Q![/i!c!}/i#T#o/i~4qTR~!Q![/i!c!}/i#T#f/i#f#g5Q#g#o/i~5VTR~!Q![/i!c!}/i#T#i/i#i#j5f#j#o/i~5kTR~!Q![/i!c!}/i#T#X/i#X#Y5z#Y#o/i~6RRj~R~!Q![/i!c!}/i#T#o/i~6aO!Z~~6fO!Y~~6kO!]~",
|
|
1578
1625
|
tokenizers: [0],
|
|
1579
1626
|
topRules: { "Program": [0, 1] },
|
|
1580
|
-
tokenPrec:
|
|
1627
|
+
tokenPrec: 424
|
|
1581
1628
|
});
|
|
1582
1629
|
|
|
1583
1630
|
// src/grammar/parser.terms.ts
|
|
@@ -1585,14 +1632,15 @@ var Lap = 7;
|
|
|
1585
1632
|
var Fragment = 8;
|
|
1586
1633
|
var Duration = 9;
|
|
1587
1634
|
var Rounds = 13;
|
|
1588
|
-
var
|
|
1589
|
-
var
|
|
1590
|
-
var
|
|
1591
|
-
var
|
|
1592
|
-
var
|
|
1593
|
-
var
|
|
1594
|
-
var
|
|
1595
|
-
var
|
|
1635
|
+
var RoundScheme = 15;
|
|
1636
|
+
var Action = 16;
|
|
1637
|
+
var Text = 17;
|
|
1638
|
+
var Heading = 18;
|
|
1639
|
+
var Quantity = 19;
|
|
1640
|
+
var Slash = 22;
|
|
1641
|
+
var Pipe = 23;
|
|
1642
|
+
var Effort = 24;
|
|
1643
|
+
var MetricObject = 25;
|
|
1596
1644
|
|
|
1597
1645
|
// src/parser/syntax-parser.ts
|
|
1598
1646
|
function createLineLocator(source) {
|
|
@@ -1641,7 +1689,7 @@ function extractSyntaxFacts(sourceOrState, treeArg) {
|
|
|
1641
1689
|
if (primitive) {
|
|
1642
1690
|
const meta2 = primitive.meta;
|
|
1643
1691
|
statements.push({
|
|
1644
|
-
id:
|
|
1692
|
+
id: statements.length,
|
|
1645
1693
|
line: meta2.line,
|
|
1646
1694
|
meta: meta2,
|
|
1647
1695
|
primitives: [primitive],
|
|
@@ -1656,7 +1704,7 @@ function extractSyntaxFacts(sourceOrState, treeArg) {
|
|
|
1656
1704
|
lastProperty = null;
|
|
1657
1705
|
const statementMeta = createMeta(locator, node.from, node.to, source.slice(node.from, node.to));
|
|
1658
1706
|
const statement = {
|
|
1659
|
-
id:
|
|
1707
|
+
id: statements.length,
|
|
1660
1708
|
line: statementMeta.line,
|
|
1661
1709
|
meta: statementMeta,
|
|
1662
1710
|
primitives: [],
|
|
@@ -1749,6 +1797,18 @@ function mapFragmentToPrimitive(locator, source, node) {
|
|
|
1749
1797
|
};
|
|
1750
1798
|
return primitive;
|
|
1751
1799
|
}
|
|
1800
|
+
case RoundScheme: {
|
|
1801
|
+
const match = raw.match(/^(\d+)\s*[xX]\s*(\d+)$/);
|
|
1802
|
+
if (!match) return null;
|
|
1803
|
+
const primitive = {
|
|
1804
|
+
kind: "round_scheme",
|
|
1805
|
+
raw,
|
|
1806
|
+
meta: meta2,
|
|
1807
|
+
rounds: parseInt(match[1], 10),
|
|
1808
|
+
reps: parseInt(match[2], 10)
|
|
1809
|
+
};
|
|
1810
|
+
return primitive;
|
|
1811
|
+
}
|
|
1752
1812
|
case Action: {
|
|
1753
1813
|
const primitive = {
|
|
1754
1814
|
kind: "action",
|
|
@@ -1883,23 +1943,22 @@ function createMeta(locator, from, to, raw) {
|
|
|
1883
1943
|
raw
|
|
1884
1944
|
};
|
|
1885
1945
|
}
|
|
1886
|
-
|
|
1887
|
-
// src/parser/lezer-mapper.ts
|
|
1888
|
-
function extractStatementsRaw(sourceOrTree, treeArg) {
|
|
1889
|
-
let source;
|
|
1890
|
-
let tree = treeArg;
|
|
1946
|
+
function resolveSourceInput(sourceOrTree, treeArg) {
|
|
1891
1947
|
if (typeof sourceOrTree === "string") {
|
|
1892
|
-
source
|
|
1893
|
-
}
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
} else if ("doc" in sourceOrTree) {
|
|
1897
|
-
source = sourceOrTree.doc.toString();
|
|
1898
|
-
} else {
|
|
1899
|
-
source = "";
|
|
1948
|
+
return { source: sourceOrTree, tree: treeArg };
|
|
1949
|
+
}
|
|
1950
|
+
if ("source" in sourceOrTree) {
|
|
1951
|
+
return { source: sourceOrTree.source, tree: treeArg ?? sourceOrTree.tree };
|
|
1900
1952
|
}
|
|
1953
|
+
if ("doc" in sourceOrTree) {
|
|
1954
|
+
return { source: sourceOrTree.doc.toString(), tree: treeArg };
|
|
1955
|
+
}
|
|
1956
|
+
return { source: "" };
|
|
1957
|
+
}
|
|
1958
|
+
function extractStatementsRaw(sourceOrTree, treeArg) {
|
|
1959
|
+
const { source, tree } = resolveSourceInput(sourceOrTree, treeArg);
|
|
1901
1960
|
const facts = extractSyntaxFacts(source, tree);
|
|
1902
|
-
return classifyStatements(facts);
|
|
1961
|
+
return normalizeInlineRounds(classifyStatements(facts));
|
|
1903
1962
|
}
|
|
1904
1963
|
function extractStatements(sourceOrTree, sportOrTree, sportArg) {
|
|
1905
1964
|
let sport;
|
|
@@ -1910,9 +1969,70 @@ function extractStatements(sourceOrTree, sportOrTree, sportArg) {
|
|
|
1910
1969
|
tree = sportOrTree;
|
|
1911
1970
|
sport = sportArg;
|
|
1912
1971
|
}
|
|
1913
|
-
const
|
|
1972
|
+
const resolved = resolveSourceInput(sourceOrTree, tree);
|
|
1973
|
+
const facts = extractSyntaxFacts(resolved.source, resolved.tree);
|
|
1974
|
+
const statements = classifyStatements(facts);
|
|
1914
1975
|
dialectStack.processAll(statements, sport);
|
|
1915
|
-
return statements;
|
|
1976
|
+
return normalizeInlineRounds(statements);
|
|
1977
|
+
}
|
|
1978
|
+
function isInlineRoundsPrescription(stmt) {
|
|
1979
|
+
if (stmt.children.length > 0) return false;
|
|
1980
|
+
return stmt.metrics.some((m) => m.type === MetricType.Rounds) && stmt.metrics.some((m) => m.type === MetricType.Rep) && !stmt.metrics.some((m) => m.type === MetricType.Duration);
|
|
1981
|
+
}
|
|
1982
|
+
function cloneStatement(stmt) {
|
|
1983
|
+
const clone = Object.create(Object.getPrototypeOf(stmt));
|
|
1984
|
+
Object.assign(clone, stmt);
|
|
1985
|
+
return clone;
|
|
1986
|
+
}
|
|
1987
|
+
function normalizeInlineRounds(statements) {
|
|
1988
|
+
if (!statements.some(isInlineRoundsPrescription)) return statements;
|
|
1989
|
+
const out = [];
|
|
1990
|
+
const oldToNew = /* @__PURE__ */ new Map();
|
|
1991
|
+
const directParentOf = /* @__PURE__ */ new Map();
|
|
1992
|
+
const childCloneOf = /* @__PURE__ */ new Map();
|
|
1993
|
+
const splitOriginOf = /* @__PURE__ */ new Map();
|
|
1994
|
+
for (const stmt of statements) {
|
|
1995
|
+
if (!isInlineRoundsPrescription(stmt)) {
|
|
1996
|
+
oldToNew.set(stmt.id, out.length);
|
|
1997
|
+
out.push(stmt);
|
|
1998
|
+
continue;
|
|
1999
|
+
}
|
|
2000
|
+
if (stmt.parent !== void 0) directParentOf.set(stmt.id, stmt.parent);
|
|
2001
|
+
const parent = cloneStatement(stmt);
|
|
2002
|
+
const child = cloneStatement(stmt);
|
|
2003
|
+
const isScheme = (m) => m.type === MetricType.Rounds || m.type === MetricType.Rep;
|
|
2004
|
+
parent.metrics = MetricContainer.from(stmt.metrics.filter(isScheme), parent.id);
|
|
2005
|
+
child.metrics = MetricContainer.from(stmt.metrics.filter((m) => !isScheme(m)), child.id);
|
|
2006
|
+
parent.metricMeta = new Map([...stmt.metricMeta].filter(([m]) => isScheme(m)));
|
|
2007
|
+
child.metricMeta = new Map([...stmt.metricMeta].filter(([m]) => !isScheme(m)));
|
|
2008
|
+
parent.isLeaf = false;
|
|
2009
|
+
child.isLeaf = true;
|
|
2010
|
+
parent.children = [];
|
|
2011
|
+
child.children = [];
|
|
2012
|
+
childCloneOf.set(child, parent);
|
|
2013
|
+
splitOriginOf.set(parent, stmt.id);
|
|
2014
|
+
oldToNew.set(stmt.id, out.length);
|
|
2015
|
+
out.push(parent, child);
|
|
2016
|
+
}
|
|
2017
|
+
return out.map((stmt, id) => {
|
|
2018
|
+
const oldId = stmt.id;
|
|
2019
|
+
stmt.id = id;
|
|
2020
|
+
stmt.metrics = MetricContainer.from(stmt.metrics, stmt.id);
|
|
2021
|
+
const parentClone = childCloneOf.get(stmt);
|
|
2022
|
+
if (parentClone) {
|
|
2023
|
+
stmt.parent = id - 1;
|
|
2024
|
+
return stmt;
|
|
2025
|
+
}
|
|
2026
|
+
if (splitOriginOf.has(stmt)) {
|
|
2027
|
+
stmt.children = [[id + 1]];
|
|
2028
|
+
const oldParent = directParentOf.get(splitOriginOf.get(stmt));
|
|
2029
|
+
stmt.parent = oldParent === void 0 ? void 0 : oldToNew.get(oldParent);
|
|
2030
|
+
return stmt;
|
|
2031
|
+
}
|
|
2032
|
+
stmt.parent = stmt.parent === void 0 ? void 0 : oldToNew.get(stmt.parent);
|
|
2033
|
+
stmt.children = stmt.children.map((group) => group.filter((childId) => !directParentOf.has(childId) || directParentOf.get(childId) === oldId).map((childId) => oldToNew.get(childId) ?? childId)).filter((group) => group.length > 0);
|
|
2034
|
+
return stmt;
|
|
2035
|
+
});
|
|
1916
2036
|
}
|
|
1917
2037
|
|
|
1918
2038
|
// src/parser/WhiteboardScript.ts
|
|
@@ -1986,7 +2106,7 @@ function parseScript(inputText, options = {}) {
|
|
|
1986
2106
|
const statements = options.withoutDialects ? extractStatementsRaw(inputText, tree) : extractStatements(inputText, tree, sport);
|
|
1987
2107
|
return new WhiteboardScript(inputText, statements, []);
|
|
1988
2108
|
} catch (error) {
|
|
1989
|
-
const msg = error
|
|
2109
|
+
const msg = error instanceof Error ? error.message : "Unknown parse error";
|
|
1990
2110
|
return new WhiteboardScript(inputText, [], [{ message: msg }]);
|
|
1991
2111
|
}
|
|
1992
2112
|
}
|
|
@@ -2647,6 +2767,7 @@ var whiteboardScriptLanguage = LRLanguage.define({
|
|
|
2647
2767
|
Identifier: tags.variableName,
|
|
2648
2768
|
String: tags.string,
|
|
2649
2769
|
Number: tags.number,
|
|
2770
|
+
"schemeNumber schemeSpaced": tags.number,
|
|
2650
2771
|
Timer: tags.keyword,
|
|
2651
2772
|
collectibleTimer: tags.keyword,
|
|
2652
2773
|
textComment: tags.lineComment,
|
|
@@ -3019,6 +3140,7 @@ var BUNDLED_EFFORT_COUNT = bundledEfforts.length;
|
|
|
3019
3140
|
var InMemoryEffortRegistry = class {
|
|
3020
3141
|
efforts = /* @__PURE__ */ new Map();
|
|
3021
3142
|
sourceFilter = null;
|
|
3143
|
+
initialized = false;
|
|
3022
3144
|
constructor(sourceFilter) {
|
|
3023
3145
|
this.sourceFilter = sourceFilter ?? null;
|
|
3024
3146
|
}
|
|
@@ -3029,6 +3151,10 @@ var InMemoryEffortRegistry = class {
|
|
|
3029
3151
|
this.efforts.set(effort.slug, effort);
|
|
3030
3152
|
}
|
|
3031
3153
|
}
|
|
3154
|
+
this.initialized = true;
|
|
3155
|
+
}
|
|
3156
|
+
isInitialized() {
|
|
3157
|
+
return this.initialized;
|
|
3032
3158
|
}
|
|
3033
3159
|
/** Seed with arbitrary efforts (useful for tests) */
|
|
3034
3160
|
seed(efforts) {
|
|
@@ -3039,10 +3165,21 @@ var InMemoryEffortRegistry = class {
|
|
|
3039
3165
|
/** Clear all efforts */
|
|
3040
3166
|
clear() {
|
|
3041
3167
|
this.efforts.clear();
|
|
3168
|
+
this.initialized = false;
|
|
3042
3169
|
}
|
|
3043
3170
|
resolve(slug) {
|
|
3044
3171
|
return this.efforts.get(slug) ?? null;
|
|
3045
3172
|
}
|
|
3173
|
+
resolveByAlias(label) {
|
|
3174
|
+
const normalized = normalizeForFuzzy(label);
|
|
3175
|
+
for (const effort of this.efforts.values()) {
|
|
3176
|
+
if (normalizeForFuzzy(effort.label) === normalized) return effort;
|
|
3177
|
+
for (const alias of effort.aliases) {
|
|
3178
|
+
if (normalizeForFuzzy(alias) === normalized) return effort;
|
|
3179
|
+
}
|
|
3180
|
+
}
|
|
3181
|
+
return null;
|
|
3182
|
+
}
|
|
3046
3183
|
list() {
|
|
3047
3184
|
return Array.from(this.efforts.values());
|
|
3048
3185
|
}
|
|
@@ -3068,6 +3205,159 @@ var InMemoryEffortRegistry = class {
|
|
|
3068
3205
|
}
|
|
3069
3206
|
};
|
|
3070
3207
|
|
|
3208
|
+
// src/effort-registry/CompositeEffortRegistry.ts
|
|
3209
|
+
var CompositeEffortRegistry = class {
|
|
3210
|
+
userEfforts = /* @__PURE__ */ new Map();
|
|
3211
|
+
bundledEfforts = /* @__PURE__ */ new Map();
|
|
3212
|
+
initialized = false;
|
|
3213
|
+
initialBundled;
|
|
3214
|
+
storage;
|
|
3215
|
+
constructor(options) {
|
|
3216
|
+
if (options) {
|
|
3217
|
+
this.initialBundled = options.bundled;
|
|
3218
|
+
this.storage = options.storage;
|
|
3219
|
+
}
|
|
3220
|
+
}
|
|
3221
|
+
/**
|
|
3222
|
+
* Initialize the registry:
|
|
3223
|
+
* 1. Load bundled efforts into memory
|
|
3224
|
+
* 2. Load user efforts from storage adapter into memory
|
|
3225
|
+
*/
|
|
3226
|
+
async loadBundled(customBundled) {
|
|
3227
|
+
const seed = customBundled ?? this.initialBundled ?? bundledEfforts;
|
|
3228
|
+
for (const effort of seed) {
|
|
3229
|
+
this.bundledEfforts.set(effort.slug, effort);
|
|
3230
|
+
}
|
|
3231
|
+
if (this.storage) {
|
|
3232
|
+
try {
|
|
3233
|
+
const userEfforts = await this.storage.load();
|
|
3234
|
+
for (const effort of userEfforts) {
|
|
3235
|
+
if (effort.registrySource === "user") {
|
|
3236
|
+
this.userEfforts.set(effort.slug, effort);
|
|
3237
|
+
}
|
|
3238
|
+
}
|
|
3239
|
+
} catch (err) {
|
|
3240
|
+
console.warn("[CompositeEffortRegistry] Failed to load user efforts from storage adapter:", err);
|
|
3241
|
+
}
|
|
3242
|
+
}
|
|
3243
|
+
this.initialized = true;
|
|
3244
|
+
}
|
|
3245
|
+
/** True after loadBundled() has resolved */
|
|
3246
|
+
isInitialized() {
|
|
3247
|
+
return this.initialized;
|
|
3248
|
+
}
|
|
3249
|
+
resolve(slug) {
|
|
3250
|
+
return this.userEfforts.get(slug) ?? this.bundledEfforts.get(slug) ?? null;
|
|
3251
|
+
}
|
|
3252
|
+
resolveByAlias(label) {
|
|
3253
|
+
const normalized = normalizeForFuzzy(label);
|
|
3254
|
+
for (const effort of this.userEfforts.values()) {
|
|
3255
|
+
if (normalizeForFuzzy(effort.label) === normalized) return effort;
|
|
3256
|
+
for (const alias of effort.aliases) {
|
|
3257
|
+
if (normalizeForFuzzy(alias) === normalized) return effort;
|
|
3258
|
+
}
|
|
3259
|
+
}
|
|
3260
|
+
for (const effort of this.bundledEfforts.values()) {
|
|
3261
|
+
if (this.userEfforts.has(effort.slug)) continue;
|
|
3262
|
+
if (normalizeForFuzzy(effort.label) === normalized) return effort;
|
|
3263
|
+
for (const alias of effort.aliases) {
|
|
3264
|
+
if (normalizeForFuzzy(alias) === normalized) return effort;
|
|
3265
|
+
}
|
|
3266
|
+
}
|
|
3267
|
+
return null;
|
|
3268
|
+
}
|
|
3269
|
+
list() {
|
|
3270
|
+
const merged = new Map(this.bundledEfforts);
|
|
3271
|
+
for (const [slug, effort] of this.userEfforts) {
|
|
3272
|
+
merged.set(slug, effort);
|
|
3273
|
+
}
|
|
3274
|
+
return Array.from(merged.values());
|
|
3275
|
+
}
|
|
3276
|
+
listByOrigin(origin) {
|
|
3277
|
+
if (origin === "user") {
|
|
3278
|
+
return Array.from(this.userEfforts.values());
|
|
3279
|
+
}
|
|
3280
|
+
if (origin === "bundled") {
|
|
3281
|
+
return Array.from(this.bundledEfforts.values());
|
|
3282
|
+
}
|
|
3283
|
+
return this.list().filter((e) => e.registrySource === origin);
|
|
3284
|
+
}
|
|
3285
|
+
async upsert(effort) {
|
|
3286
|
+
if (effort.registrySource !== "user") {
|
|
3287
|
+
throw new Error(
|
|
3288
|
+
`CompositeEffortRegistry.upsert: only user efforts can be written. Received registrySource="${effort.registrySource}"`
|
|
3289
|
+
);
|
|
3290
|
+
}
|
|
3291
|
+
this.userEfforts.set(effort.slug, effort);
|
|
3292
|
+
if (this.storage) {
|
|
3293
|
+
try {
|
|
3294
|
+
await this.storage.save(effort);
|
|
3295
|
+
} catch (err) {
|
|
3296
|
+
console.warn("[CompositeEffortRegistry] Failed to persist effort to storage adapter:", err);
|
|
3297
|
+
}
|
|
3298
|
+
}
|
|
3299
|
+
}
|
|
3300
|
+
async delete(slug) {
|
|
3301
|
+
const existing = this.resolve(slug);
|
|
3302
|
+
if (existing && existing.registrySource !== "user") {
|
|
3303
|
+
throw new Error(
|
|
3304
|
+
`CompositeEffortRegistry.delete: cannot delete non-user effort "${slug}"`
|
|
3305
|
+
);
|
|
3306
|
+
}
|
|
3307
|
+
this.userEfforts.delete(slug);
|
|
3308
|
+
if (this.storage) {
|
|
3309
|
+
try {
|
|
3310
|
+
await this.storage.delete(slug);
|
|
3311
|
+
} catch (err) {
|
|
3312
|
+
console.warn("[CompositeEffortRegistry] Failed to delete effort from storage adapter:", err);
|
|
3313
|
+
}
|
|
3314
|
+
}
|
|
3315
|
+
}
|
|
3316
|
+
};
|
|
3317
|
+
|
|
3318
|
+
// src/effort-registry/aliasManagement.ts
|
|
3319
|
+
async function addAliasToEffort(registry, targetSlug, newAlias) {
|
|
3320
|
+
const trimmed = newAlias.trim();
|
|
3321
|
+
if (!trimmed) {
|
|
3322
|
+
throw new Error("Alias cannot be empty");
|
|
3323
|
+
}
|
|
3324
|
+
const existing = registry.resolve(targetSlug);
|
|
3325
|
+
if (!existing) {
|
|
3326
|
+
throw new Error(`Effort "${targetSlug}" not found in registry`);
|
|
3327
|
+
}
|
|
3328
|
+
const normalizedNew = normalizeForFuzzy(trimmed);
|
|
3329
|
+
const alreadyHas = normalizeForFuzzy(existing.label) === normalizedNew || existing.aliases.some((a) => normalizeForFuzzy(a) === normalizedNew);
|
|
3330
|
+
if (alreadyHas) {
|
|
3331
|
+
return existing;
|
|
3332
|
+
}
|
|
3333
|
+
const updatedAliases = [...existing.aliases, trimmed];
|
|
3334
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3335
|
+
if (existing.registrySource === "bundled") {
|
|
3336
|
+
const id = typeof crypto !== "undefined" && typeof crypto.randomUUID === "function" ? `effort-user-${crypto.randomUUID()}` : `effort-user-${Date.now()}`;
|
|
3337
|
+
const userEffort = {
|
|
3338
|
+
...existing,
|
|
3339
|
+
id,
|
|
3340
|
+
registrySource: "user",
|
|
3341
|
+
aliases: updatedAliases,
|
|
3342
|
+
updatedAt: now,
|
|
3343
|
+
derivation: existing.derivation ?? {
|
|
3344
|
+
parentSlug: existing.slug,
|
|
3345
|
+
coefficients: {},
|
|
3346
|
+
hardOverrides: {}
|
|
3347
|
+
}
|
|
3348
|
+
};
|
|
3349
|
+
await registry.upsert(userEffort);
|
|
3350
|
+
return userEffort;
|
|
3351
|
+
}
|
|
3352
|
+
const updatedUserEffort = {
|
|
3353
|
+
...existing,
|
|
3354
|
+
aliases: updatedAliases,
|
|
3355
|
+
updatedAt: now
|
|
3356
|
+
};
|
|
3357
|
+
await registry.upsert(updatedUserEffort);
|
|
3358
|
+
return updatedUserEffort;
|
|
3359
|
+
}
|
|
3360
|
+
|
|
3071
3361
|
// src/runtime/contracts/IRuntimeOptions.ts
|
|
3072
3362
|
var DEFAULT_RUNTIME_OPTIONS = {
|
|
3073
3363
|
debugMode: false,
|
|
@@ -3622,9 +3912,7 @@ var ExecutionContext = class {
|
|
|
3622
3912
|
this._workList.push(initialAction);
|
|
3623
3913
|
while (this._workList.length > 0) {
|
|
3624
3914
|
if (this._iteration >= this._maxIterations) {
|
|
3625
|
-
|
|
3626
|
-
console.error(errorMsg);
|
|
3627
|
-
throw new Error(errorMsg);
|
|
3915
|
+
throw new Error(`[ExecutionContext] Max iterations reached (${this._maxIterations}). Aborting to prevent infinite loop.`);
|
|
3628
3916
|
}
|
|
3629
3917
|
const action = this._workList.shift();
|
|
3630
3918
|
this._iteration++;
|
|
@@ -3687,6 +3975,7 @@ var OutputEmitter = class {
|
|
|
3687
3975
|
return;
|
|
3688
3976
|
}
|
|
3689
3977
|
const processed = this._analyticsEngine ? this._analyticsEngine.run(output) : output;
|
|
3978
|
+
this._propagateSourceLine(processed);
|
|
3690
3979
|
this._outputStatements.push(processed);
|
|
3691
3980
|
for (const listener of this._outputListeners) {
|
|
3692
3981
|
try {
|
|
@@ -3945,11 +4234,25 @@ var OutputEmitter = class {
|
|
|
3945
4234
|
// =========================================================================
|
|
3946
4235
|
// Private helpers
|
|
3947
4236
|
// =========================================================================
|
|
4237
|
+
/** Options-built outputs carry only sourceStatementId — copy the source
|
|
4238
|
+
* statement's line/text/dialect so persisted logs stay joinable by line. */
|
|
4239
|
+
_propagateSourceLine(output) {
|
|
4240
|
+
if (output.sourceStatementId === void 0 || output.line !== void 0) return;
|
|
4241
|
+
const src = this._script?.getId(output.sourceStatementId);
|
|
4242
|
+
if (!src) return;
|
|
4243
|
+
output.line = src.line;
|
|
4244
|
+
output.text ??= src.text;
|
|
4245
|
+
output.dialect ??= src.dialect;
|
|
4246
|
+
}
|
|
3948
4247
|
};
|
|
3949
4248
|
|
|
3950
4249
|
// src/runtime/RuntimeObservers.ts
|
|
3951
4250
|
var RuntimeObservers = class {
|
|
3952
4251
|
_stackObservers = /* @__PURE__ */ new Set();
|
|
4252
|
+
_logger;
|
|
4253
|
+
constructor(logger) {
|
|
4254
|
+
this._logger = logger;
|
|
4255
|
+
}
|
|
3953
4256
|
/**
|
|
3954
4257
|
* Subscribe to stack snapshots. The collaborator does NOT emit an
|
|
3955
4258
|
* `'initial'` snapshot automatically — the calling adapter is
|
|
@@ -3975,7 +4278,7 @@ var RuntimeObservers = class {
|
|
|
3975
4278
|
try {
|
|
3976
4279
|
observer(snapshot);
|
|
3977
4280
|
} catch (err) {
|
|
3978
|
-
|
|
4281
|
+
this._logger?.error?.("[RuntimeObservers] Stack observer error:", err);
|
|
3979
4282
|
}
|
|
3980
4283
|
}
|
|
3981
4284
|
}
|
|
@@ -4020,6 +4323,10 @@ var RuntimeObservers = class {
|
|
|
4020
4323
|
|
|
4021
4324
|
// src/runtime/RuntimeLogger.ts
|
|
4022
4325
|
var RuntimeLoggerImpl = class {
|
|
4326
|
+
// Console is this logger's designated output sink; all writes funnel
|
|
4327
|
+
// through this single reference so the no-console rule is waived once.
|
|
4328
|
+
// eslint-disable-next-line no-console
|
|
4329
|
+
_console = console;
|
|
4023
4330
|
_enabled = false;
|
|
4024
4331
|
_history = [];
|
|
4025
4332
|
_maxHistory = 500;
|
|
@@ -4042,7 +4349,8 @@ var RuntimeLoggerImpl = class {
|
|
|
4042
4349
|
};
|
|
4043
4350
|
constructor() {
|
|
4044
4351
|
if (typeof window !== "undefined") {
|
|
4045
|
-
|
|
4352
|
+
const debugWindow = window;
|
|
4353
|
+
this._enabled = !!debugWindow.__WOD_DEBUG__;
|
|
4046
4354
|
}
|
|
4047
4355
|
}
|
|
4048
4356
|
get enabled() {
|
|
@@ -4050,11 +4358,11 @@ var RuntimeLoggerImpl = class {
|
|
|
4050
4358
|
}
|
|
4051
4359
|
enable() {
|
|
4052
4360
|
this._enabled = true;
|
|
4053
|
-
|
|
4361
|
+
this._console.log("%c[RT] \u{1F527} Runtime logging ENABLED", "color: #22c55e; font-weight: bold");
|
|
4054
4362
|
}
|
|
4055
4363
|
disable() {
|
|
4056
4364
|
this._enabled = false;
|
|
4057
|
-
|
|
4365
|
+
this._console.log("%c[RT] Runtime logging disabled", "color: #64748b");
|
|
4058
4366
|
}
|
|
4059
4367
|
getHistory() {
|
|
4060
4368
|
return [...this._history];
|
|
@@ -4072,18 +4380,18 @@ var RuntimeLoggerImpl = class {
|
|
|
4072
4380
|
if (!this._enabled) return;
|
|
4073
4381
|
const behaviors = this.getBehaviorNames(block);
|
|
4074
4382
|
const memoryTypes = block.getAllMemory?.().map((loc) => loc.tag) ?? [];
|
|
4075
|
-
|
|
4383
|
+
this._console.groupCollapsed(
|
|
4076
4384
|
`%c[RT] \u25B6 PUSH %c${block.label || block.blockType || "Block"}%c [${block.key.toString().slice(0, 8)}]`,
|
|
4077
4385
|
this.STYLES.push,
|
|
4078
4386
|
"color: inherit; font-weight: bold",
|
|
4079
4387
|
"color: #64748b; font-weight: normal"
|
|
4080
4388
|
);
|
|
4081
|
-
|
|
4082
|
-
if (parentKey)
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
if (memoryTypes.length > 0)
|
|
4086
|
-
|
|
4389
|
+
this._console.log("Key:", block.key.toString());
|
|
4390
|
+
if (parentKey) this._console.log("Parent:", parentKey);
|
|
4391
|
+
this._console.log("Source IDs:", block.sourceIds);
|
|
4392
|
+
this._console.log("Behaviors:", behaviors);
|
|
4393
|
+
if (memoryTypes.length > 0) this._console.log("Memory Types:", memoryTypes);
|
|
4394
|
+
this._console.groupEnd();
|
|
4087
4395
|
this.addToHistory("info", "push", `PUSH ${block.label}`, {
|
|
4088
4396
|
key: block.key.toString(),
|
|
4089
4397
|
parentKey,
|
|
@@ -4096,7 +4404,7 @@ var RuntimeLoggerImpl = class {
|
|
|
4096
4404
|
*/
|
|
4097
4405
|
logPop(block, reason) {
|
|
4098
4406
|
if (!this._enabled) return;
|
|
4099
|
-
|
|
4407
|
+
this._console.log(
|
|
4100
4408
|
`%c[RT] \u25C0 POP %c${block.label || block.blockType || "Block"}%c [${block.key.toString().slice(0, 8)}]${reason ? ` (${reason})` : ""}`,
|
|
4101
4409
|
this.STYLES.pop,
|
|
4102
4410
|
"color: inherit; font-weight: bold",
|
|
@@ -4116,15 +4424,15 @@ var RuntimeLoggerImpl = class {
|
|
|
4116
4424
|
if (actions.length === 0) {
|
|
4117
4425
|
return;
|
|
4118
4426
|
}
|
|
4119
|
-
|
|
4427
|
+
this._console.groupCollapsed(
|
|
4120
4428
|
`%c[RT] \u2192 NEXT %c${block.label || "Block"}%c \u2192 ${actions.length} action(s)`,
|
|
4121
4429
|
this.STYLES.next,
|
|
4122
4430
|
"color: inherit; font-weight: bold",
|
|
4123
4431
|
"color: #64748b; font-weight: normal"
|
|
4124
4432
|
);
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4433
|
+
this._console.log("Block:", block.key.toString());
|
|
4434
|
+
this._console.log("Actions:", actionNames);
|
|
4435
|
+
this._console.groupEnd();
|
|
4128
4436
|
this.addToHistory("info", "next", `NEXT ${block.label}`, {
|
|
4129
4437
|
key: block.key.toString(),
|
|
4130
4438
|
actions: actionNames
|
|
@@ -4137,15 +4445,15 @@ var RuntimeLoggerImpl = class {
|
|
|
4137
4445
|
if (!this._enabled) return;
|
|
4138
4446
|
if (actions.length === 0) return;
|
|
4139
4447
|
const actionNames = actions.map((a) => a.type || a.constructor?.name || "Action");
|
|
4140
|
-
|
|
4448
|
+
this._console.groupCollapsed(
|
|
4141
4449
|
`%c[RT] \u26A1 EVENT %c${event.name}%c \u2192 ${actions.length} action(s)`,
|
|
4142
4450
|
this.STYLES.event,
|
|
4143
4451
|
"color: inherit; font-weight: bold",
|
|
4144
4452
|
"color: #64748b; font-weight: normal"
|
|
4145
4453
|
);
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4454
|
+
this._console.log("Event Data:", event.data);
|
|
4455
|
+
this._console.log("Actions:", actionNames);
|
|
4456
|
+
this._console.groupEnd();
|
|
4149
4457
|
this.addToHistory("info", "event", `EVENT ${event.name}`, {
|
|
4150
4458
|
eventName: event.name,
|
|
4151
4459
|
eventData: event.data,
|
|
@@ -4161,7 +4469,7 @@ var RuntimeLoggerImpl = class {
|
|
|
4161
4469
|
if (typeof value === "object" && value !== null) {
|
|
4162
4470
|
displayValue = this.summarizeObject(value);
|
|
4163
4471
|
}
|
|
4164
|
-
|
|
4472
|
+
this._console.log(
|
|
4165
4473
|
`%c[RT] \u{1F4DD} MEMORY %c${memoryType}%c on [${blockKey.slice(0, 8)}]:`,
|
|
4166
4474
|
this.STYLES.memory,
|
|
4167
4475
|
"color: inherit; font-weight: bold",
|
|
@@ -4181,17 +4489,35 @@ var RuntimeLoggerImpl = class {
|
|
|
4181
4489
|
if (!this._enabled) return;
|
|
4182
4490
|
const indent = " ".repeat(depth);
|
|
4183
4491
|
const actionName = action.type || action.constructor?.name || "Action";
|
|
4184
|
-
|
|
4492
|
+
this._console.log(
|
|
4185
4493
|
`%c[RT] ${indent}\u2699 %c${actionName}`,
|
|
4186
4494
|
this.STYLES.action,
|
|
4187
4495
|
"color: inherit"
|
|
4188
4496
|
);
|
|
4189
4497
|
}
|
|
4498
|
+
/**
|
|
4499
|
+
* General-purpose message log for runtime consumers.
|
|
4500
|
+
* Gates on _enabled; writes to the console sink and history.
|
|
4501
|
+
*/
|
|
4502
|
+
logMessage(level, category, message, data) {
|
|
4503
|
+
if (!this._enabled) return;
|
|
4504
|
+
this._console.log(`%c[RT] ${category} %c${message}`, this.styleFor(level), "color: inherit");
|
|
4505
|
+
this.addToHistory(level, category, message, data);
|
|
4506
|
+
}
|
|
4507
|
+
/**
|
|
4508
|
+
* Always-on variant of `logMessage`. Use sparingly for errors/warnings that
|
|
4509
|
+
* must be visible even when debug logging is disabled.
|
|
4510
|
+
*/
|
|
4511
|
+
logAlways(level, category, message, data) {
|
|
4512
|
+
this._console.log(`%c[RT] ${category} %c${message}`, this.styleFor(level), "color: inherit");
|
|
4513
|
+
this.addToHistory(level, category, message, data);
|
|
4514
|
+
}
|
|
4190
4515
|
// ============================================================================
|
|
4191
4516
|
// Helpers
|
|
4192
4517
|
// ============================================================================
|
|
4193
4518
|
getBehaviorNames(block) {
|
|
4194
|
-
const
|
|
4519
|
+
const blockWithBehaviors = block;
|
|
4520
|
+
const behaviors = blockWithBehaviors.behaviors;
|
|
4195
4521
|
if (!behaviors || !Array.isArray(behaviors)) return [];
|
|
4196
4522
|
return behaviors.map((b) => b.constructor?.name || "Behavior");
|
|
4197
4523
|
}
|
|
@@ -4208,6 +4534,18 @@ var RuntimeLoggerImpl = class {
|
|
|
4208
4534
|
}
|
|
4209
4535
|
return summary;
|
|
4210
4536
|
}
|
|
4537
|
+
styleFor(level) {
|
|
4538
|
+
switch (level) {
|
|
4539
|
+
case "error":
|
|
4540
|
+
return "color: #ef4444; font-weight: bold";
|
|
4541
|
+
case "warn":
|
|
4542
|
+
return "color: #f59e0b; font-weight: bold";
|
|
4543
|
+
case "info":
|
|
4544
|
+
return "color: #3b82f6; font-weight: bold";
|
|
4545
|
+
default:
|
|
4546
|
+
return "color: #64748b";
|
|
4547
|
+
}
|
|
4548
|
+
}
|
|
4211
4549
|
addToHistory(level, category, message, data) {
|
|
4212
4550
|
this._history.push({
|
|
4213
4551
|
timestamp: /* @__PURE__ */ new Date(),
|
|
@@ -4312,6 +4650,7 @@ var ScriptRuntime = class {
|
|
|
4312
4650
|
constructor(script, compiler, dependencies, options = {}, now = wallClockNow) {
|
|
4313
4651
|
this.script = script;
|
|
4314
4652
|
this.options = { ...DEFAULT_RUNTIME_OPTIONS, ...options };
|
|
4653
|
+
this._observers = new RuntimeObservers(this.options.logger);
|
|
4315
4654
|
this.stack = dependencies.stack;
|
|
4316
4655
|
this.clock = dependencies.clock;
|
|
4317
4656
|
this.eventBus = dependencies.eventBus;
|
|
@@ -4352,7 +4691,7 @@ var ScriptRuntime = class {
|
|
|
4352
4691
|
_output = new OutputEmitter();
|
|
4353
4692
|
// Shared observer collaborator — owns the stack subscriber Set and the
|
|
4354
4693
|
// post-mount snapshot contract. See `RuntimeObservers` for the seam.
|
|
4355
|
-
_observers
|
|
4694
|
+
_observers;
|
|
4356
4695
|
// The current execution context for the "turn"
|
|
4357
4696
|
_activeContext = null;
|
|
4358
4697
|
_now;
|
|
@@ -4499,12 +4838,12 @@ var ScriptRuntime = class {
|
|
|
4499
4838
|
if (block) {
|
|
4500
4839
|
try {
|
|
4501
4840
|
block.unmount(this);
|
|
4502
|
-
} catch
|
|
4841
|
+
} catch {
|
|
4503
4842
|
}
|
|
4504
4843
|
this.stack.pop();
|
|
4505
4844
|
try {
|
|
4506
4845
|
block.dispose(this);
|
|
4507
|
-
} catch
|
|
4846
|
+
} catch {
|
|
4508
4847
|
}
|
|
4509
4848
|
} else {
|
|
4510
4849
|
this.stack.pop();
|
|
@@ -4571,16 +4910,18 @@ var ScriptRuntime = class {
|
|
|
4571
4910
|
}
|
|
4572
4911
|
};
|
|
4573
4912
|
var TypedMemoryReference = class {
|
|
4574
|
-
constructor(_memory, ownerId, type, visibility = "private") {
|
|
4913
|
+
constructor(_memory, ownerId, type, visibility = "private", _logger) {
|
|
4575
4914
|
this._memory = _memory;
|
|
4576
4915
|
this.ownerId = ownerId;
|
|
4577
4916
|
this.type = type;
|
|
4578
4917
|
this.visibility = visibility;
|
|
4918
|
+
this._logger = _logger;
|
|
4579
4919
|
}
|
|
4580
4920
|
_memory;
|
|
4581
4921
|
ownerId;
|
|
4582
4922
|
type;
|
|
4583
4923
|
visibility;
|
|
4924
|
+
_logger;
|
|
4584
4925
|
id = v7();
|
|
4585
4926
|
_subscriptions = [];
|
|
4586
4927
|
/**
|
|
@@ -4651,7 +4992,7 @@ var TypedMemoryReference = class {
|
|
|
4651
4992
|
try {
|
|
4652
4993
|
subscription.callback(newValue, oldValue);
|
|
4653
4994
|
} catch (error) {
|
|
4654
|
-
|
|
4995
|
+
this._logger?.error?.("Error in memory subscription callback:", error);
|
|
4655
4996
|
}
|
|
4656
4997
|
}
|
|
4657
4998
|
}
|
|
@@ -5073,7 +5414,7 @@ var BehaviorContext = class {
|
|
|
5073
5414
|
try {
|
|
5074
5415
|
unsubscribe();
|
|
5075
5416
|
} catch (err) {
|
|
5076
|
-
|
|
5417
|
+
this.runtime.options.logger?.error?.("[BehaviorContext] Unsubscribe error:", err);
|
|
5077
5418
|
}
|
|
5078
5419
|
}
|
|
5079
5420
|
this.subscriptions = [];
|
|
@@ -5349,7 +5690,7 @@ var RuntimeBlock = class {
|
|
|
5349
5690
|
*/
|
|
5350
5691
|
next(runtime, options) {
|
|
5351
5692
|
if (!this._behaviorContext) {
|
|
5352
|
-
|
|
5693
|
+
RuntimeLogger.logAlways("warn", "RuntimeBlock", "next() called before mount()");
|
|
5353
5694
|
return [];
|
|
5354
5695
|
}
|
|
5355
5696
|
const clock = options?.clock ?? this._behaviorContext.clock;
|
|
@@ -5399,7 +5740,7 @@ var RuntimeBlock = class {
|
|
|
5399
5740
|
try {
|
|
5400
5741
|
unsub();
|
|
5401
5742
|
} catch (err) {
|
|
5402
|
-
|
|
5743
|
+
RuntimeLogger.logAlways("error", "RuntimeBlock", "Error unsubscribing event handler", { error: err });
|
|
5403
5744
|
}
|
|
5404
5745
|
}
|
|
5405
5746
|
this._eventUnsubscribers = [];
|
|
@@ -5554,8 +5895,7 @@ var CompletionTimestampBehavior = class {
|
|
|
5554
5895
|
return [];
|
|
5555
5896
|
}
|
|
5556
5897
|
onNext(ctx) {
|
|
5557
|
-
|
|
5558
|
-
if (blockState && blockState.isComplete && !this.wasComplete && !this.completionTime) {
|
|
5898
|
+
if (ctx.block.isComplete && !this.wasComplete && !this.completionTime) {
|
|
5559
5899
|
this.completionTime = new Date(ctx.clock.currentDate);
|
|
5560
5900
|
this.wasComplete = true;
|
|
5561
5901
|
const completionFragment = {
|
|
@@ -5738,7 +6078,10 @@ var ClearChildrenAction = class {
|
|
|
5738
6078
|
iterations++;
|
|
5739
6079
|
}
|
|
5740
6080
|
if (iterations >= MAX_ITERATIONS) {
|
|
5741
|
-
|
|
6081
|
+
runtime.options.logger?.error?.(
|
|
6082
|
+
"[ClearChildrenAction] Max iterations reached, possible infinite loop",
|
|
6083
|
+
new Error(`Exceeded ${MAX_ITERATIONS} pop iterations for target ${this.targetBlockKey}`)
|
|
6084
|
+
);
|
|
5742
6085
|
}
|
|
5743
6086
|
if (runtime.stack.current?.key.toString() === this.targetBlockKey) {
|
|
5744
6087
|
actions.push(new NextAction(void 0, runtime.nowProvider));
|
|
@@ -5918,7 +6261,7 @@ var CountdownTimerBehavior = class {
|
|
|
5918
6261
|
if (childLoc?.metrics[0]) {
|
|
5919
6262
|
ctx.updateMemory("children:status", [{ ...childLoc.metrics[0], value: newChildStatus }]);
|
|
5920
6263
|
} else {
|
|
5921
|
-
ctx.pushMemory("children:status", [{ type:
|
|
6264
|
+
ctx.pushMemory("children:status", [{ type: "status", image: "", origin: "runtime", value: newChildStatus }]);
|
|
5922
6265
|
}
|
|
5923
6266
|
}
|
|
5924
6267
|
}
|
|
@@ -6322,6 +6665,7 @@ function resolveDominantOrigin(origins) {
|
|
|
6322
6665
|
}
|
|
6323
6666
|
|
|
6324
6667
|
// src/runtime/compiler/EffortEnrichmentPass.ts
|
|
6668
|
+
var logTrace = (message) => console.log(message);
|
|
6325
6669
|
function applyEffortEnrichment(block, options) {
|
|
6326
6670
|
const { resolver, overwrite = false, debug = false } = options;
|
|
6327
6671
|
tryEnrichBlock(block, resolver, overwrite, debug);
|
|
@@ -6333,14 +6677,14 @@ function tryEnrichBlock(block, resolver, overwrite, debug) {
|
|
|
6333
6677
|
}
|
|
6334
6678
|
const label = block.label;
|
|
6335
6679
|
if (!label) {
|
|
6336
|
-
if (debug)
|
|
6680
|
+
if (debug) logTrace(`[EffortEnrichment] Skipping block with no label: ${block.key}`);
|
|
6337
6681
|
return;
|
|
6338
6682
|
}
|
|
6339
6683
|
const existingEffortData = block.getAllMemory().find(
|
|
6340
6684
|
(loc) => loc.metrics.toArray().some((m) => m.type === EFFORT_DATA_METRIC_TYPE)
|
|
6341
6685
|
);
|
|
6342
6686
|
if (existingEffortData && !overwrite) {
|
|
6343
|
-
if (debug)
|
|
6687
|
+
if (debug) logTrace(`[EffortEnrichment] Skipping block already enriched: ${label}`);
|
|
6344
6688
|
return;
|
|
6345
6689
|
}
|
|
6346
6690
|
try {
|
|
@@ -6350,7 +6694,7 @@ function tryEnrichBlock(block, resolver, overwrite, debug) {
|
|
|
6350
6694
|
block.mergeHints(effortHints);
|
|
6351
6695
|
}
|
|
6352
6696
|
if (debug) {
|
|
6353
|
-
|
|
6697
|
+
logTrace(`[EffortEnrichment] Resolved effort: ${label} \u2192 ${resolved.label} (MET: ${resolved.met})`);
|
|
6354
6698
|
}
|
|
6355
6699
|
const effortDataMetric = {
|
|
6356
6700
|
type: EFFORT_DATA_METRIC_TYPE,
|
|
@@ -6406,7 +6750,7 @@ var CompileAndPushBlockAction = class {
|
|
|
6406
6750
|
}
|
|
6407
6751
|
return [new PushBlockAction(compiledBlock, this.options)];
|
|
6408
6752
|
} catch (error) {
|
|
6409
|
-
|
|
6753
|
+
runtime.options.logger?.error?.("CompileAndPushBlockAction: Compilation failed", error);
|
|
6410
6754
|
return [];
|
|
6411
6755
|
}
|
|
6412
6756
|
}
|
|
@@ -6625,7 +6969,7 @@ var ChildSelectionBehavior = class _ChildSelectionBehavior {
|
|
|
6625
6969
|
if (childLoc?.metrics[0]) {
|
|
6626
6970
|
ctx.updateMemory("children:status", [{ ...childLoc.metrics[0], value: status }]);
|
|
6627
6971
|
} else {
|
|
6628
|
-
ctx.pushMemory("children:status", [{ type:
|
|
6972
|
+
ctx.pushMemory("children:status", [{ type: "status", image: "", origin: "runtime", value: status }]);
|
|
6629
6973
|
}
|
|
6630
6974
|
}
|
|
6631
6975
|
/**
|
|
@@ -7173,7 +7517,7 @@ var WaitingToStartBlock = class _WaitingToStartBlock extends RuntimeBlock {
|
|
|
7173
7517
|
*/
|
|
7174
7518
|
static buildBehaviors() {
|
|
7175
7519
|
const behaviors = [];
|
|
7176
|
-
behaviors.push(new ReportOutputBehavior({ label: "Ready to Start" }));
|
|
7520
|
+
behaviors.push(new ReportOutputBehavior({ label: "Ready to Start", emitSegmentOnMount: true }));
|
|
7177
7521
|
behaviors.push(new LabelingBehavior({
|
|
7178
7522
|
mode: "clock",
|
|
7179
7523
|
label: "Ready to Start"
|
|
@@ -7609,7 +7953,7 @@ var JitCompiler = class {
|
|
|
7609
7953
|
const promotion = this._promotionResolver.resolvePromotions(parentBlock, runtime);
|
|
7610
7954
|
if (promotion.hasPromotions) {
|
|
7611
7955
|
const promotedFragments = promotion.promotedFragments;
|
|
7612
|
-
effectiveNodes =
|
|
7956
|
+
effectiveNodes = effectiveNodes.map((node) => {
|
|
7613
7957
|
const clone = Object.create(Object.getPrototypeOf(node));
|
|
7614
7958
|
Object.assign(clone, node);
|
|
7615
7959
|
clone.metrics = node.metrics.clone(node.id).add(...promotedFragments);
|
|
@@ -7626,8 +7970,7 @@ var JitCompiler = class {
|
|
|
7626
7970
|
}
|
|
7627
7971
|
try {
|
|
7628
7972
|
return builder.build();
|
|
7629
|
-
} catch
|
|
7630
|
-
console.error("Failed to build block from composition:", e);
|
|
7973
|
+
} catch {
|
|
7631
7974
|
return void 0;
|
|
7632
7975
|
}
|
|
7633
7976
|
}
|
|
@@ -11565,7 +11908,7 @@ var RuntimeAdapter = class {
|
|
|
11565
11908
|
blocks: stackBlocks,
|
|
11566
11909
|
activeIndex: activeIndex >= 0 ? activeIndex : 0,
|
|
11567
11910
|
depth: stackBlocks.length,
|
|
11568
|
-
rootBlockKey: stackBlocks.
|
|
11911
|
+
rootBlockKey: stackBlocks.at(-1)?.key
|
|
11569
11912
|
},
|
|
11570
11913
|
memory: {
|
|
11571
11914
|
entries: memoryEntries,
|
|
@@ -11592,7 +11935,7 @@ var RuntimeAdapter = class {
|
|
|
11592
11935
|
const blocks = runtime.stack.blocks;
|
|
11593
11936
|
return blocks.map((block, index) => {
|
|
11594
11937
|
const blockType = this.mapBlockType(block);
|
|
11595
|
-
const isActive = index ===
|
|
11938
|
+
const isActive = index === 0;
|
|
11596
11939
|
const status = this.determineBlockStatus(isActive);
|
|
11597
11940
|
const metrics = this.extractBlockFragments(runtime, block);
|
|
11598
11941
|
const displayLocs = block.getMemoryByTag("metric:display");
|
|
@@ -11614,7 +11957,7 @@ var RuntimeAdapter = class {
|
|
|
11614
11957
|
metrics,
|
|
11615
11958
|
metricGroups,
|
|
11616
11959
|
sourceIds: block.sourceIds,
|
|
11617
|
-
lineNumber: block.sourceIds.length > 0 ? block.sourceIds[0] : void 0,
|
|
11960
|
+
lineNumber: block.sourceIds.length > 0 ? runtime.script.getId(block.sourceIds[0])?.line : void 0,
|
|
11618
11961
|
metadata: {
|
|
11619
11962
|
mountTime: void 0,
|
|
11620
11963
|
executionTime: void 0,
|
|
@@ -11641,9 +11984,8 @@ var RuntimeAdapter = class {
|
|
|
11641
11984
|
const ownerLabelMap = /* @__PURE__ */ new Map();
|
|
11642
11985
|
runtime.stack.blocks.forEach((block) => {
|
|
11643
11986
|
const key = block.key.toString();
|
|
11644
|
-
|
|
11645
|
-
|
|
11646
|
-
}
|
|
11987
|
+
const line = block.sourceIds.length > 0 ? runtime.script.getId(block.sourceIds[0])?.line : void 0;
|
|
11988
|
+
if (line !== void 0) ownerLineMap.set(key, line);
|
|
11647
11989
|
ownerLabelMap.set(key, block.label);
|
|
11648
11990
|
});
|
|
11649
11991
|
for (const block of runtime.stack.blocks) {
|
|
@@ -11781,8 +12123,7 @@ var RuntimeAdapter = class {
|
|
|
11781
12123
|
return "pending";
|
|
11782
12124
|
}
|
|
11783
12125
|
findParentKey(blocks, currentIndex) {
|
|
11784
|
-
|
|
11785
|
-
return blocks[currentIndex - 1].key.toString();
|
|
12126
|
+
return blocks[currentIndex + 1]?.key.toString();
|
|
11786
12127
|
}
|
|
11787
12128
|
findChildrenKeys(_blocks, _parentKey) {
|
|
11788
12129
|
return [];
|
|
@@ -12384,6 +12725,8 @@ function evaluateNode(node, context, row) {
|
|
|
12384
12725
|
return right === 0 ? void 0 : left / right;
|
|
12385
12726
|
case "^":
|
|
12386
12727
|
return Math.pow(left, right);
|
|
12728
|
+
default:
|
|
12729
|
+
return void 0;
|
|
12387
12730
|
}
|
|
12388
12731
|
}
|
|
12389
12732
|
case "call":
|
|
@@ -12724,8 +13067,6 @@ function compileLineForm(src, defaultScope) {
|
|
|
12724
13067
|
const sc = SCOPE_RE.exec(line);
|
|
12725
13068
|
if (sc && /^(on\s|when\s|:)/.test(line.slice(sc[0].length).trim())) {
|
|
12726
13069
|
scope = sc[1];
|
|
12727
|
-
fences = void 0;
|
|
12728
|
-
defWhen = void 0;
|
|
12729
13070
|
const header = parseSectionHeader(line.slice(sc[0].length).trim());
|
|
12730
13071
|
fences = header.fences;
|
|
12731
13072
|
defWhen = header.when;
|
|
@@ -13122,7 +13463,7 @@ function computeWorkloadRollups(loads, throughDay) {
|
|
|
13122
13463
|
return rollups;
|
|
13123
13464
|
}
|
|
13124
13465
|
function toStoredOutputStatement(output) {
|
|
13125
|
-
const metrics = output.metrics instanceof MetricContainer ? output.metrics.toArray() : Array.isArray(output.metrics) ? output.metrics : output.metrics
|
|
13466
|
+
const metrics = output.metrics instanceof MetricContainer ? output.metrics.toArray() : Array.isArray(output.metrics) ? output.metrics : typeof output.metrics.toArray === "function" ? output.metrics.toArray() : [];
|
|
13126
13467
|
const hints = getHints(output);
|
|
13127
13468
|
return {
|
|
13128
13469
|
id: output.id,
|
|
@@ -13141,16 +13482,195 @@ function toStoredOutputStatement(output) {
|
|
|
13141
13482
|
};
|
|
13142
13483
|
}
|
|
13143
13484
|
|
|
13144
|
-
// src/
|
|
13145
|
-
var
|
|
13146
|
-
var
|
|
13147
|
-
|
|
13148
|
-
|
|
13149
|
-
|
|
13150
|
-
|
|
13151
|
-
|
|
13152
|
-
|
|
13485
|
+
// src/parser-fixture/metricLine.ts
|
|
13486
|
+
var TAIL_TOKEN_RE = /[\w-]+:(?:"(?:[^"\\]|\\.)*"|[^ ]+)/g;
|
|
13487
|
+
var FixtureSyntaxError = class extends Error {
|
|
13488
|
+
constructor(message) {
|
|
13489
|
+
super(message);
|
|
13490
|
+
this.name = "FixtureSyntaxError";
|
|
13491
|
+
}
|
|
13492
|
+
};
|
|
13493
|
+
function canonicalizeType(token) {
|
|
13494
|
+
const kebab = token.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
|
|
13495
|
+
return kebab;
|
|
13496
|
+
}
|
|
13497
|
+
var TIME_RE = /^\d{1,2}(:\d{2}){1,2}$/;
|
|
13498
|
+
var NUMBER_RE = /^\d+(\.\d+)?$/;
|
|
13499
|
+
var TAIL_RE = /^[\w-]+:([^ ]+)$/;
|
|
13500
|
+
function parseTimeToMs(token) {
|
|
13501
|
+
const parts = token.split(":").map(Number);
|
|
13502
|
+
return parts.reduce((acc, p) => acc * 60 + p, 0) * 1e3;
|
|
13503
|
+
}
|
|
13504
|
+
function parseTails(sequence, at) {
|
|
13505
|
+
const fields = {};
|
|
13506
|
+
TAIL_TOKEN_RE.lastIndex = 0;
|
|
13507
|
+
let cursor = 0;
|
|
13508
|
+
let m;
|
|
13509
|
+
while ((m = TAIL_TOKEN_RE.exec(sequence)) !== null) {
|
|
13510
|
+
if (sequence.slice(cursor, m.index).trim() !== "") {
|
|
13511
|
+
at(`invalid object tail ${JSON.stringify(sequence.slice(cursor, m.index).trim())}`);
|
|
13512
|
+
}
|
|
13513
|
+
const sep = m[0].indexOf(":");
|
|
13514
|
+
const k = m[0].slice(0, sep);
|
|
13515
|
+
const raw = m[0].slice(sep + 1);
|
|
13516
|
+
fields[k] = raw.startsWith('"') ? JSON.parse(raw) : NUMBER_RE.test(raw) ? Number(raw) : raw;
|
|
13517
|
+
cursor = m.index + m[0].length;
|
|
13518
|
+
}
|
|
13519
|
+
if (sequence.slice(cursor).trim() !== "") {
|
|
13520
|
+
at(`invalid object tail ${JSON.stringify(sequence.slice(cursor).trim())}`);
|
|
13521
|
+
}
|
|
13522
|
+
return fields;
|
|
13523
|
+
}
|
|
13524
|
+
function parseMetricLine(line, file, lineNo) {
|
|
13525
|
+
const src = line.trim();
|
|
13526
|
+
function at(detail) {
|
|
13527
|
+
throw new FixtureSyntaxError(`${file} [line ${lineNo}]: ${detail}`);
|
|
13528
|
+
}
|
|
13529
|
+
if (!line.startsWith("- ")) {
|
|
13530
|
+
at(`metric line must start with "- " (got: ${JSON.stringify(line)})`);
|
|
13531
|
+
}
|
|
13532
|
+
const body = line.slice(2).trim();
|
|
13533
|
+
const tokens = body.split(/\s+/).filter(Boolean);
|
|
13534
|
+
if (tokens.length === 0) {
|
|
13535
|
+
at("metric line is empty");
|
|
13536
|
+
}
|
|
13537
|
+
const [typeToken, ...rest] = tokens;
|
|
13538
|
+
const type = canonicalizeType(typeToken);
|
|
13539
|
+
if (rest.length === 0) {
|
|
13540
|
+
at(`metric "${typeToken}" is missing a value`);
|
|
13541
|
+
}
|
|
13542
|
+
let origin;
|
|
13543
|
+
const lastToken = rest[rest.length - 1];
|
|
13544
|
+
const beforeLast = rest.slice(0, -1).join(" ");
|
|
13545
|
+
const quotesBeforeLast = (beforeLast.match(/"/g) ?? []).length;
|
|
13546
|
+
if (lastToken.startsWith("@") && quotesBeforeLast % 2 === 0) {
|
|
13547
|
+
origin = lastToken.slice(1);
|
|
13548
|
+
rest.pop();
|
|
13549
|
+
if (rest.length === 0) {
|
|
13550
|
+
at(`metric "${typeToken}" is missing a value before @${origin}`);
|
|
13551
|
+
}
|
|
13552
|
+
}
|
|
13553
|
+
const first = rest[0];
|
|
13554
|
+
if (first.startsWith('"')) {
|
|
13555
|
+
const joined = rest.join(" ");
|
|
13556
|
+
const m = joined.match(/^"(?:[^"\\]|\\.)*"/);
|
|
13557
|
+
if (!m) {
|
|
13558
|
+
at(`unterminated quoted string in: ${joined}`);
|
|
13559
|
+
}
|
|
13560
|
+
let value;
|
|
13561
|
+
try {
|
|
13562
|
+
value = JSON.parse(m[0]);
|
|
13563
|
+
} catch {
|
|
13564
|
+
at(`invalid quoted string ${m[0]} (JSON escapes only)`);
|
|
13565
|
+
}
|
|
13566
|
+
const tailPart = joined.slice(m[0].length).trim();
|
|
13567
|
+
if (tailPart) {
|
|
13568
|
+
at(`quoted string cannot combine with object tails (${tailPart}) \u2014 assert fields on the object-valued form instead`);
|
|
13569
|
+
}
|
|
13570
|
+
return { type, kind: "string", value, source: src, ...origin ? { origin } : {} };
|
|
13571
|
+
}
|
|
13572
|
+
if (TIME_RE.test(first)) {
|
|
13573
|
+
if (rest.length > 1) at(`unexpected tokens after time literal: ${rest.slice(1).join(" ")}`);
|
|
13574
|
+
return { type, kind: "number", value: parseTimeToMs(first), source: src, ...origin ? { origin } : {} };
|
|
13575
|
+
}
|
|
13576
|
+
if (NUMBER_RE.test(first)) {
|
|
13577
|
+
if (rest.length === 1) {
|
|
13578
|
+
return { type, kind: "number", value: Number(first), source: src, ...origin ? { origin } : {} };
|
|
13579
|
+
}
|
|
13580
|
+
const second = rest[1];
|
|
13581
|
+
if (!TAIL_RE.test(second)) {
|
|
13582
|
+
if (rest.length > 2) at(`unexpected tokens after amount+unit: ${rest.slice(2).join(" ")}`);
|
|
13583
|
+
return { type, kind: "amountUnit", amount: Number(first), unit: second, source: src, ...origin ? { origin } : {} };
|
|
13584
|
+
}
|
|
13585
|
+
at(`number literal followed by object tail is ambiguous: ${rest.join(" ")}`);
|
|
13586
|
+
}
|
|
13587
|
+
if (TAIL_RE.test(first)) {
|
|
13588
|
+
return { type, kind: "object", fields: parseTails(rest.join(" "), at), source: src, ...origin ? { origin } : {} };
|
|
13589
|
+
}
|
|
13590
|
+
if (first === "?" && rest.length === 1) {
|
|
13591
|
+
return { type, kind: "undefined", source: src, ...origin ? { origin } : {} };
|
|
13592
|
+
}
|
|
13593
|
+
if (rest.length === 1) {
|
|
13594
|
+
return { type, kind: "string", value: first, source: src, ...origin ? { origin } : {} };
|
|
13595
|
+
}
|
|
13596
|
+
at(`unquoted string value with spaces \u2014 use quotes: ${rest.join(" ")}`);
|
|
13597
|
+
}
|
|
13598
|
+
|
|
13599
|
+
// src/parser-fixture/compare.ts
|
|
13600
|
+
function renderMetric(m) {
|
|
13601
|
+
const type = canonicalizeType(String(m.type));
|
|
13602
|
+
const cap = type.charAt(0).toUpperCase() + type.slice(1);
|
|
13603
|
+
const origin = m.origin ? ` @${m.origin}` : "";
|
|
13604
|
+
if (m.value !== null && typeof m.value === "object") {
|
|
13605
|
+
const inner = Object.entries(m.value).map(([k, v]) => `${k}:${String(v)}`).join(" ");
|
|
13606
|
+
return `${cap} ${inner}${origin}`;
|
|
13607
|
+
}
|
|
13608
|
+
if (typeof m.value === "string") {
|
|
13609
|
+
return m.value.includes(" ") ? `${cap} "${m.value}"${origin}` : `${cap} ${m.value}${origin}`;
|
|
13610
|
+
}
|
|
13611
|
+
return `${cap} ${String(m.value)}${origin}`;
|
|
13612
|
+
}
|
|
13613
|
+
function literalMatches(line, metric) {
|
|
13614
|
+
const value = metric.value;
|
|
13615
|
+
switch (line.kind) {
|
|
13616
|
+
case "number":
|
|
13617
|
+
return typeof value === "number" && value === line.value;
|
|
13618
|
+
case "undefined":
|
|
13619
|
+
return metric.value === void 0;
|
|
13620
|
+
case "string":
|
|
13621
|
+
return value === line.value;
|
|
13622
|
+
case "amountUnit": {
|
|
13623
|
+
if (value === null || typeof value !== "object") return false;
|
|
13624
|
+
const v = value;
|
|
13625
|
+
return v.amount === line.amount && v.unit === line.unit && metric.unit === line.unit;
|
|
13626
|
+
}
|
|
13627
|
+
case "object": {
|
|
13628
|
+
if (value === null || typeof value !== "object") return false;
|
|
13629
|
+
const obj = value;
|
|
13630
|
+
return Object.entries(line.fields ?? {}).every(([k, expected]) => {
|
|
13631
|
+
const actual = obj[k];
|
|
13632
|
+
if (typeof actual === "number" && typeof expected === "number") {
|
|
13633
|
+
return actual === expected;
|
|
13634
|
+
}
|
|
13635
|
+
return String(actual) === String(expected);
|
|
13636
|
+
});
|
|
13637
|
+
}
|
|
13638
|
+
}
|
|
13639
|
+
}
|
|
13640
|
+
function lineMatches(line, metric) {
|
|
13641
|
+
if (canonicalizeType(String(metric.type)) !== line.type) return false;
|
|
13642
|
+
if (line.origin !== void 0 && metric.origin !== line.origin) return false;
|
|
13643
|
+
return literalMatches(line, metric);
|
|
13644
|
+
}
|
|
13645
|
+
function diffStatement(expected, actual) {
|
|
13646
|
+
const remaining = [...actual];
|
|
13647
|
+
const matched = [];
|
|
13648
|
+
const missingExpected = [];
|
|
13649
|
+
for (const line of expected) {
|
|
13650
|
+
const hit = remaining.findIndex((m) => lineMatches(line, m));
|
|
13651
|
+
if (hit === -1) {
|
|
13652
|
+
missingExpected.push(line);
|
|
13653
|
+
} else {
|
|
13654
|
+
matched.push({ expected: line, actual: remaining.splice(hit, 1)[0] });
|
|
13655
|
+
}
|
|
13656
|
+
}
|
|
13657
|
+
return { matched, missingExpected, extraActual: remaining };
|
|
13658
|
+
}
|
|
13659
|
+
function compareStatement(expectations, actual, mode) {
|
|
13660
|
+
const { missingExpected, extraActual } = diffStatement(expectations, actual);
|
|
13661
|
+
const diffs = [];
|
|
13662
|
+
const present = actual.map(renderMetric).join("; ") || "nothing";
|
|
13663
|
+
for (const line of missingExpected) {
|
|
13664
|
+
diffs.push(`unmatched expectation ${line.source} \u2014 statement carries: ${present}`);
|
|
13665
|
+
}
|
|
13666
|
+
if (mode === "closed" && missingExpected.length === 0) {
|
|
13667
|
+
for (const m of extraActual) {
|
|
13668
|
+
diffs.push(`unexpected metric ${renderMetric(m)} \u2014 not in the Expected block`);
|
|
13669
|
+
}
|
|
13670
|
+
}
|
|
13671
|
+
return diffs;
|
|
13672
|
+
}
|
|
13153
13673
|
|
|
13154
|
-
export { ABSENT, AGGREGATE_BUILTINS, AUTHORITATIVE_CASTS, AbortSessionAction, AmrapLogicStrategy, AnalyticsEngine, AnalyticsTransformer,
|
|
13674
|
+
export { ABSENT, AGGREGATE_BUILTINS, AUTHORITATIVE_CASTS, AbortSessionAction, AmrapLogicStrategy, AnalyticsEngine, AnalyticsTransformer, BUILTIN_CALCS, BUNDLED_EFFORT_COUNT, BehaviorContext, BlockBuilder, BlockContext, ButtonBehavior, CONSUMED_HINTS, CONSUMED_HINT_KEYS, CONTEXT_ATOMS, CalcEngine, CalcEvalError, CalcParseError, CalcRegistrationError, CalcUnitError, CalculateBlockProcessor, CalculationRegistry, CardioDialect, ChildSelectionBehavior, ChildrenStrategy, ChoiceGroupMetric, ClearChildrenAction, ClimbDialect, ClimbMetricType, CompileAndPushBlockAction, CompletionTimestampBehavior, CompositeEffortRegistry, CountdownTimerBehavior, CountupTimerBehavior, CrossFitDialect, DAY, DEFAULT_RESOLVER_OPTIONS, DEFAULT_RUNTIME_OPTIONS, DEFAULT_UNRESOLVED_EFFORT_MET, DIM_COUNT, DIM_ENERGY, DIM_LENGTH, DIM_MASS, DIM_TIME, DIM_ZERO, DISCIPLINE_FACTORS, DialectStack, EFFORT_DATA_METRIC_TYPE, EFFORT_DISCIPLINES, EFFORT_REGISTRY_ORIGINS, EffortBlock, EffortFallbackStrategy, EffortResolver, EmitEventAction, EmitSystemOutputAction, ErrorAction, EventBus, ExecutionContext, ExitBehavior, FixtureSyntaxError, GenericGroupStrategy, GenericLoopStrategy, GenericTimerStrategy, HabitsDialect, INTENSITY_TIERS, InMemoryEffortRegistry, IntervalLogicStrategy, JitCompiler, LabelingBehavior, LocalEventProvider, LocalRuntimeSubscription, LookupRegistry, MdTimerRuntime, MemoryLocation, MemoryTypeEnum, MetricPromotionBehavior, NAMED_COMPOUNDS, NextAction, NextEvent, NextEventHandler, OutputEmitter, PREDEFINED_SOUNDS, PRODUCTION_STRATEGIES, PlaySoundAction, PopBlockAction, PushBlockAction, PushRestBlockAction, REST_EXCLUSION, RPE_LABELS, RegisterEventHandlerAction, Registry, ReportOutputBehavior, ReportOutputStrategy, RestBlock, RoundsMetric, RuntimeAdapter, RuntimeBlock, RuntimeBuilder, RuntimeClock, RuntimeFactory, RuntimeLogger, RuntimeMemory, RuntimeObservers, RuntimeStack, STANDARD_UNITS, STORE_CALCS, STREAM_ATOMS, ScriptRuntime, SessionRootBlock, SessionRootStrategy, SnapshotClock, SoundCueBehavior, SoundStrategy, SpanTrackingBehavior, StandardAnalyticsProfile, StartSessionAction, StartWorkoutAction, SubscriptionManager, ThrowError, ThrowErrorAction, TimeSpan, TwoPassEffortResolutionProcess, TypedMemoryReference, UNITS, UnitRegistry, UnitSet, UnitsDialect, UnregisterEventHandlerAction, UpdateNextPreviewAction, VISIBILITY_ICONS, VISIBILITY_LABELS, WaitingToStartBlock, WaitingToStartInjectorBehavior, WhiteboardScript, WodDialect, YogaDialect, addAliasToEffort, addDim, buildStaticLookups, buildTooltip, bundledEfforts, calculateElapsed, canonicalizeType, checkCalcLine, classifyStatements, closeCurrentSpan, collapseUnresolvedChoices, commonFixtureSet, compareStatement, compileLineForm, composeDivUnit, composeMulUnit, compoundName, computeColumnLabel, computeLabel, computeWorkloadRollups, convertScalar, createAnalyticsEngineForBlock, createCalcEngine, createCalcStack, createCompiler, createDialectStack, createDisciplinesTable, createEffortTable, createLineLocator, createPolicy as createMetricPresentationPolicy, createMockClock, createParser, createProfileTable, createRpeLabelsTable, dailySessionLoads, dayBucket, dialectRegistry, dialectStack, diffStatement, dimEquals, disciplineFactorFor, evaluate, evaluateCalculateDefinitions, extractEffortData, extractMetrics, extractStatements, extractStatementsRaw, extractSyntaxFacts, filterTagsByVisibility, findBestFuzzyMatch, findUnresolvedChoices, fixtureBackSquat, fixtureBurpee, fixturePlank, fixtureRowing, fixtureRunning, fixtureUserCustom, fixtureUserOverride, formatDim, formatDuration, metricsToLabel as fragmentsToLabel, fullFixtureSet, fuseUnits, fuseUnitsInMetrics, getAnalyticsFromLogs, getAnalyticsFromRuntime, getHints, getMetricVisibility, getUnit, hasHint, hintMetric, hintsToContainer, inferDim, isCastSubscription, isChoiceResolved, isDimensionless, isEffortDiscipline, isFragmentTag, isTimeLikeMetric, isWithinThreshold, levenshteinDistance, metricPresentation, mutateTimerSpans, normalizeForFuzzy, num, openSpan, outputNodeId, outputNodeIds, parseCalcLine, parseCalculateBlock, parseExpression, parseMetricLine, parseScript, printCalculation, readTimer, realtimeProcessorRegistry, renderMetric, resolveDominantOrigin, sharedParser, startSpan, str, strategyRegistry, subDim, summaryProcessorRegistry, toStoredOutputStatement, truthy, validateOutputUnit, parser as whiteboardParser, whiteboardScript, whiteboardScriptLanguage, writeChoiceSelection };
|
|
13155
13675
|
//# sourceMappingURL=index.mjs.map
|
|
13156
13676
|
//# sourceMappingURL=index.mjs.map
|