@aigne/ash 0.0.2-beta.3 → 0.0.2-beta.4
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/compiler.cjs +16 -8
- package/dist/compiler.d.cts.map +1 -1
- package/dist/compiler.d.mts.map +1 -1
- package/dist/compiler.mjs +16 -8
- package/dist/compiler.mjs.map +1 -1
- package/dist/parser.cjs +32 -2
- package/dist/parser.d.cts +7 -0
- package/dist/parser.d.cts.map +1 -1
- package/dist/parser.d.mts +7 -0
- package/dist/parser.d.mts.map +1 -1
- package/dist/parser.mjs +32 -2
- package/dist/parser.mjs.map +1 -1
- package/package.json +1 -1
package/dist/compiler.cjs
CHANGED
|
@@ -548,12 +548,13 @@ var AshCompiler = class {
|
|
|
548
548
|
}
|
|
549
549
|
return mapped;
|
|
550
550
|
};
|
|
551
|
+
const initialRec = initialStream?.[0] ?? void 0;
|
|
551
552
|
if (stage.exprMappings) return stream.map((item) => {
|
|
552
553
|
const result = {};
|
|
553
|
-
for (const [key, expr] of Object.entries(stage.exprMappings)) result[key] = this.evaluateExpression(expr, item, variables);
|
|
554
|
+
for (const [key, expr] of Object.entries(stage.exprMappings)) result[key] = this.evaluateExpression(expr, item, variables, initialRec);
|
|
554
555
|
return preserveSystemFields(item, result);
|
|
555
556
|
});
|
|
556
|
-
if (stage.expression) return stream.map((item) => this.evaluateExpression(stage.expression, item, variables));
|
|
557
|
+
if (stage.expression) return stream.map((item) => this.evaluateExpression(stage.expression, item, variables, initialRec));
|
|
557
558
|
if (stage.mappings) return stream.map((item) => {
|
|
558
559
|
const result = {};
|
|
559
560
|
for (const [key, field] of Object.entries(stage.mappings)) result[key] = this.resolveField(item, field);
|
|
@@ -800,16 +801,23 @@ var AshCompiler = class {
|
|
|
800
801
|
}
|
|
801
802
|
return current;
|
|
802
803
|
}
|
|
803
|
-
evaluateExpression(expr, item, variables) {
|
|
804
|
+
evaluateExpression(expr, item, variables, fallbackItem) {
|
|
804
805
|
switch (expr.kind) {
|
|
805
806
|
case "literal": return expr.value;
|
|
806
|
-
case "field_access":
|
|
807
|
+
case "field_access": {
|
|
808
|
+
const value = this.resolveField(item, expr.path);
|
|
809
|
+
if (value === void 0 && fallbackItem != null) {
|
|
810
|
+
const topField = expr.path.split(".")[0];
|
|
811
|
+
if (typeof item !== "object" || item === null || !Object.hasOwn(item, topField)) return this.resolveField(fallbackItem, expr.path);
|
|
812
|
+
}
|
|
813
|
+
return value;
|
|
814
|
+
}
|
|
807
815
|
case "var_ref":
|
|
808
816
|
if (!variables.has(expr.name)) throw new Error(`Undefined variable: $${expr.name}`);
|
|
809
817
|
return variables.get(expr.name);
|
|
810
818
|
case "binary": {
|
|
811
|
-
const left = this.evaluateExpression(expr.left, item, variables);
|
|
812
|
-
const right = this.evaluateExpression(expr.right, item, variables);
|
|
819
|
+
const left = this.evaluateExpression(expr.left, item, variables, fallbackItem);
|
|
820
|
+
const right = this.evaluateExpression(expr.right, item, variables, fallbackItem);
|
|
813
821
|
switch (expr.op) {
|
|
814
822
|
case "+":
|
|
815
823
|
if (typeof left === "string" || typeof right === "string") return String(left ?? "") + String(right ?? "");
|
|
@@ -820,10 +828,10 @@ var AshCompiler = class {
|
|
|
820
828
|
default: throw new Error(`Unknown operator: ${expr.op}`);
|
|
821
829
|
}
|
|
822
830
|
}
|
|
823
|
-
case "array_literal": return expr.elements.map((el) => this.evaluateExpression(el, item, variables));
|
|
831
|
+
case "array_literal": return expr.elements.map((el) => this.evaluateExpression(el, item, variables, fallbackItem));
|
|
824
832
|
case "object_literal": {
|
|
825
833
|
const obj = {};
|
|
826
|
-
for (const [key, valExpr] of Object.entries(expr.properties)) obj[key] = this.evaluateExpression(valExpr, item, variables);
|
|
834
|
+
for (const [key, valExpr] of Object.entries(expr.properties)) obj[key] = this.evaluateExpression(valExpr, item, variables, fallbackItem);
|
|
827
835
|
return obj;
|
|
828
836
|
}
|
|
829
837
|
default: throw new Error(`Unknown expression kind: ${expr.kind}`);
|
package/dist/compiler.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compiler.d.cts","names":[],"sources":["../src/compiler.ts"],"mappings":";;;;UAOiB,aAAA;EACf,OAAA,GAAU,eAAA;EACV,WAAA,EAAa,aAAA;EACb,UAAA;AAAA;AAAA,iBAuBc,aAAA,CAAc,MAAA,WAAiB,aAAA;AAAA,UAgQ9B,WAAA;EACf,IAAA;EACA,OAAA;EACA,OAAA,GAAU,UAAA;AAAA;AAAA,UAGK,aAAA;EACf,MAAA,CAAO,KAAA,EAAO,WAAA;AAAA;AAAA,UAGC,UAAA;EACf,KAAA,EAAO,cAAA;EACP,IAAA,EAAM,GAAA;EACN,MAAA,EAAQ,SAAA;EACR,MAAA,GAAS,aAAA;AAAA;AAAA,UAGM,cAAA;EACf,IAAA,CAAK,IAAA,UAAc,KAAA,GAAQ,cAAA,eAA6B,OAAA;EACxD,KAAA,CAAM,IAAA,UAAc,IAAA;EACpB,OAAA,CAAQ,KAAA,UAAe,IAAA;EACvB,IAAA,EAAM,IAAA,UAAc,KAAA,aAAkB,MAAA,GAAS,MAAA,oBAA0B,OAAA;EACzE,KAAA,EAAO,MAAA,oBAA0B,OAAA;AAAA;AAAA,UAGlB,UAAA;EACf,SAAA;EACA,MAAA;EACA,OAAA;EACA,SAAA;EACA,OAAA;EACA,UAAA;AAAA;AAAA,UAGe,SAAA;EACf,GAAA,CAAI,KAAA,UAAe,MAAA,UAAgB,MAAA;EACnC,IAAA,EAAM,KAAA,uCAA4C,OAAA,UAAiB,OAAA,GAAU,UAAA;AAAA;AAAA,UAG9D,SAAA;EACf,MAAA;EACA,WAAA;EACA,MAAA;AAAA;AAAA,UAGe,YAAA;EACf,IAAA;EACA,KAAA;EACA,UAAA;EACA,WAAA;EACA,UAAA;EACA,KAAA;AAAA;AAAA,UAGe,SAAA,SAAkB,SAAA;EACjC,OAAA;EACA,eAAA;EACA,MAAA,EAAQ,YAAA;AAAA;AAAA,UAGO,aAAA;EACf,IAAA,EAAM,SAAA;EACN,eAAA;AAAA;AAAA,UAGe,WAAA;EACf,IAAA;EACA,IAAA;EACA,OAAA,GAAU,kBAAA;EACV,OAAA,CAAQ,GAAA,EAAK,UAAA,EAAY,aAAA,eAA4B,OAAA,CAAQ,SAAA;AAAA;AAAA,UAG9C,cAAA;EACf,IAAA;EACA,OAAA;EACA,OAAA,CAAQ,GAAA,EAAK,UAAA,GAAa,OAAA;AAAA;AAAA,KAGhB,YAAA,GAAe,WAAA,GAAc,cAAA;AAAA,UAExB,eAAA;EACf,IAAA,EAAM,WAAA;EACN,KAAA,EAAO,YAAA;EACP,MAAA,EAAQ,GAAA,SAAY,WAAA;EACpB,MAAA,EAAQ,GAAA;EACR,YAAA,GAAe,GAAA;AAAA;AAAA,cAqCJ,WAAA;EAAA,QACH,eAAA;EAAA,QACA,kBAAA;EAAA,QACA,OAAA;EAER,OAAA,CAAQ,GAAA,EAAK,OAAA,GAAU,eAAA;EAAA,QAmDf,gBAAA;EAAA,QAOA,qBAAA;EAAA,QAWA,UAAA;EAAA,QAqOM,YAAA;EAAA,
|
|
1
|
+
{"version":3,"file":"compiler.d.cts","names":[],"sources":["../src/compiler.ts"],"mappings":";;;;UAOiB,aAAA;EACf,OAAA,GAAU,eAAA;EACV,WAAA,EAAa,aAAA;EACb,UAAA;AAAA;AAAA,iBAuBc,aAAA,CAAc,MAAA,WAAiB,aAAA;AAAA,UAgQ9B,WAAA;EACf,IAAA;EACA,OAAA;EACA,OAAA,GAAU,UAAA;AAAA;AAAA,UAGK,aAAA;EACf,MAAA,CAAO,KAAA,EAAO,WAAA;AAAA;AAAA,UAGC,UAAA;EACf,KAAA,EAAO,cAAA;EACP,IAAA,EAAM,GAAA;EACN,MAAA,EAAQ,SAAA;EACR,MAAA,GAAS,aAAA;AAAA;AAAA,UAGM,cAAA;EACf,IAAA,CAAK,IAAA,UAAc,KAAA,GAAQ,cAAA,eAA6B,OAAA;EACxD,KAAA,CAAM,IAAA,UAAc,IAAA;EACpB,OAAA,CAAQ,KAAA,UAAe,IAAA;EACvB,IAAA,EAAM,IAAA,UAAc,KAAA,aAAkB,MAAA,GAAS,MAAA,oBAA0B,OAAA;EACzE,KAAA,EAAO,MAAA,oBAA0B,OAAA;AAAA;AAAA,UAGlB,UAAA;EACf,SAAA;EACA,MAAA;EACA,OAAA;EACA,SAAA;EACA,OAAA;EACA,UAAA;AAAA;AAAA,UAGe,SAAA;EACf,GAAA,CAAI,KAAA,UAAe,MAAA,UAAgB,MAAA;EACnC,IAAA,EAAM,KAAA,uCAA4C,OAAA,UAAiB,OAAA,GAAU,UAAA;AAAA;AAAA,UAG9D,SAAA;EACf,MAAA;EACA,WAAA;EACA,MAAA;AAAA;AAAA,UAGe,YAAA;EACf,IAAA;EACA,KAAA;EACA,UAAA;EACA,WAAA;EACA,UAAA;EACA,KAAA;AAAA;AAAA,UAGe,SAAA,SAAkB,SAAA;EACjC,OAAA;EACA,eAAA;EACA,MAAA,EAAQ,YAAA;AAAA;AAAA,UAGO,aAAA;EACf,IAAA,EAAM,SAAA;EACN,eAAA;AAAA;AAAA,UAGe,WAAA;EACf,IAAA;EACA,IAAA;EACA,OAAA,GAAU,kBAAA;EACV,OAAA,CAAQ,GAAA,EAAK,UAAA,EAAY,aAAA,eAA4B,OAAA,CAAQ,SAAA;AAAA;AAAA,UAG9C,cAAA;EACf,IAAA;EACA,OAAA;EACA,OAAA,CAAQ,GAAA,EAAK,UAAA,GAAa,OAAA;AAAA;AAAA,KAGhB,YAAA,GAAe,WAAA,GAAc,cAAA;AAAA,UAExB,eAAA;EACf,IAAA,EAAM,WAAA;EACN,KAAA,EAAO,YAAA;EACP,MAAA,EAAQ,GAAA,SAAY,WAAA;EACpB,MAAA,EAAQ,GAAA;EACR,YAAA,GAAe,GAAA;AAAA;AAAA,cAqCJ,WAAA;EAAA,QACH,eAAA;EAAA,QACA,kBAAA;EAAA,QACA,OAAA;EAER,OAAA,CAAQ,GAAA,EAAK,OAAA,GAAU,eAAA;EAAA,QAmDf,gBAAA;EAAA,QAOA,qBAAA;EAAA,QAWA,UAAA;EAAA,QAqOM,YAAA;EAAA,QA8SN,gBAAA;EAAA,QAqBA,gBAAA;EAAA,QAuBA,aAAA;EAAA,QA6BA,YAAA;EAAA,QAWA,kBAAA;EAAA,QA2DM,aAAA;AAAA"}
|
package/dist/compiler.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compiler.d.mts","names":[],"sources":["../src/compiler.ts"],"mappings":";;;;UAOiB,aAAA;EACf,OAAA,GAAU,eAAA;EACV,WAAA,EAAa,aAAA;EACb,UAAA;AAAA;AAAA,iBAuBc,aAAA,CAAc,MAAA,WAAiB,aAAA;AAAA,UAgQ9B,WAAA;EACf,IAAA;EACA,OAAA;EACA,OAAA,GAAU,UAAA;AAAA;AAAA,UAGK,aAAA;EACf,MAAA,CAAO,KAAA,EAAO,WAAA;AAAA;AAAA,UAGC,UAAA;EACf,KAAA,EAAO,cAAA;EACP,IAAA,EAAM,GAAA;EACN,MAAA,EAAQ,SAAA;EACR,MAAA,GAAS,aAAA;AAAA;AAAA,UAGM,cAAA;EACf,IAAA,CAAK,IAAA,UAAc,KAAA,GAAQ,cAAA,eAA6B,OAAA;EACxD,KAAA,CAAM,IAAA,UAAc,IAAA;EACpB,OAAA,CAAQ,KAAA,UAAe,IAAA;EACvB,IAAA,EAAM,IAAA,UAAc,KAAA,aAAkB,MAAA,GAAS,MAAA,oBAA0B,OAAA;EACzE,KAAA,EAAO,MAAA,oBAA0B,OAAA;AAAA;AAAA,UAGlB,UAAA;EACf,SAAA;EACA,MAAA;EACA,OAAA;EACA,SAAA;EACA,OAAA;EACA,UAAA;AAAA;AAAA,UAGe,SAAA;EACf,GAAA,CAAI,KAAA,UAAe,MAAA,UAAgB,MAAA;EACnC,IAAA,EAAM,KAAA,uCAA4C,OAAA,UAAiB,OAAA,GAAU,UAAA;AAAA;AAAA,UAG9D,SAAA;EACf,MAAA;EACA,WAAA;EACA,MAAA;AAAA;AAAA,UAGe,YAAA;EACf,IAAA;EACA,KAAA;EACA,UAAA;EACA,WAAA;EACA,UAAA;EACA,KAAA;AAAA;AAAA,UAGe,SAAA,SAAkB,SAAA;EACjC,OAAA;EACA,eAAA;EACA,MAAA,EAAQ,YAAA;AAAA;AAAA,UAGO,aAAA;EACf,IAAA,EAAM,SAAA;EACN,eAAA;AAAA;AAAA,UAGe,WAAA;EACf,IAAA;EACA,IAAA;EACA,OAAA,GAAU,kBAAA;EACV,OAAA,CAAQ,GAAA,EAAK,UAAA,EAAY,aAAA,eAA4B,OAAA,CAAQ,SAAA;AAAA;AAAA,UAG9C,cAAA;EACf,IAAA;EACA,OAAA;EACA,OAAA,CAAQ,GAAA,EAAK,UAAA,GAAa,OAAA;AAAA;AAAA,KAGhB,YAAA,GAAe,WAAA,GAAc,cAAA;AAAA,UAExB,eAAA;EACf,IAAA,EAAM,WAAA;EACN,KAAA,EAAO,YAAA;EACP,MAAA,EAAQ,GAAA,SAAY,WAAA;EACpB,MAAA,EAAQ,GAAA;EACR,YAAA,GAAe,GAAA;AAAA;AAAA,cAqCJ,WAAA;EAAA,QACH,eAAA;EAAA,QACA,kBAAA;EAAA,QACA,OAAA;EAER,OAAA,CAAQ,GAAA,EAAK,OAAA,GAAU,eAAA;EAAA,QAmDf,gBAAA;EAAA,QAOA,qBAAA;EAAA,QAWA,UAAA;EAAA,QAqOM,YAAA;EAAA,
|
|
1
|
+
{"version":3,"file":"compiler.d.mts","names":[],"sources":["../src/compiler.ts"],"mappings":";;;;UAOiB,aAAA;EACf,OAAA,GAAU,eAAA;EACV,WAAA,EAAa,aAAA;EACb,UAAA;AAAA;AAAA,iBAuBc,aAAA,CAAc,MAAA,WAAiB,aAAA;AAAA,UAgQ9B,WAAA;EACf,IAAA;EACA,OAAA;EACA,OAAA,GAAU,UAAA;AAAA;AAAA,UAGK,aAAA;EACf,MAAA,CAAO,KAAA,EAAO,WAAA;AAAA;AAAA,UAGC,UAAA;EACf,KAAA,EAAO,cAAA;EACP,IAAA,EAAM,GAAA;EACN,MAAA,EAAQ,SAAA;EACR,MAAA,GAAS,aAAA;AAAA;AAAA,UAGM,cAAA;EACf,IAAA,CAAK,IAAA,UAAc,KAAA,GAAQ,cAAA,eAA6B,OAAA;EACxD,KAAA,CAAM,IAAA,UAAc,IAAA;EACpB,OAAA,CAAQ,KAAA,UAAe,IAAA;EACvB,IAAA,EAAM,IAAA,UAAc,KAAA,aAAkB,MAAA,GAAS,MAAA,oBAA0B,OAAA;EACzE,KAAA,EAAO,MAAA,oBAA0B,OAAA;AAAA;AAAA,UAGlB,UAAA;EACf,SAAA;EACA,MAAA;EACA,OAAA;EACA,SAAA;EACA,OAAA;EACA,UAAA;AAAA;AAAA,UAGe,SAAA;EACf,GAAA,CAAI,KAAA,UAAe,MAAA,UAAgB,MAAA;EACnC,IAAA,EAAM,KAAA,uCAA4C,OAAA,UAAiB,OAAA,GAAU,UAAA;AAAA;AAAA,UAG9D,SAAA;EACf,MAAA;EACA,WAAA;EACA,MAAA;AAAA;AAAA,UAGe,YAAA;EACf,IAAA;EACA,KAAA;EACA,UAAA;EACA,WAAA;EACA,UAAA;EACA,KAAA;AAAA;AAAA,UAGe,SAAA,SAAkB,SAAA;EACjC,OAAA;EACA,eAAA;EACA,MAAA,EAAQ,YAAA;AAAA;AAAA,UAGO,aAAA;EACf,IAAA,EAAM,SAAA;EACN,eAAA;AAAA;AAAA,UAGe,WAAA;EACf,IAAA;EACA,IAAA;EACA,OAAA,GAAU,kBAAA;EACV,OAAA,CAAQ,GAAA,EAAK,UAAA,EAAY,aAAA,eAA4B,OAAA,CAAQ,SAAA;AAAA;AAAA,UAG9C,cAAA;EACf,IAAA;EACA,OAAA;EACA,OAAA,CAAQ,GAAA,EAAK,UAAA,GAAa,OAAA;AAAA;AAAA,KAGhB,YAAA,GAAe,WAAA,GAAc,cAAA;AAAA,UAExB,eAAA;EACf,IAAA,EAAM,WAAA;EACN,KAAA,EAAO,YAAA;EACP,MAAA,EAAQ,GAAA,SAAY,WAAA;EACpB,MAAA,EAAQ,GAAA;EACR,YAAA,GAAe,GAAA;AAAA;AAAA,cAqCJ,WAAA;EAAA,QACH,eAAA;EAAA,QACA,kBAAA;EAAA,QACA,OAAA;EAER,OAAA,CAAQ,GAAA,EAAK,OAAA,GAAU,eAAA;EAAA,QAmDf,gBAAA;EAAA,QAOA,qBAAA;EAAA,QAWA,UAAA;EAAA,QAqOM,YAAA;EAAA,QA8SN,gBAAA;EAAA,QAqBA,gBAAA;EAAA,QAuBA,aAAA;EAAA,QA6BA,YAAA;EAAA,QAWA,kBAAA;EAAA,QA2DM,aAAA;AAAA"}
|
package/dist/compiler.mjs
CHANGED
|
@@ -548,12 +548,13 @@ var AshCompiler = class {
|
|
|
548
548
|
}
|
|
549
549
|
return mapped;
|
|
550
550
|
};
|
|
551
|
+
const initialRec = initialStream?.[0] ?? void 0;
|
|
551
552
|
if (stage.exprMappings) return stream.map((item) => {
|
|
552
553
|
const result = {};
|
|
553
|
-
for (const [key, expr] of Object.entries(stage.exprMappings)) result[key] = this.evaluateExpression(expr, item, variables);
|
|
554
|
+
for (const [key, expr] of Object.entries(stage.exprMappings)) result[key] = this.evaluateExpression(expr, item, variables, initialRec);
|
|
554
555
|
return preserveSystemFields(item, result);
|
|
555
556
|
});
|
|
556
|
-
if (stage.expression) return stream.map((item) => this.evaluateExpression(stage.expression, item, variables));
|
|
557
|
+
if (stage.expression) return stream.map((item) => this.evaluateExpression(stage.expression, item, variables, initialRec));
|
|
557
558
|
if (stage.mappings) return stream.map((item) => {
|
|
558
559
|
const result = {};
|
|
559
560
|
for (const [key, field] of Object.entries(stage.mappings)) result[key] = this.resolveField(item, field);
|
|
@@ -800,16 +801,23 @@ var AshCompiler = class {
|
|
|
800
801
|
}
|
|
801
802
|
return current;
|
|
802
803
|
}
|
|
803
|
-
evaluateExpression(expr, item, variables) {
|
|
804
|
+
evaluateExpression(expr, item, variables, fallbackItem) {
|
|
804
805
|
switch (expr.kind) {
|
|
805
806
|
case "literal": return expr.value;
|
|
806
|
-
case "field_access":
|
|
807
|
+
case "field_access": {
|
|
808
|
+
const value = this.resolveField(item, expr.path);
|
|
809
|
+
if (value === void 0 && fallbackItem != null) {
|
|
810
|
+
const topField = expr.path.split(".")[0];
|
|
811
|
+
if (typeof item !== "object" || item === null || !Object.hasOwn(item, topField)) return this.resolveField(fallbackItem, expr.path);
|
|
812
|
+
}
|
|
813
|
+
return value;
|
|
814
|
+
}
|
|
807
815
|
case "var_ref":
|
|
808
816
|
if (!variables.has(expr.name)) throw new Error(`Undefined variable: $${expr.name}`);
|
|
809
817
|
return variables.get(expr.name);
|
|
810
818
|
case "binary": {
|
|
811
|
-
const left = this.evaluateExpression(expr.left, item, variables);
|
|
812
|
-
const right = this.evaluateExpression(expr.right, item, variables);
|
|
819
|
+
const left = this.evaluateExpression(expr.left, item, variables, fallbackItem);
|
|
820
|
+
const right = this.evaluateExpression(expr.right, item, variables, fallbackItem);
|
|
813
821
|
switch (expr.op) {
|
|
814
822
|
case "+":
|
|
815
823
|
if (typeof left === "string" || typeof right === "string") return String(left ?? "") + String(right ?? "");
|
|
@@ -820,10 +828,10 @@ var AshCompiler = class {
|
|
|
820
828
|
default: throw new Error(`Unknown operator: ${expr.op}`);
|
|
821
829
|
}
|
|
822
830
|
}
|
|
823
|
-
case "array_literal": return expr.elements.map((el) => this.evaluateExpression(el, item, variables));
|
|
831
|
+
case "array_literal": return expr.elements.map((el) => this.evaluateExpression(el, item, variables, fallbackItem));
|
|
824
832
|
case "object_literal": {
|
|
825
833
|
const obj = {};
|
|
826
|
-
for (const [key, valExpr] of Object.entries(expr.properties)) obj[key] = this.evaluateExpression(valExpr, item, variables);
|
|
834
|
+
for (const [key, valExpr] of Object.entries(expr.properties)) obj[key] = this.evaluateExpression(valExpr, item, variables, fallbackItem);
|
|
827
835
|
return obj;
|
|
828
836
|
}
|
|
829
837
|
default: throw new Error(`Unknown expression kind: ${expr.kind}`);
|
package/dist/compiler.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compiler.mjs","names":["durationMs","capPath","result"],"sources":["../src/compiler.ts"],"sourcesContent":["import type { Program, JobDeclaration, PipelineStage, WhereClause, FanoutExpression, OutputExpression, TopLevelStatement, QueryCondition, LetStatement, GroupByExpression, ActionExpression, Expression, MapExpression, RouteExpression, LookupExpression, ParamDeclaration, TriggerDeclaration } from \"./ast.js\";\nimport { AshLexer } from \"./lexer.js\";\nimport { AshParser } from \"./parser.js\";\nimport { checkPipelineTypes, checkProhibitedPatterns, checkAnnotations, checkJobCaps, typeErrorsToDiagnostics, compileErrorsToDiagnostics, annotationErrorsToDiagnostics, parseSyntaxError, parseCaps, hasCapFor } from \"./type-checker.js\";\nimport type { AshDiagnostic, CapEntry } from \"./type-checker.js\";\nimport { resolveActionParams, resolveTemplatePath } from \"./template.js\";\n\nexport interface CompileResult {\n program?: CompiledProgram;\n diagnostics: AshDiagnostic[];\n sourceHash?: string;\n}\n\nfunction fnv1aHash(str: string): string {\n let hash = 2166136261;\n for (let i = 0; i < str.length; i++) {\n hash ^= str.charCodeAt(i);\n hash = Math.imul(hash, 16777619) >>> 0;\n }\n return hash.toString(16).padStart(8, \"0\");\n}\n\nfunction collectActions(stages: PipelineStage[]): ActionExpression[] {\n const actions: ActionExpression[] = [];\n for (const stage of stages) {\n if (stage.kind === \"action\") actions.push(stage);\n else if (stage.kind === \"fanout\") {\n for (const branch of stage.branches) actions.push(...collectActions(branch));\n }\n }\n return actions;\n}\n\nexport function compileSource(source: string): CompileResult {\n const diagnostics: AshDiagnostic[] = [];\n const sourceHash = fnv1aHash(source);\n const lexer = new AshLexer();\n const parser = new AshParser();\n const compiler = new AshCompiler();\n\n // Lex\n let tokens;\n try {\n tokens = lexer.tokenize(source);\n } catch (e: any) {\n return { sourceHash, diagnostics: [parseSyntaxError(e.message ?? String(e))] };\n }\n\n // Parse\n let ast;\n try {\n ast = parser.parse(tokens);\n } catch (e: any) {\n return { sourceHash, diagnostics: [parseSyntaxError(e.message ?? String(e))] };\n }\n\n // Type check\n const prohibErrors = checkProhibitedPatterns(ast);\n diagnostics.push(...compileErrorsToDiagnostics(prohibErrors));\n\n for (const job of ast.jobs) {\n const typeErrors = checkPipelineTypes(job.pipeline);\n diagnostics.push(...typeErrorsToDiagnostics(typeErrors));\n\n const annErrors = checkAnnotations(job);\n diagnostics.push(...annotationErrorsToDiagnostics(annErrors));\n\n // @caps: static path security check\n diagnostics.push(...checkJobCaps(job));\n\n // @readonly check: pipeline must not contain save, publish, or tee\n const isReadonly = job.annotations.some(a => a.name === \"readonly\");\n if (isReadonly) {\n for (const stage of job.pipeline) {\n if (stage.kind === \"save\" || stage.kind === \"publish\" || stage.kind === \"tee\" || stage.kind === \"action\") {\n diagnostics.push({\n code: \"ASH_READONLY_VIOLATION\",\n message: `@readonly job '${job.name}' contains '${stage.kind}' which writes data`,\n });\n }\n }\n // Check route targets: @readonly must propagate to route-target jobs\n for (const stage of job.pipeline) {\n if (stage.kind === \"route\") {\n const targetNames = [...stage.branches.map(b => b.targetJob), ...(stage.fallback ? [stage.fallback] : [])];\n for (const targetName of targetNames) {\n const targetJob = ast.jobs.find(j => j.name === targetName);\n if (!targetJob) continue;\n for (const tStage of targetJob.pipeline) {\n if (tStage.kind === \"save\" || tStage.kind === \"publish\" || tStage.kind === \"tee\" || tStage.kind === \"action\") {\n diagnostics.push({\n code: \"ASH_READONLY_VIOLATION\",\n message: `@readonly job '${job.name}' routes to '${targetName}' which contains '${tStage.kind}' (write operation)`,\n });\n break; // one error per target is enough\n }\n }\n }\n }\n }\n }\n }\n\n // Let pipeline restrictions: writes in let bindings are never legitimate\n const WRITE_STAGES = new Set([\"save\", \"publish\", \"tee\", \"action\"]);\n const letStatements = ast.statements.filter((s): s is LetStatement => s.kind === \"let\" && !!s.pipeline);\n for (const letStmt of letStatements) {\n if (letStmt.pipeline) {\n for (const stage of letStmt.pipeline) {\n if (WRITE_STAGES.has(stage.kind)) {\n diagnostics.push({\n code: \"ASH_LET_WRITE\",\n message: `let '${letStmt.name}' pipeline contains '${stage.kind}' — write operations in let bindings are not permitted`,\n });\n }\n }\n }\n }\n\n // Let pipeline pre-approval bypass: let pipelines with find/action execute before @approval checks\n const hasApproval = ast.jobs.some(j => j.annotations.some(a => a.name === \"approval\"));\n if (hasApproval && letStatements.length > 0) {\n const sideEffectLets = letStatements.filter(s =>\n s.pipeline?.some(stage => stage.kind === \"find\" || stage.kind === \"action\"),\n );\n if (sideEffectLets.length > 0) {\n diagnostics.push({\n code: \"ASH_LET_PRE_APPROVAL\",\n severity: \"warning\",\n message: `let bindings (${sideEffectLets.map(s => s.name).join(\", \")}) execute before @approval checks — side effects in let pipelines bypass approval`,\n });\n }\n }\n\n // Param write-gate: $param in where clause before write operation = logic bomb risk\n const paramNames = new Set(ast.statements.filter((s): s is ParamDeclaration => s.kind === \"param\").map(s => s.name));\n if (paramNames.size > 0) {\n for (const job of ast.jobs) {\n const hasWrite = job.pipeline.some(s => WRITE_STAGES.has(s.kind));\n if (!hasWrite) continue;\n for (const stage of job.pipeline) {\n if (stage.kind === \"where\" && typeof stage.right === \"string\" && stage.right.startsWith(\"$\")) {\n const varName = stage.right.slice(1);\n if (paramNames.has(varName)) {\n diagnostics.push({\n code: \"ASH_PARAM_WRITE_GATE\",\n severity: \"warning\",\n message: `Job '${job.name}': param '$${varName}' gates write operations — callers can override param to change behavior`,\n });\n break; // one warning per job\n }\n }\n }\n }\n }\n\n // Mixed annotation deception check: @readonly jobs alongside unrestricted write jobs\n const readonlyJobs = ast.jobs.filter(j => j.annotations.some(a => a.name === \"readonly\"));\n if (readonlyJobs.length > 0 && readonlyJobs.length < ast.jobs.length) {\n const nonReadonly = ast.jobs.filter(j => !j.annotations.some(a => a.name === \"readonly\"));\n const writingJobs = nonReadonly.filter(j =>\n j.pipeline.some(s => s.kind === \"save\" || s.kind === \"publish\" || s.kind === \"tee\" || s.kind === \"action\"),\n );\n if (writingJobs.length > 0) {\n diagnostics.push({\n code: \"ASH_MIXED_SECURITY\",\n severity: \"warning\",\n message: `Program has mixed security posture: ${readonlyJobs.length} @readonly job(s) alongside ${writingJobs.length} unrestricted writing job(s) (${writingJobs.map(j => j.name).join(\", \")}) — this can mask malicious intent`,\n });\n }\n }\n\n // Action hardening: uncapped, amplification (caps+budget gated), cross-provider (caps+budget gated)\n for (const job of ast.jobs) {\n const actions = collectActions(job.pipeline);\n if (actions.length === 0) continue;\n\n const hasCaps = job.annotations.some(a => a.name === \"caps\");\n const hasBudget = job.annotations.some(a => a.name === \"budget\");\n\n // No @caps + action → error (actions require explicit capability declaration)\n if (!hasCaps) {\n diagnostics.push({\n code: \"ASH_UNCAPPED_ACTION\",\n message: `Job '${job.name}' contains action stages but has no @caps — actions require explicit capability declaration`,\n });\n }\n\n // Multiple actions → caps+budget gated\n if (actions.length > 1) {\n if (hasCaps && hasBudget) {\n diagnostics.push({\n code: \"ASH_ACTION_AMPLIFICATION\",\n severity: \"warning\",\n message: `Job '${job.name}' contains ${actions.length} action stages — budget-gated multi-action execution permitted`,\n });\n } else {\n diagnostics.push({\n code: \"ASH_ACTION_AMPLIFICATION\",\n message: `Job '${job.name}' contains ${actions.length} action stages — multi-action jobs require @caps and @budget to prevent amplification attacks`,\n });\n }\n }\n\n // Actions targeting multiple providers → caps+budget gated\n const providers = new Set(actions.filter(a => !a.relative).map(a => a.path.split(\"/\")[1]).filter(Boolean));\n if (providers.size > 1) {\n if (hasCaps && hasBudget) {\n diagnostics.push({\n code: \"ASH_CROSS_PROVIDER_ACTION\",\n severity: \"warning\",\n message: `Job '${job.name}' has actions targeting ${providers.size} providers (${[...providers].join(\", \")}) — budget-gated cross-provider execution permitted`,\n });\n } else {\n diagnostics.push({\n code: \"ASH_CROSS_PROVIDER_ACTION\",\n message: `Job '${job.name}' has actions targeting ${providers.size} providers (${[...providers].join(\", \")}) — cross-provider actions require @caps and @budget`,\n });\n }\n }\n\n // Relative action checks\n const relativeActions = actions.filter(a => a.relative);\n if (relativeActions.length > 0) {\n // Relative action without upstream find → error\n const hasFindUpstream = job.pipeline.some((s, idx) =>\n s.kind === \"find\" && job.pipeline.findIndex(p => p === relativeActions[0]) > idx\n );\n if (!hasFindUpstream) {\n diagnostics.push({\n code: \"ASH_RELATIVE_ACTION_NO_FIND\",\n message: `Job '${job.name}': relative action '${relativeActions[0].path}' has no upstream 'find' — relative actions require a find stage to provide records with paths`,\n });\n }\n\n // Relative action = inherent amplification (1 stage, N execs)\n if (hasCaps && hasBudget) {\n diagnostics.push({\n code: \"ASH_ACTION_AMPLIFICATION\",\n severity: \"warning\",\n message: `Job '${job.name}': relative action '${relativeActions[0].path}' executes per-record — budget-gated amplification permitted`,\n });\n } else if (!hasCaps || !hasBudget) {\n diagnostics.push({\n code: \"ASH_ACTION_AMPLIFICATION\",\n message: `Job '${job.name}': relative action '${relativeActions[0].path}' executes per-record — requires @caps and @budget to prevent amplification`,\n });\n }\n }\n }\n\n // Write operation hardening: publish and tee require @caps\n for (const job of ast.jobs) {\n const hasCaps = job.annotations.some(a => a.name === \"caps\");\n const hasFind = job.pipeline.some(s => s.kind === \"find\" || s.kind === \"lookup\");\n const writeStages = job.pipeline.filter(s => s.kind === \"publish\" || s.kind === \"tee\");\n\n if (writeStages.length > 0 && hasFind && !hasCaps) {\n for (const ws of writeStages) {\n diagnostics.push({\n code: \"ASH_UNCAPPED_WRITE\",\n message: `Job '${job.name}': '${ws.kind}' combined with data reads requires @caps — write operations on external data must declare capabilities`,\n });\n }\n }\n }\n\n // Budget ceiling: reject unreasonably high budget values\n const BUDGET_CEILINGS: Record<string, number> = { actions: 100, writes: 100, records: 10000 };\n for (const job of ast.jobs) {\n const budgetAnn = job.annotations.find(a => a.name === \"budget\");\n if (!budgetAnn) continue;\n for (let i = 0; i < budgetAnn.args.length; i += 2) {\n const dim = budgetAnn.args[i];\n const val = Number(budgetAnn.args[i + 1]);\n if (dim in BUDGET_CEILINGS && val > BUDGET_CEILINGS[dim]) {\n diagnostics.push({\n code: \"ASH_BUDGET_EXCESSIVE\",\n message: `Job '${job.name}': @budget(${dim} ${val}) exceeds ceiling of ${BUDGET_CEILINGS[dim]} — reduce budget or justify with explicit approval`,\n });\n }\n }\n }\n\n // Compile\n const program = compiler.compile(ast);\n return { program, diagnostics, sourceHash };\n}\n\nexport interface OutputEvent {\n kind: \"text\";\n content: string;\n context?: LogContext;\n}\n\nexport interface OutputHandler {\n output(event: OutputEvent): void;\n}\n\nexport interface JobContext {\n world: WorldInterface;\n caps: Set<string>;\n logger: JobLogger;\n output?: OutputHandler;\n}\n\nexport interface WorldInterface {\n read(path: string, query?: QueryCondition): unknown[] | Promise<unknown[]>;\n write(path: string, data: unknown[]): void;\n publish(topic: string, data: unknown[]): void;\n exec?(path: string, input: unknown[], params?: Record<string, unknown>): Promise<unknown[]>;\n input?(prompt: string): string | Promise<string>;\n}\n\nexport interface LogContext {\n programId?: string;\n procId?: string;\n agentId?: string;\n sessionId?: string;\n jobName?: string;\n stageIndex?: number;\n}\n\nexport interface JobLogger {\n log(stage: string, action: string, detail?: unknown): void;\n emit?(level: \"debug\" | \"info\" | \"warn\" | \"error\", message: string, context?: LogContext): void;\n}\n\nexport interface JobResult {\n status: \"ok\" | \"error\" | \"partial\";\n recordCount: number;\n errors: string[];\n}\n\nexport interface StageMetrics {\n name: string;\n index: number;\n inputCount: number;\n outputCount: number;\n durationMs: number;\n error?: string;\n}\n\nexport interface JobReport extends JobResult {\n jobName: string;\n totalDurationMs: number;\n stages: StageMetrics[];\n}\n\nexport interface ProgramReport {\n jobs: JobReport[];\n totalDurationMs: number;\n}\n\nexport interface CompiledJob {\n kind: \"job\";\n name: string;\n trigger?: TriggerDeclaration;\n execute(ctx: JobContext, initialStream?: unknown[]): Promise<JobResult>;\n}\n\nexport interface CompiledOutput {\n kind: \"output\";\n message: string;\n execute(ctx: JobContext): Promise<void>;\n}\n\nexport type CompiledUnit = CompiledJob | CompiledOutput;\n\nexport interface CompiledProgram {\n jobs: CompiledJob[];\n units: CompiledUnit[];\n jobMap: Map<string, CompiledJob>;\n params: Map<string, string | number | (string | number)[]>; // param defaults (can be overridden before execution)\n routeTargets?: Set<string>; // jobs that are ONLY route targets (should not auto-execute as top-level)\n}\n\nfunction safeOutput(ctx: JobContext, content: string, logContext?: LogContext): void {\n if (ctx.output) {\n try {\n ctx.output.output({ kind: \"text\", content, context: logContext });\n } catch {\n // Output fault must not crash pipeline\n }\n }\n safeEmit(ctx.logger, \"info\", content, logContext);\n}\n\nfunction safeEmit(logger: JobLogger, level: \"debug\" | \"info\" | \"warn\" | \"error\", message: string, context?: LogContext): void {\n if (logger.emit) {\n try {\n logger.emit(level, message, context);\n } catch {\n // Log fault must not crash pipeline (INVARIANT: emit failure is silent)\n }\n }\n}\n\n/**\n * Strict equality with boolean coercion only.\n * No string fallback (prevents type confusion like 0 == \"0\").\n * Boolean coercion: true/\"true\" and false/\"false\" are equal.\n */\nfunction strictEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n // Boolean coercion: \"true\" matches true, \"false\" matches false\n if (typeof a === \"boolean\" && typeof b === \"string\") return a === (b === \"true\");\n if (typeof b === \"boolean\" && typeof a === \"string\") return b === (a === \"true\");\n return false;\n}\n\nexport class AshCompiler {\n private _currentJobName?: string;\n private _currentStageIndex?: number;\n private _jobMap = new Map<string, CompiledJob>();\n\n compile(ast: Program): CompiledProgram {\n // Collect param defaults\n const params = new Map<string, string | number | (string | number)[]>();\n for (const stmt of ast.statements) {\n if (stmt.kind === \"param\") {\n params.set(stmt.name, stmt.defaultValue);\n }\n }\n\n // Collect static let bindings (params first, then lets override)\n const variables = new Map<string, string | number | (string | number)[]>(params);\n const runtimeLets: LetStatement[] = [];\n for (const stmt of ast.statements) {\n if (stmt.kind === \"let\") {\n if (stmt.pipeline) {\n runtimeLets.push(stmt);\n } else {\n variables.set(stmt.name, stmt.value);\n }\n }\n }\n\n const units: CompiledUnit[] = ast.statements\n .filter((s): s is Exclude<TopLevelStatement, LetStatement | ParamDeclaration> => s.kind !== \"let\" && s.kind !== \"param\")\n .map((stmt) => this.compileStatement(stmt, variables, runtimeLets));\n const jobs = units.filter((u): u is CompiledJob => u.kind === \"job\");\n const jobMap = new Map<string, CompiledJob>();\n for (const job of jobs) jobMap.set(job.name, job);\n this._jobMap = jobMap;\n\n // Identify route-target-only jobs: jobs referenced by route stages but with no trigger\n const routeTargetNames = new Set<string>();\n const triggeredJobs = new Set<string>();\n for (const job of ast.jobs) {\n if (job.trigger) triggeredJobs.add(job.name);\n for (const stage of job.pipeline) {\n if (stage.kind === \"route\") {\n for (const branch of stage.branches) {\n routeTargetNames.add(branch.targetJob);\n }\n if (stage.fallback) routeTargetNames.add(stage.fallback);\n }\n }\n }\n // Exclude triggered jobs — they have independent execution reasons\n for (const name of triggeredJobs) routeTargetNames.delete(name);\n const routeTargets = routeTargetNames.size > 0 ? routeTargetNames : undefined;\n\n return { jobs, units, jobMap, params, routeTargets };\n }\n\n private compileStatement(stmt: Exclude<TopLevelStatement, LetStatement | ParamDeclaration>, variables: Map<string, string | number | (string | number)[]>, runtimeLets: LetStatement[] = []): CompiledUnit {\n if (stmt.kind === \"output\") {\n return this.compileTopLevelOutput(stmt);\n }\n return this.compileJob(stmt, variables, runtimeLets);\n }\n\n private compileTopLevelOutput(output: OutputExpression): CompiledOutput {\n return {\n kind: \"output\",\n message: output.message,\n execute: async (ctx: JobContext): Promise<void> => {\n ctx.logger.log(\"output\", \"output\", { message: output.message });\n safeOutput(ctx, output.message);\n },\n };\n }\n\n private compileJob(job: JobDeclaration, variables: Map<string, string | number | (string | number)[]> = new Map(), runtimeLets: LetStatement[] = []): CompiledJob {\n const stages = job.pipeline;\n const annotations = job.annotations;\n\n // Extract annotation configs\n const retryAnn = annotations.find(a => a.name === \"retry\");\n const timeoutAnn = annotations.find(a => a.name === \"timeout\");\n const onErrorAnn = annotations.find(a => a.name === \"on_error\");\n const budgetAnn = annotations.find(a => a.name === \"budget\");\n const retryCount = retryAnn ? (retryAnn.args.length > 0 ? Number(retryAnn.args[0]) : 3) : 0;\n const timeoutMs = timeoutAnn ? (timeoutAnn.args.length > 0 ? Number(timeoutAnn.args[0]) : 0) : 0;\n const onErrorStrategy = onErrorAnn?.args[0] as \"skip\" | \"save\" | \"fail\" | undefined;\n const onErrorPath = onErrorStrategy === \"save\" ? onErrorAnn?.args[1] : undefined;\n\n // Parse budget limits\n const budgetLimits: Record<string, number> = {};\n if (budgetAnn) {\n for (let i = 0; i < budgetAnn.args.length; i += 2) {\n budgetLimits[budgetAnn.args[i]] = Number(budgetAnn.args[i + 1]);\n }\n }\n\n // Parse @caps for runtime enforcement (script-declared caps are authoritative)\n const capsAnns = annotations.filter(a => a.name === \"caps\");\n const scriptCaps: CapEntry[] = [];\n for (const ann of capsAnns) {\n if (ann.args.length > 0 && ann.args.length % 2 === 0) {\n scriptCaps.push(...parseCaps(ann));\n }\n }\n\n const self = this;\n\n const runOnce = async (ctx: JobContext, initialStream?: unknown[]): Promise<JobReport> => {\n const errors: string[] = [];\n const jobInitialStream = initialStream ?? [];\n let stream: unknown[] = [...jobInitialStream];\n const stageMetrics: StageMetrics[] = [];\n const jobStart = performance.now();\n const budgetUsed = { actions: 0, writes: 0, records: 0, tokens: 0, cost: 0 };\n const checkBudget = (dim: string, increment: number) => {\n if (!(dim in budgetLimits)) return;\n (budgetUsed as any)[dim] += increment;\n if ((budgetUsed as any)[dim] > budgetLimits[dim]) {\n throw new Error(`budget exceeded: ${dim} used ${(budgetUsed as any)[dim]}, limit ${budgetLimits[dim]}`);\n }\n };\n\n // Runtime caps enforcement: if script declares @caps, enforce them with glob matching.\n // Script-declared caps are the ceiling — ctx.caps (caller-provided) cannot widen them.\n const checkCap = (op: CapEntry[\"op\"], path: string): void => {\n if (scriptCaps.length > 0 && !hasCapFor(scriptCaps, op, path)) {\n throw new Error(`Permission denied: @caps does not allow ${op} '${path}'`);\n }\n };\n\n // Resolve runtime lets\n const runtimeVars = new Map(variables);\n for (const rtLet of runtimeLets) {\n if (rtLet.pipeline) {\n try {\n let rtStream: unknown[] = [];\n for (const stage of rtLet.pipeline) {\n rtStream = await self.executeStage(stage, rtStream, ctx, errors, runtimeVars);\n }\n // Bind the result: if single object with a numeric/string value, extract it\n if (rtStream.length === 1 && typeof rtStream[0] === \"object\" && rtStream[0] !== null) {\n const obj = rtStream[0] as Record<string, unknown>;\n const keys = Object.keys(obj);\n if (keys.length === 1) {\n const val = obj[keys[0]];\n if (typeof val === \"number\" || typeof val === \"string\") {\n runtimeVars.set(rtLet.name, val);\n continue;\n }\n }\n }\n // Fallback: use length or first value\n if (rtStream.length === 1) {\n const v = rtStream[0];\n if (typeof v === \"number\" || typeof v === \"string\") {\n runtimeVars.set(rtLet.name, v);\n } else {\n runtimeVars.set(rtLet.name, rtStream.length);\n }\n } else {\n // Multi-record: try to collect scalar values into an array\n const collected: (string | number)[] = [];\n let allScalar = true;\n for (const item of rtStream) {\n if (typeof item === \"string\" || typeof item === \"number\") {\n collected.push(item);\n } else if (typeof item === \"object\" && item !== null) {\n const keys = Object.keys(item as Record<string, unknown>);\n if (keys.length === 1) {\n const val = (item as Record<string, unknown>)[keys[0]];\n if (typeof val === \"string\" || typeof val === \"number\") {\n collected.push(val);\n continue;\n }\n }\n allScalar = false;\n break;\n } else {\n allScalar = false;\n break;\n }\n }\n runtimeVars.set(rtLet.name, allScalar ? collected : rtStream.length);\n }\n } catch (e: any) {\n errors.push(`Runtime let '${rtLet.name}' failed: ${e.message ?? String(e)}`);\n return { status: \"error\", recordCount: 0, errors, jobName: job.name, totalDurationMs: performance.now() - jobStart, stages: stageMetrics };\n }\n }\n }\n\n for (let i = 0; i < stages.length; i++) {\n const stage = stages[i];\n const inputCount = stream.length;\n const stageStart = performance.now();\n self._currentJobName = job.name;\n self._currentStageIndex = i;\n try {\n // Skip absolute actions on empty downstream stream (not first stage).\n // \"action as source\" (i === 0) still executes — it generates data from nothing.\n // Relative actions already skip naturally (for-of loop over empty stream).\n if (stage.kind === \"action\" && !stage.relative && i > 0 && stream.length === 0) {\n const durationMs = performance.now() - stageStart;\n ctx.logger.log(stage.kind, \"skip\", { reason: \"empty-stream\" });\n safeEmit(ctx.logger, \"debug\", `${stage.kind} skip (empty stream)`, { jobName: job.name, stageIndex: i });\n stageMetrics.push({ name: stage.kind, index: i, inputCount, outputCount: 0, durationMs });\n continue;\n }\n ctx.logger.log(stage.kind, \"enter\", { recordCount: stream.length });\n safeEmit(ctx.logger, \"debug\", `${stage.kind} enter`, { jobName: job.name, stageIndex: i });\n stream = await self.executeStage(stage, stream, ctx, errors, runtimeVars, checkBudget, checkCap, jobInitialStream);\n // Budget checks after stage execution\n // Relative actions are checked per-record inside executeStage; only check absolute actions here\n // Absolute actions with inline params also check per-record inside executeStage\n const hasInlineParams = stage.kind === \"action\" && !stage.relative &&\n stage.params && Object.keys(stage.params).length > 0;\n if (stage.kind === \"action\" && !stage.relative && !hasInlineParams) checkBudget(\"actions\", 1);\n if (stage.kind === \"save\" || stage.kind === \"publish\" || stage.kind === \"tee\") checkBudget(\"writes\", 1);\n checkBudget(\"records\", stream.length);\n const durationMs = performance.now() - stageStart;\n ctx.logger.log(stage.kind, \"exit\", { recordCount: stream.length });\n safeEmit(ctx.logger, \"debug\", `${stage.kind} exit`, { jobName: job.name, stageIndex: i });\n stageMetrics.push({ name: stage.kind, index: i, inputCount, outputCount: stream.length, durationMs });\n } catch (e: any) {\n const durationMs = performance.now() - stageStart;\n const errMsg = e.message ?? String(e);\n errors.push(errMsg);\n\n if (onErrorStrategy === \"skip\") {\n // Skip: log error, continue with remaining stream\n stageMetrics.push({ name: stage.kind, index: i, inputCount, outputCount: stream.length, durationMs, error: errMsg });\n continue;\n } else if (onErrorStrategy === \"save\" && onErrorPath) {\n // Save: write failed items to error path\n try {\n ctx.world.write(onErrorPath, stream.map(item => ({ _error: errMsg, _item: item })));\n } catch {\n errors.push(`Failed to write errors to ${onErrorPath}`);\n }\n stageMetrics.push({ name: stage.kind, index: i, inputCount, outputCount: stream.length, durationMs, error: errMsg });\n continue;\n }\n\n // Default (fail): terminate\n stageMetrics.push({ name: stage.kind, index: i, inputCount, outputCount: stream.length, durationMs, error: errMsg });\n return { status: \"error\", recordCount: stream.length, errors, jobName: job.name, totalDurationMs: performance.now() - jobStart, stages: stageMetrics };\n }\n }\n\n return {\n status: errors.length > 0 ? \"partial\" : \"ok\",\n recordCount: stream.length,\n errors,\n jobName: job.name,\n totalDurationMs: performance.now() - jobStart,\n stages: stageMetrics,\n };\n };\n\n const runWithTimeout = async (ctx: JobContext, initialStream?: unknown[]): Promise<JobResult> => {\n if (timeoutMs <= 0) return runOnce(ctx, initialStream);\n return Promise.race([\n runOnce(ctx, initialStream),\n new Promise<JobResult>((_, reject) =>\n setTimeout(() => reject(new Error(`Timeout: job exceeded ${timeoutMs}ms`)), timeoutMs)\n ),\n ]);\n };\n\n return {\n kind: \"job\",\n name: job.name,\n trigger: job.trigger,\n execute: async (ctx: JobContext, initialStream?: unknown[]): Promise<JobResult> => {\n if (retryCount <= 0 && !retryAnn) {\n // No retry annotation at all\n return runWithTimeout(ctx, initialStream);\n }\n\n const maxAttempts = retryCount > 0 ? retryCount : 1;\n const allErrors: string[] = [];\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n try {\n const result = await runWithTimeout(ctx, initialStream);\n if (result.status !== \"error\") return result;\n allErrors.push(...result.errors);\n // If last attempt, return error\n if (attempt === maxAttempts - 1) return { status: \"error\", recordCount: result.recordCount, errors: allErrors };\n // Backoff (in tests we don't actually wait)\n } catch (e: any) {\n allErrors.push(e.message ?? String(e));\n if (attempt === maxAttempts - 1) {\n return { status: \"error\", recordCount: 0, errors: allErrors };\n }\n }\n }\n\n return { status: \"error\", recordCount: 0, errors: allErrors };\n },\n };\n }\n\n private async executeStage(stage: PipelineStage, stream: unknown[], ctx: JobContext, errors: string[], variables: Map<string, string | number | (string | number)[]> = new Map(), budgetCheck?: (dim: string, increment: number) => void, capCheck?: (op: CapEntry[\"op\"], path: string) => void, initialStream?: unknown[]): Promise<unknown[]> {\n switch (stage.kind) {\n case \"find\": {\n // Resolve template path from stream context (e.g. find /msgs/${data.messageId})\n let findPath = stage.path;\n if (findPath.includes(\"${\") && stream.length > 0) {\n const rec = (typeof stream[0] === \"object\" && stream[0] !== null ? stream[0] : {}) as Record<string, unknown>;\n findPath = resolveTemplatePath(findPath, rec);\n }\n\n // Runtime @caps enforcement (script-declared caps)\n if (capCheck) capCheck(\"read\", findPath);\n const capPath = findPath.split(\"/\").slice(0, 3).join(\"/\");\n if (ctx.caps.size > 0 && !ctx.caps.has(capPath) && !ctx.caps.has(\"*\")) {\n throw new Error(`Permission denied: cannot read '${findPath}'`);\n }\n try {\n const query = stage.query ? this.resolveQueryVars(stage.query, variables) : undefined;\n let result = await ctx.world.read(findPath, query);\n // Fallback: if world.read ignores query, apply in-memory filter\n if (query && result.length > 0) {\n result = result.filter((item) => {\n try {\n return this.evaluateWhere(\n { kind: \"where\", left: query!.field, op: query!.op, right: query!.value },\n item,\n );\n } catch {\n return false;\n }\n });\n }\n return result;\n } catch {\n return []; // non-existent path → empty stream\n }\n }\n\n case \"where\": {\n // Resolve $variable references in where clause\n const resolvedStage = this.resolveWhereVars(stage, variables);\n return stream.filter((item) => {\n try {\n return this.evaluateWhere(resolvedStage, item);\n } catch {\n return false; // missing field → skip\n }\n });\n }\n\n case \"map\": {\n // System fields that map cannot overwrite (identity fields from AFS nodes)\n const IMMUTABLE_FIELDS = [\"path\", \"kind\"];\n\n const preserveSystemFields = (original: unknown, mapped: Record<string, unknown>): Record<string, unknown> => {\n if (typeof original === \"object\" && original !== null) {\n for (const field of IMMUTABLE_FIELDS) {\n if (field in (original as Record<string, unknown>)) {\n mapped[field] = (original as Record<string, unknown>)[field];\n }\n }\n }\n return mapped;\n };\n\n if (stage.exprMappings) {\n return stream.map((item) => {\n const result: Record<string, unknown> = {};\n for (const [key, expr] of Object.entries(stage.exprMappings!)) {\n result[key] = this.evaluateExpression(expr, item, variables);\n }\n return preserveSystemFields(item, result);\n });\n }\n if (stage.expression) {\n return stream.map((item) => this.evaluateExpression(stage.expression!, item, variables));\n }\n if (stage.mappings) {\n return stream.map((item) => {\n const result: Record<string, unknown> = {};\n for (const [key, field] of Object.entries(stage.mappings!)) {\n result[key] = this.resolveField(item, field);\n }\n return preserveSystemFields(item, result);\n });\n }\n return stream.map((item) => this.resolveField(item, stage.field));\n }\n\n case \"save\": {\n // Runtime @caps enforcement (script-declared caps)\n if (capCheck) capCheck(\"write\", stage.path);\n const capPath = stage.path.split(\"/\").slice(0, 3).join(\"/\");\n if (ctx.caps.size > 0 && !ctx.caps.has(capPath) && !ctx.caps.has(\"*\")) {\n errors.push(`Permission denied: cannot write '${stage.path}'`);\n return stream;\n }\n ctx.world.write(stage.path, stream);\n return [];\n }\n\n case \"publish\": {\n // Runtime @caps enforcement (script-declared caps)\n if (capCheck) capCheck(\"write\", stage.path);\n const capPath = stage.path.split(\"/\").slice(0, 3).join(\"/\");\n if (ctx.caps.size > 0 && !ctx.caps.has(capPath) && !ctx.caps.has(\"*\")) {\n errors.push(`Permission denied: cannot publish '${stage.path}'`);\n return stream;\n }\n ctx.world.publish(stage.path, stream);\n return [];\n }\n\n case \"tee\": {\n // Runtime @caps enforcement (script-declared caps)\n if (capCheck) capCheck(\"write\", stage.path);\n try {\n ctx.world.write(stage.path, [...stream]);\n } catch (e: any) {\n errors.push(`tee side-write failed: ${e.message}`);\n // Main pipeline continues\n }\n return stream;\n }\n\n case \"fanout\": {\n return await this.executeFanout(stage, stream, ctx, errors, variables, budgetCheck, capCheck, initialStream);\n }\n\n case \"output\": {\n if (stage.expression) {\n // Expression mode: evaluate per stream item, emit each result as text\n for (const item of stream) {\n const val = this.evaluateExpression(stage.expression, item, variables);\n const text = val == null ? \"\" : String(val);\n ctx.logger.log(\"output\", \"output\", { message: text, streamSize: stream.length });\n safeOutput(ctx, text, { jobName: this._currentJobName, stageIndex: this._currentStageIndex });\n }\n } else {\n ctx.logger.log(\"output\", \"output\", { message: stage.message, streamSize: stream.length });\n safeOutput(ctx, stage.message, { jobName: this._currentJobName, stageIndex: this._currentStageIndex });\n }\n return stream; // pass-through\n }\n\n case \"input\": {\n ctx.logger.log(\"input\", \"prompt\", { prompt: stage.prompt });\n const response = ctx.world.input\n ? await ctx.world.input(stage.prompt)\n : \"\";\n return [{ prompt: stage.prompt, response }];\n }\n\n case \"count\": {\n return [{ count: stream.length }];\n }\n\n case \"group-by\": {\n const groups = new Map<unknown, unknown[]>();\n for (const item of stream) {\n const key = this.resolveField(item, stage.field);\n if (!groups.has(key)) groups.set(key, []);\n groups.get(key)!.push(item);\n }\n return Array.from(groups.entries()).map(([key, items]) => ({ key, items }));\n }\n\n case \"route\": {\n // Dispatch items to target jobs based on field value\n const buckets = new Map<string, unknown[]>();\n for (const item of stream) {\n const val = String(this.resolveField(item, stage.field) ?? \"\");\n const branch = stage.branches.find(b => b.value === val);\n const targetJob = branch ? branch.targetJob : stage.fallback;\n if (targetJob) {\n if (!buckets.has(targetJob)) buckets.set(targetJob, []);\n buckets.get(targetJob)!.push(item);\n }\n // If no match and no fallback, item is dropped (silently)\n }\n // Execute each target job with its bucket as initial stream\n for (const [jobName, items] of buckets) {\n const compiled = this._jobMap.get(jobName);\n if (!compiled) {\n errors.push(`Route target job '${jobName}' not found`);\n continue;\n }\n await compiled.execute(ctx, items);\n }\n return []; // route is terminal\n }\n\n case \"lookup\": {\n // Left join: read lookup source, build index by joinKey, merge into stream items\n const lookupData = await ctx.world.read(stage.path);\n const index = new Map<string, unknown>();\n for (const item of lookupData) {\n const key = String(this.resolveField(item, stage.joinKey) ?? \"\");\n if (!index.has(key)) index.set(key, item);\n }\n return stream.map((item) => {\n const key = String(this.resolveField(item, stage.joinKey) ?? \"\");\n const match = index.get(key);\n if (match && typeof match === \"object\" && match !== null && typeof item === \"object\" && item !== null) {\n return { ...match, ...item }; // item fields take precedence\n }\n return item; // LEFT JOIN: unmatched items preserved\n });\n }\n\n case \"action\": {\n if (!ctx.world.exec) {\n throw new Error(`WorldInterface.exec not available — cannot execute action '${stage.path}'`);\n }\n\n const hasParams = stage.params && Object.keys(stage.params).length > 0;\n const hasTemplatePath = stage.path.includes(\"${\");\n\n if (stage.relative) {\n // Per-record relative action: resolve path from each record\n const results: unknown[] = [];\n for (const record of stream) {\n // Pre-check budget before each execution\n if (budgetCheck) budgetCheck(\"actions\", 1);\n if (typeof record !== \"object\" || record === null || !(\"path\" in record)) {\n throw new Error(`Relative action '${stage.path}' requires records with a 'path' field`);\n }\n const recordPath = String((record as Record<string, unknown>).path);\n const fullPath = recordPath + \"/.actions/\" + stage.path;\n // Runtime caps enforcement: verify resolved path against @caps (glob-aware)\n if (capCheck) capCheck(\"exec\", fullPath);\n const capPath = fullPath.split(\"/\").slice(0, 3).join(\"/\");\n if (ctx.caps.size > 0 && !ctx.caps.has(capPath) && !ctx.caps.has(\"*\")) {\n throw new Error(`Permission denied: cannot exec '${fullPath}'`);\n }\n const rec = record as Record<string, unknown>;\n // New merge model: if inline params exist, resolve templates and pass ONLY params (no stream merge)\n const resolvedParams = hasParams ? resolveActionParams(stage.params as Record<string, unknown>, rec) : undefined;\n const input = hasParams ? [] : [record];\n const result = await ctx.world.exec(fullPath, input, resolvedParams);\n if (result != null) {\n if (Array.isArray(result)) results.push(...result);\n else results.push(result);\n }\n }\n return results;\n }\n\n // Absolute action — with inline params or template path: per-record execution\n if (hasParams || hasTemplatePath) {\n const results: unknown[] = [];\n const records = stream.length > 0 ? stream : [{}];\n // Path templates resolve from initial stream (trigger event / job context)\n // Params templates resolve from current stream record\n const initialRec = (initialStream && initialStream.length > 0\n && typeof initialStream[0] === \"object\" && initialStream[0] !== null)\n ? initialStream[0] as Record<string, unknown>\n : undefined;\n for (const record of records) {\n if (budgetCheck) budgetCheck(\"actions\", 1);\n const rec = (typeof record === \"object\" && record !== null ? record : {}) as Record<string, unknown>;\n // Path: prefer initial stream record (event context), fall back to current stream record\n const pathRec = initialRec ?? rec;\n const resolvedPath = hasTemplatePath ? resolveTemplatePath(stage.path, pathRec) : stage.path;\n // Caps check on resolved path\n if (capCheck) capCheck(\"exec\", resolvedPath);\n const capPath = resolvedPath.split(\"/\").slice(0, 3).join(\"/\");\n if (ctx.caps.size > 0 && !ctx.caps.has(capPath) && !ctx.caps.has(\"*\")) {\n throw new Error(`Permission denied: cannot exec '${resolvedPath}'`);\n }\n const resolvedParams = hasParams ? resolveActionParams(stage.params as Record<string, unknown>, rec) : undefined;\n const input = hasParams ? [] : [record];\n const result = await ctx.world.exec(resolvedPath, input, resolvedParams);\n if (result != null) {\n if (Array.isArray(result)) results.push(...result);\n else results.push(result);\n }\n }\n return results;\n }\n\n // No params, no template path — passthrough (backward compatible)\n // Runtime @caps enforcement (script-declared caps)\n if (capCheck) capCheck(\"exec\", stage.path);\n const capPath = stage.path.split(\"/\").slice(0, 3).join(\"/\");\n if (ctx.caps.size > 0 && !ctx.caps.has(capPath) && !ctx.caps.has(\"*\")) {\n throw new Error(`Permission denied: cannot exec '${stage.path}'`);\n }\n const result = await ctx.world.exec(stage.path, stream, undefined);\n if (result == null) return [];\n if (!Array.isArray(result)) return [result];\n return result;\n }\n\n default:\n throw new Error(`Unknown stage kind: ${(stage as any).kind}`);\n }\n }\n\n private resolveQueryVars(query: QueryCondition, variables: Map<string, string | number | (string | number)[]>): QueryCondition {\n // For `in` with $variable reference\n if (query.op === \"in\" && typeof query.value === \"string\" && /^\\$[a-zA-Z_]\\w*$/.test(query.value)) {\n const varName = query.value.slice(1);\n if (!variables.has(varName)) {\n throw new Error(`Undefined variable: $${varName}`);\n }\n const val = variables.get(varName)!;\n const value = Array.isArray(val) ? val : [val];\n return { ...query, value };\n }\n if (typeof query.value === \"string\" && /^\\$[a-zA-Z_]\\w*$/.test(query.value)) {\n const varName = query.value.slice(1);\n if (!variables.has(varName)) {\n throw new Error(`Undefined variable: $${varName}`);\n }\n return { ...query, value: variables.get(varName)! };\n }\n return query;\n }\n\n private resolveWhereVars(clause: WhereClause, variables: Map<string, string | number | (string | number)[]>): WhereClause {\n // For `in` operator with $variable reference: resolve to array or wrap single value\n if (clause.op === \"in\" && typeof clause.right === \"string\" && /^\\$[a-zA-Z_]\\w*$/.test(clause.right)) {\n const varName = clause.right.slice(1);\n if (!variables.has(varName)) {\n throw new Error(`Undefined variable: $${varName}`);\n }\n const val = variables.get(varName)!;\n // If the resolved value is an array, use it directly; otherwise wrap as single-element array\n const right = Array.isArray(val) ? val : [val];\n return { ...clause, right };\n }\n // Only resolve $varName pattern ($ followed by identifier chars only)\n if (typeof clause.right === \"string\" && /^\\$[a-zA-Z_]\\w*$/.test(clause.right)) {\n const varName = clause.right.slice(1);\n if (!variables.has(varName)) {\n throw new Error(`Undefined variable: $${varName}`);\n }\n return { ...clause, right: variables.get(varName)! };\n }\n return clause;\n }\n\n private evaluateWhere(clause: WhereClause, item: unknown): boolean {\n const left = this.resolveField(item, clause.left);\n const right = clause.right;\n\n switch (clause.op) {\n case \"==\": return strictEqual(left, right);\n case \"!=\": return !strictEqual(left, right);\n case \"in\": {\n // right should be an array after resolveWhereVars; if not, wrap as single-element array\n const values = Array.isArray(right) ? right : [right];\n return values.some(v => strictEqual(left, v));\n }\n case \">\":\n case \"<\":\n case \">=\":\n case \"<=\": {\n const l = Number(left);\n const r = Number(right);\n // NaN or Infinity in comparisons → reject (safety: non-finite values should not pass guards)\n if (!Number.isFinite(l) || !Number.isFinite(r)) return false;\n if (clause.op === \">\") return l > r;\n if (clause.op === \"<\") return l < r;\n if (clause.op === \">=\") return l >= r;\n return l <= r;\n }\n default: return false;\n }\n }\n\n private resolveField(item: unknown, field: string): unknown {\n const parts = field.split(\".\");\n let current: any = item;\n for (const part of parts) {\n if (current == null) return undefined;\n if (typeof current !== \"object\" || !Object.hasOwn(current, part)) return undefined;\n current = current[part];\n }\n return current;\n }\n\n private evaluateExpression(expr: Expression, item: unknown, variables: Map<string, string | number | (string | number)[]>): unknown {\n switch (expr.kind) {\n case \"literal\":\n return expr.value;\n case \"field_access\":\n return this.resolveField(item, expr.path);\n case \"var_ref\": {\n if (!variables.has(expr.name)) {\n throw new Error(`Undefined variable: $${expr.name}`);\n }\n return variables.get(expr.name)!;\n }\n case \"binary\": {\n const left = this.evaluateExpression(expr.left, item, variables);\n const right = this.evaluateExpression(expr.right, item, variables);\n switch (expr.op) {\n case \"+\":\n // String concat if either side is string\n if (typeof left === \"string\" || typeof right === \"string\") {\n return String(left ?? \"\") + String(right ?? \"\");\n }\n return Number(left) + Number(right);\n case \"-\":\n return Number(left) - Number(right);\n case \"*\":\n return Number(left) * Number(right);\n case \"/\":\n return Number(left) / Number(right);\n default:\n throw new Error(`Unknown operator: ${(expr as any).op}`);\n }\n }\n case \"array_literal\": {\n return expr.elements.map((el) => this.evaluateExpression(el, item, variables));\n }\n case \"object_literal\": {\n const obj: Record<string, unknown> = {};\n for (const [key, valExpr] of Object.entries(expr.properties)) {\n obj[key] = this.evaluateExpression(valExpr, item, variables);\n }\n return obj;\n }\n default:\n throw new Error(`Unknown expression kind: ${(expr as any).kind}`);\n }\n }\n\n private async executeFanout(stage: FanoutExpression, stream: unknown[], ctx: JobContext, errors: string[], variables: Map<string, string | number | (string | number)[]> = new Map(), budgetCheck?: (dim: string, increment: number) => void, capCheck?: (op: CapEntry[\"op\"], path: string) => void, initialStream?: unknown[]): Promise<unknown[]> {\n const results: unknown[][] = [];\n for (const branch of stage.branches) {\n let branchStream = [...stream];\n try {\n for (const branchStage of branch) {\n branchStream = await this.executeStage(branchStage, branchStream, ctx, errors, variables, budgetCheck, capCheck, initialStream);\n }\n results.push(branchStream);\n } catch (e: any) {\n errors.push(`fanout branch failed: ${e.message}`);\n }\n }\n // Return merged results from all successful branches\n return results.flat();\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"compiler.mjs","names":["durationMs","capPath","result"],"sources":["../src/compiler.ts"],"sourcesContent":["import type { Program, JobDeclaration, PipelineStage, WhereClause, FanoutExpression, OutputExpression, TopLevelStatement, QueryCondition, LetStatement, GroupByExpression, ActionExpression, Expression, MapExpression, RouteExpression, LookupExpression, ParamDeclaration, TriggerDeclaration } from \"./ast.js\";\nimport { AshLexer } from \"./lexer.js\";\nimport { AshParser } from \"./parser.js\";\nimport { checkPipelineTypes, checkProhibitedPatterns, checkAnnotations, checkJobCaps, typeErrorsToDiagnostics, compileErrorsToDiagnostics, annotationErrorsToDiagnostics, parseSyntaxError, parseCaps, hasCapFor } from \"./type-checker.js\";\nimport type { AshDiagnostic, CapEntry } from \"./type-checker.js\";\nimport { resolveActionParams, resolveTemplatePath } from \"./template.js\";\n\nexport interface CompileResult {\n program?: CompiledProgram;\n diagnostics: AshDiagnostic[];\n sourceHash?: string;\n}\n\nfunction fnv1aHash(str: string): string {\n let hash = 2166136261;\n for (let i = 0; i < str.length; i++) {\n hash ^= str.charCodeAt(i);\n hash = Math.imul(hash, 16777619) >>> 0;\n }\n return hash.toString(16).padStart(8, \"0\");\n}\n\nfunction collectActions(stages: PipelineStage[]): ActionExpression[] {\n const actions: ActionExpression[] = [];\n for (const stage of stages) {\n if (stage.kind === \"action\") actions.push(stage);\n else if (stage.kind === \"fanout\") {\n for (const branch of stage.branches) actions.push(...collectActions(branch));\n }\n }\n return actions;\n}\n\nexport function compileSource(source: string): CompileResult {\n const diagnostics: AshDiagnostic[] = [];\n const sourceHash = fnv1aHash(source);\n const lexer = new AshLexer();\n const parser = new AshParser();\n const compiler = new AshCompiler();\n\n // Lex\n let tokens;\n try {\n tokens = lexer.tokenize(source);\n } catch (e: any) {\n return { sourceHash, diagnostics: [parseSyntaxError(e.message ?? String(e))] };\n }\n\n // Parse\n let ast;\n try {\n ast = parser.parse(tokens);\n } catch (e: any) {\n return { sourceHash, diagnostics: [parseSyntaxError(e.message ?? String(e))] };\n }\n\n // Type check\n const prohibErrors = checkProhibitedPatterns(ast);\n diagnostics.push(...compileErrorsToDiagnostics(prohibErrors));\n\n for (const job of ast.jobs) {\n const typeErrors = checkPipelineTypes(job.pipeline);\n diagnostics.push(...typeErrorsToDiagnostics(typeErrors));\n\n const annErrors = checkAnnotations(job);\n diagnostics.push(...annotationErrorsToDiagnostics(annErrors));\n\n // @caps: static path security check\n diagnostics.push(...checkJobCaps(job));\n\n // @readonly check: pipeline must not contain save, publish, or tee\n const isReadonly = job.annotations.some(a => a.name === \"readonly\");\n if (isReadonly) {\n for (const stage of job.pipeline) {\n if (stage.kind === \"save\" || stage.kind === \"publish\" || stage.kind === \"tee\" || stage.kind === \"action\") {\n diagnostics.push({\n code: \"ASH_READONLY_VIOLATION\",\n message: `@readonly job '${job.name}' contains '${stage.kind}' which writes data`,\n });\n }\n }\n // Check route targets: @readonly must propagate to route-target jobs\n for (const stage of job.pipeline) {\n if (stage.kind === \"route\") {\n const targetNames = [...stage.branches.map(b => b.targetJob), ...(stage.fallback ? [stage.fallback] : [])];\n for (const targetName of targetNames) {\n const targetJob = ast.jobs.find(j => j.name === targetName);\n if (!targetJob) continue;\n for (const tStage of targetJob.pipeline) {\n if (tStage.kind === \"save\" || tStage.kind === \"publish\" || tStage.kind === \"tee\" || tStage.kind === \"action\") {\n diagnostics.push({\n code: \"ASH_READONLY_VIOLATION\",\n message: `@readonly job '${job.name}' routes to '${targetName}' which contains '${tStage.kind}' (write operation)`,\n });\n break; // one error per target is enough\n }\n }\n }\n }\n }\n }\n }\n\n // Let pipeline restrictions: writes in let bindings are never legitimate\n const WRITE_STAGES = new Set([\"save\", \"publish\", \"tee\", \"action\"]);\n const letStatements = ast.statements.filter((s): s is LetStatement => s.kind === \"let\" && !!s.pipeline);\n for (const letStmt of letStatements) {\n if (letStmt.pipeline) {\n for (const stage of letStmt.pipeline) {\n if (WRITE_STAGES.has(stage.kind)) {\n diagnostics.push({\n code: \"ASH_LET_WRITE\",\n message: `let '${letStmt.name}' pipeline contains '${stage.kind}' — write operations in let bindings are not permitted`,\n });\n }\n }\n }\n }\n\n // Let pipeline pre-approval bypass: let pipelines with find/action execute before @approval checks\n const hasApproval = ast.jobs.some(j => j.annotations.some(a => a.name === \"approval\"));\n if (hasApproval && letStatements.length > 0) {\n const sideEffectLets = letStatements.filter(s =>\n s.pipeline?.some(stage => stage.kind === \"find\" || stage.kind === \"action\"),\n );\n if (sideEffectLets.length > 0) {\n diagnostics.push({\n code: \"ASH_LET_PRE_APPROVAL\",\n severity: \"warning\",\n message: `let bindings (${sideEffectLets.map(s => s.name).join(\", \")}) execute before @approval checks — side effects in let pipelines bypass approval`,\n });\n }\n }\n\n // Param write-gate: $param in where clause before write operation = logic bomb risk\n const paramNames = new Set(ast.statements.filter((s): s is ParamDeclaration => s.kind === \"param\").map(s => s.name));\n if (paramNames.size > 0) {\n for (const job of ast.jobs) {\n const hasWrite = job.pipeline.some(s => WRITE_STAGES.has(s.kind));\n if (!hasWrite) continue;\n for (const stage of job.pipeline) {\n if (stage.kind === \"where\" && typeof stage.right === \"string\" && stage.right.startsWith(\"$\")) {\n const varName = stage.right.slice(1);\n if (paramNames.has(varName)) {\n diagnostics.push({\n code: \"ASH_PARAM_WRITE_GATE\",\n severity: \"warning\",\n message: `Job '${job.name}': param '$${varName}' gates write operations — callers can override param to change behavior`,\n });\n break; // one warning per job\n }\n }\n }\n }\n }\n\n // Mixed annotation deception check: @readonly jobs alongside unrestricted write jobs\n const readonlyJobs = ast.jobs.filter(j => j.annotations.some(a => a.name === \"readonly\"));\n if (readonlyJobs.length > 0 && readonlyJobs.length < ast.jobs.length) {\n const nonReadonly = ast.jobs.filter(j => !j.annotations.some(a => a.name === \"readonly\"));\n const writingJobs = nonReadonly.filter(j =>\n j.pipeline.some(s => s.kind === \"save\" || s.kind === \"publish\" || s.kind === \"tee\" || s.kind === \"action\"),\n );\n if (writingJobs.length > 0) {\n diagnostics.push({\n code: \"ASH_MIXED_SECURITY\",\n severity: \"warning\",\n message: `Program has mixed security posture: ${readonlyJobs.length} @readonly job(s) alongside ${writingJobs.length} unrestricted writing job(s) (${writingJobs.map(j => j.name).join(\", \")}) — this can mask malicious intent`,\n });\n }\n }\n\n // Action hardening: uncapped, amplification (caps+budget gated), cross-provider (caps+budget gated)\n for (const job of ast.jobs) {\n const actions = collectActions(job.pipeline);\n if (actions.length === 0) continue;\n\n const hasCaps = job.annotations.some(a => a.name === \"caps\");\n const hasBudget = job.annotations.some(a => a.name === \"budget\");\n\n // No @caps + action → error (actions require explicit capability declaration)\n if (!hasCaps) {\n diagnostics.push({\n code: \"ASH_UNCAPPED_ACTION\",\n message: `Job '${job.name}' contains action stages but has no @caps — actions require explicit capability declaration`,\n });\n }\n\n // Multiple actions → caps+budget gated\n if (actions.length > 1) {\n if (hasCaps && hasBudget) {\n diagnostics.push({\n code: \"ASH_ACTION_AMPLIFICATION\",\n severity: \"warning\",\n message: `Job '${job.name}' contains ${actions.length} action stages — budget-gated multi-action execution permitted`,\n });\n } else {\n diagnostics.push({\n code: \"ASH_ACTION_AMPLIFICATION\",\n message: `Job '${job.name}' contains ${actions.length} action stages — multi-action jobs require @caps and @budget to prevent amplification attacks`,\n });\n }\n }\n\n // Actions targeting multiple providers → caps+budget gated\n const providers = new Set(actions.filter(a => !a.relative).map(a => a.path.split(\"/\")[1]).filter(Boolean));\n if (providers.size > 1) {\n if (hasCaps && hasBudget) {\n diagnostics.push({\n code: \"ASH_CROSS_PROVIDER_ACTION\",\n severity: \"warning\",\n message: `Job '${job.name}' has actions targeting ${providers.size} providers (${[...providers].join(\", \")}) — budget-gated cross-provider execution permitted`,\n });\n } else {\n diagnostics.push({\n code: \"ASH_CROSS_PROVIDER_ACTION\",\n message: `Job '${job.name}' has actions targeting ${providers.size} providers (${[...providers].join(\", \")}) — cross-provider actions require @caps and @budget`,\n });\n }\n }\n\n // Relative action checks\n const relativeActions = actions.filter(a => a.relative);\n if (relativeActions.length > 0) {\n // Relative action without upstream find → error\n const hasFindUpstream = job.pipeline.some((s, idx) =>\n s.kind === \"find\" && job.pipeline.findIndex(p => p === relativeActions[0]) > idx\n );\n if (!hasFindUpstream) {\n diagnostics.push({\n code: \"ASH_RELATIVE_ACTION_NO_FIND\",\n message: `Job '${job.name}': relative action '${relativeActions[0].path}' has no upstream 'find' — relative actions require a find stage to provide records with paths`,\n });\n }\n\n // Relative action = inherent amplification (1 stage, N execs)\n if (hasCaps && hasBudget) {\n diagnostics.push({\n code: \"ASH_ACTION_AMPLIFICATION\",\n severity: \"warning\",\n message: `Job '${job.name}': relative action '${relativeActions[0].path}' executes per-record — budget-gated amplification permitted`,\n });\n } else if (!hasCaps || !hasBudget) {\n diagnostics.push({\n code: \"ASH_ACTION_AMPLIFICATION\",\n message: `Job '${job.name}': relative action '${relativeActions[0].path}' executes per-record — requires @caps and @budget to prevent amplification`,\n });\n }\n }\n }\n\n // Write operation hardening: publish and tee require @caps\n for (const job of ast.jobs) {\n const hasCaps = job.annotations.some(a => a.name === \"caps\");\n const hasFind = job.pipeline.some(s => s.kind === \"find\" || s.kind === \"lookup\");\n const writeStages = job.pipeline.filter(s => s.kind === \"publish\" || s.kind === \"tee\");\n\n if (writeStages.length > 0 && hasFind && !hasCaps) {\n for (const ws of writeStages) {\n diagnostics.push({\n code: \"ASH_UNCAPPED_WRITE\",\n message: `Job '${job.name}': '${ws.kind}' combined with data reads requires @caps — write operations on external data must declare capabilities`,\n });\n }\n }\n }\n\n // Budget ceiling: reject unreasonably high budget values\n const BUDGET_CEILINGS: Record<string, number> = { actions: 100, writes: 100, records: 10000 };\n for (const job of ast.jobs) {\n const budgetAnn = job.annotations.find(a => a.name === \"budget\");\n if (!budgetAnn) continue;\n for (let i = 0; i < budgetAnn.args.length; i += 2) {\n const dim = budgetAnn.args[i];\n const val = Number(budgetAnn.args[i + 1]);\n if (dim in BUDGET_CEILINGS && val > BUDGET_CEILINGS[dim]) {\n diagnostics.push({\n code: \"ASH_BUDGET_EXCESSIVE\",\n message: `Job '${job.name}': @budget(${dim} ${val}) exceeds ceiling of ${BUDGET_CEILINGS[dim]} — reduce budget or justify with explicit approval`,\n });\n }\n }\n }\n\n // Compile\n const program = compiler.compile(ast);\n return { program, diagnostics, sourceHash };\n}\n\nexport interface OutputEvent {\n kind: \"text\";\n content: string;\n context?: LogContext;\n}\n\nexport interface OutputHandler {\n output(event: OutputEvent): void;\n}\n\nexport interface JobContext {\n world: WorldInterface;\n caps: Set<string>;\n logger: JobLogger;\n output?: OutputHandler;\n}\n\nexport interface WorldInterface {\n read(path: string, query?: QueryCondition): unknown[] | Promise<unknown[]>;\n write(path: string, data: unknown[]): void;\n publish(topic: string, data: unknown[]): void;\n exec?(path: string, input: unknown[], params?: Record<string, unknown>): Promise<unknown[]>;\n input?(prompt: string): string | Promise<string>;\n}\n\nexport interface LogContext {\n programId?: string;\n procId?: string;\n agentId?: string;\n sessionId?: string;\n jobName?: string;\n stageIndex?: number;\n}\n\nexport interface JobLogger {\n log(stage: string, action: string, detail?: unknown): void;\n emit?(level: \"debug\" | \"info\" | \"warn\" | \"error\", message: string, context?: LogContext): void;\n}\n\nexport interface JobResult {\n status: \"ok\" | \"error\" | \"partial\";\n recordCount: number;\n errors: string[];\n}\n\nexport interface StageMetrics {\n name: string;\n index: number;\n inputCount: number;\n outputCount: number;\n durationMs: number;\n error?: string;\n}\n\nexport interface JobReport extends JobResult {\n jobName: string;\n totalDurationMs: number;\n stages: StageMetrics[];\n}\n\nexport interface ProgramReport {\n jobs: JobReport[];\n totalDurationMs: number;\n}\n\nexport interface CompiledJob {\n kind: \"job\";\n name: string;\n trigger?: TriggerDeclaration;\n execute(ctx: JobContext, initialStream?: unknown[]): Promise<JobResult>;\n}\n\nexport interface CompiledOutput {\n kind: \"output\";\n message: string;\n execute(ctx: JobContext): Promise<void>;\n}\n\nexport type CompiledUnit = CompiledJob | CompiledOutput;\n\nexport interface CompiledProgram {\n jobs: CompiledJob[];\n units: CompiledUnit[];\n jobMap: Map<string, CompiledJob>;\n params: Map<string, string | number | (string | number)[]>; // param defaults (can be overridden before execution)\n routeTargets?: Set<string>; // jobs that are ONLY route targets (should not auto-execute as top-level)\n}\n\nfunction safeOutput(ctx: JobContext, content: string, logContext?: LogContext): void {\n if (ctx.output) {\n try {\n ctx.output.output({ kind: \"text\", content, context: logContext });\n } catch {\n // Output fault must not crash pipeline\n }\n }\n safeEmit(ctx.logger, \"info\", content, logContext);\n}\n\nfunction safeEmit(logger: JobLogger, level: \"debug\" | \"info\" | \"warn\" | \"error\", message: string, context?: LogContext): void {\n if (logger.emit) {\n try {\n logger.emit(level, message, context);\n } catch {\n // Log fault must not crash pipeline (INVARIANT: emit failure is silent)\n }\n }\n}\n\n/**\n * Strict equality with boolean coercion only.\n * No string fallback (prevents type confusion like 0 == \"0\").\n * Boolean coercion: true/\"true\" and false/\"false\" are equal.\n */\nfunction strictEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n // Boolean coercion: \"true\" matches true, \"false\" matches false\n if (typeof a === \"boolean\" && typeof b === \"string\") return a === (b === \"true\");\n if (typeof b === \"boolean\" && typeof a === \"string\") return b === (a === \"true\");\n return false;\n}\n\nexport class AshCompiler {\n private _currentJobName?: string;\n private _currentStageIndex?: number;\n private _jobMap = new Map<string, CompiledJob>();\n\n compile(ast: Program): CompiledProgram {\n // Collect param defaults\n const params = new Map<string, string | number | (string | number)[]>();\n for (const stmt of ast.statements) {\n if (stmt.kind === \"param\") {\n params.set(stmt.name, stmt.defaultValue);\n }\n }\n\n // Collect static let bindings (params first, then lets override)\n const variables = new Map<string, string | number | (string | number)[]>(params);\n const runtimeLets: LetStatement[] = [];\n for (const stmt of ast.statements) {\n if (stmt.kind === \"let\") {\n if (stmt.pipeline) {\n runtimeLets.push(stmt);\n } else {\n variables.set(stmt.name, stmt.value);\n }\n }\n }\n\n const units: CompiledUnit[] = ast.statements\n .filter((s): s is Exclude<TopLevelStatement, LetStatement | ParamDeclaration> => s.kind !== \"let\" && s.kind !== \"param\")\n .map((stmt) => this.compileStatement(stmt, variables, runtimeLets));\n const jobs = units.filter((u): u is CompiledJob => u.kind === \"job\");\n const jobMap = new Map<string, CompiledJob>();\n for (const job of jobs) jobMap.set(job.name, job);\n this._jobMap = jobMap;\n\n // Identify route-target-only jobs: jobs referenced by route stages but with no trigger\n const routeTargetNames = new Set<string>();\n const triggeredJobs = new Set<string>();\n for (const job of ast.jobs) {\n if (job.trigger) triggeredJobs.add(job.name);\n for (const stage of job.pipeline) {\n if (stage.kind === \"route\") {\n for (const branch of stage.branches) {\n routeTargetNames.add(branch.targetJob);\n }\n if (stage.fallback) routeTargetNames.add(stage.fallback);\n }\n }\n }\n // Exclude triggered jobs — they have independent execution reasons\n for (const name of triggeredJobs) routeTargetNames.delete(name);\n const routeTargets = routeTargetNames.size > 0 ? routeTargetNames : undefined;\n\n return { jobs, units, jobMap, params, routeTargets };\n }\n\n private compileStatement(stmt: Exclude<TopLevelStatement, LetStatement | ParamDeclaration>, variables: Map<string, string | number | (string | number)[]>, runtimeLets: LetStatement[] = []): CompiledUnit {\n if (stmt.kind === \"output\") {\n return this.compileTopLevelOutput(stmt);\n }\n return this.compileJob(stmt, variables, runtimeLets);\n }\n\n private compileTopLevelOutput(output: OutputExpression): CompiledOutput {\n return {\n kind: \"output\",\n message: output.message,\n execute: async (ctx: JobContext): Promise<void> => {\n ctx.logger.log(\"output\", \"output\", { message: output.message });\n safeOutput(ctx, output.message);\n },\n };\n }\n\n private compileJob(job: JobDeclaration, variables: Map<string, string | number | (string | number)[]> = new Map(), runtimeLets: LetStatement[] = []): CompiledJob {\n const stages = job.pipeline;\n const annotations = job.annotations;\n\n // Extract annotation configs\n const retryAnn = annotations.find(a => a.name === \"retry\");\n const timeoutAnn = annotations.find(a => a.name === \"timeout\");\n const onErrorAnn = annotations.find(a => a.name === \"on_error\");\n const budgetAnn = annotations.find(a => a.name === \"budget\");\n const retryCount = retryAnn ? (retryAnn.args.length > 0 ? Number(retryAnn.args[0]) : 3) : 0;\n const timeoutMs = timeoutAnn ? (timeoutAnn.args.length > 0 ? Number(timeoutAnn.args[0]) : 0) : 0;\n const onErrorStrategy = onErrorAnn?.args[0] as \"skip\" | \"save\" | \"fail\" | undefined;\n const onErrorPath = onErrorStrategy === \"save\" ? onErrorAnn?.args[1] : undefined;\n\n // Parse budget limits\n const budgetLimits: Record<string, number> = {};\n if (budgetAnn) {\n for (let i = 0; i < budgetAnn.args.length; i += 2) {\n budgetLimits[budgetAnn.args[i]] = Number(budgetAnn.args[i + 1]);\n }\n }\n\n // Parse @caps for runtime enforcement (script-declared caps are authoritative)\n const capsAnns = annotations.filter(a => a.name === \"caps\");\n const scriptCaps: CapEntry[] = [];\n for (const ann of capsAnns) {\n if (ann.args.length > 0 && ann.args.length % 2 === 0) {\n scriptCaps.push(...parseCaps(ann));\n }\n }\n\n const self = this;\n\n const runOnce = async (ctx: JobContext, initialStream?: unknown[]): Promise<JobReport> => {\n const errors: string[] = [];\n const jobInitialStream = initialStream ?? [];\n let stream: unknown[] = [...jobInitialStream];\n const stageMetrics: StageMetrics[] = [];\n const jobStart = performance.now();\n const budgetUsed = { actions: 0, writes: 0, records: 0, tokens: 0, cost: 0 };\n const checkBudget = (dim: string, increment: number) => {\n if (!(dim in budgetLimits)) return;\n (budgetUsed as any)[dim] += increment;\n if ((budgetUsed as any)[dim] > budgetLimits[dim]) {\n throw new Error(`budget exceeded: ${dim} used ${(budgetUsed as any)[dim]}, limit ${budgetLimits[dim]}`);\n }\n };\n\n // Runtime caps enforcement: if script declares @caps, enforce them with glob matching.\n // Script-declared caps are the ceiling — ctx.caps (caller-provided) cannot widen them.\n const checkCap = (op: CapEntry[\"op\"], path: string): void => {\n if (scriptCaps.length > 0 && !hasCapFor(scriptCaps, op, path)) {\n throw new Error(`Permission denied: @caps does not allow ${op} '${path}'`);\n }\n };\n\n // Resolve runtime lets\n const runtimeVars = new Map(variables);\n for (const rtLet of runtimeLets) {\n if (rtLet.pipeline) {\n try {\n let rtStream: unknown[] = [];\n for (const stage of rtLet.pipeline) {\n rtStream = await self.executeStage(stage, rtStream, ctx, errors, runtimeVars);\n }\n // Bind the result: if single object with a numeric/string value, extract it\n if (rtStream.length === 1 && typeof rtStream[0] === \"object\" && rtStream[0] !== null) {\n const obj = rtStream[0] as Record<string, unknown>;\n const keys = Object.keys(obj);\n if (keys.length === 1) {\n const val = obj[keys[0]];\n if (typeof val === \"number\" || typeof val === \"string\") {\n runtimeVars.set(rtLet.name, val);\n continue;\n }\n }\n }\n // Fallback: use length or first value\n if (rtStream.length === 1) {\n const v = rtStream[0];\n if (typeof v === \"number\" || typeof v === \"string\") {\n runtimeVars.set(rtLet.name, v);\n } else {\n runtimeVars.set(rtLet.name, rtStream.length);\n }\n } else {\n // Multi-record: try to collect scalar values into an array\n const collected: (string | number)[] = [];\n let allScalar = true;\n for (const item of rtStream) {\n if (typeof item === \"string\" || typeof item === \"number\") {\n collected.push(item);\n } else if (typeof item === \"object\" && item !== null) {\n const keys = Object.keys(item as Record<string, unknown>);\n if (keys.length === 1) {\n const val = (item as Record<string, unknown>)[keys[0]];\n if (typeof val === \"string\" || typeof val === \"number\") {\n collected.push(val);\n continue;\n }\n }\n allScalar = false;\n break;\n } else {\n allScalar = false;\n break;\n }\n }\n runtimeVars.set(rtLet.name, allScalar ? collected : rtStream.length);\n }\n } catch (e: any) {\n errors.push(`Runtime let '${rtLet.name}' failed: ${e.message ?? String(e)}`);\n return { status: \"error\", recordCount: 0, errors, jobName: job.name, totalDurationMs: performance.now() - jobStart, stages: stageMetrics };\n }\n }\n }\n\n for (let i = 0; i < stages.length; i++) {\n const stage = stages[i];\n const inputCount = stream.length;\n const stageStart = performance.now();\n self._currentJobName = job.name;\n self._currentStageIndex = i;\n try {\n // Skip absolute actions on empty downstream stream (not first stage).\n // \"action as source\" (i === 0) still executes — it generates data from nothing.\n // Relative actions already skip naturally (for-of loop over empty stream).\n if (stage.kind === \"action\" && !stage.relative && i > 0 && stream.length === 0) {\n const durationMs = performance.now() - stageStart;\n ctx.logger.log(stage.kind, \"skip\", { reason: \"empty-stream\" });\n safeEmit(ctx.logger, \"debug\", `${stage.kind} skip (empty stream)`, { jobName: job.name, stageIndex: i });\n stageMetrics.push({ name: stage.kind, index: i, inputCount, outputCount: 0, durationMs });\n continue;\n }\n ctx.logger.log(stage.kind, \"enter\", { recordCount: stream.length });\n safeEmit(ctx.logger, \"debug\", `${stage.kind} enter`, { jobName: job.name, stageIndex: i });\n stream = await self.executeStage(stage, stream, ctx, errors, runtimeVars, checkBudget, checkCap, jobInitialStream);\n // Budget checks after stage execution\n // Relative actions are checked per-record inside executeStage; only check absolute actions here\n // Absolute actions with inline params also check per-record inside executeStage\n const hasInlineParams = stage.kind === \"action\" && !stage.relative &&\n stage.params && Object.keys(stage.params).length > 0;\n if (stage.kind === \"action\" && !stage.relative && !hasInlineParams) checkBudget(\"actions\", 1);\n if (stage.kind === \"save\" || stage.kind === \"publish\" || stage.kind === \"tee\") checkBudget(\"writes\", 1);\n checkBudget(\"records\", stream.length);\n const durationMs = performance.now() - stageStart;\n ctx.logger.log(stage.kind, \"exit\", { recordCount: stream.length });\n safeEmit(ctx.logger, \"debug\", `${stage.kind} exit`, { jobName: job.name, stageIndex: i });\n stageMetrics.push({ name: stage.kind, index: i, inputCount, outputCount: stream.length, durationMs });\n } catch (e: any) {\n const durationMs = performance.now() - stageStart;\n const errMsg = e.message ?? String(e);\n errors.push(errMsg);\n\n if (onErrorStrategy === \"skip\") {\n // Skip: log error, continue with remaining stream\n stageMetrics.push({ name: stage.kind, index: i, inputCount, outputCount: stream.length, durationMs, error: errMsg });\n continue;\n } else if (onErrorStrategy === \"save\" && onErrorPath) {\n // Save: write failed items to error path\n try {\n ctx.world.write(onErrorPath, stream.map(item => ({ _error: errMsg, _item: item })));\n } catch {\n errors.push(`Failed to write errors to ${onErrorPath}`);\n }\n stageMetrics.push({ name: stage.kind, index: i, inputCount, outputCount: stream.length, durationMs, error: errMsg });\n continue;\n }\n\n // Default (fail): terminate\n stageMetrics.push({ name: stage.kind, index: i, inputCount, outputCount: stream.length, durationMs, error: errMsg });\n return { status: \"error\", recordCount: stream.length, errors, jobName: job.name, totalDurationMs: performance.now() - jobStart, stages: stageMetrics };\n }\n }\n\n return {\n status: errors.length > 0 ? \"partial\" : \"ok\",\n recordCount: stream.length,\n errors,\n jobName: job.name,\n totalDurationMs: performance.now() - jobStart,\n stages: stageMetrics,\n };\n };\n\n const runWithTimeout = async (ctx: JobContext, initialStream?: unknown[]): Promise<JobResult> => {\n if (timeoutMs <= 0) return runOnce(ctx, initialStream);\n return Promise.race([\n runOnce(ctx, initialStream),\n new Promise<JobResult>((_, reject) =>\n setTimeout(() => reject(new Error(`Timeout: job exceeded ${timeoutMs}ms`)), timeoutMs)\n ),\n ]);\n };\n\n return {\n kind: \"job\",\n name: job.name,\n trigger: job.trigger,\n execute: async (ctx: JobContext, initialStream?: unknown[]): Promise<JobResult> => {\n if (retryCount <= 0 && !retryAnn) {\n // No retry annotation at all\n return runWithTimeout(ctx, initialStream);\n }\n\n const maxAttempts = retryCount > 0 ? retryCount : 1;\n const allErrors: string[] = [];\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n try {\n const result = await runWithTimeout(ctx, initialStream);\n if (result.status !== \"error\") return result;\n allErrors.push(...result.errors);\n // If last attempt, return error\n if (attempt === maxAttempts - 1) return { status: \"error\", recordCount: result.recordCount, errors: allErrors };\n // Backoff (in tests we don't actually wait)\n } catch (e: any) {\n allErrors.push(e.message ?? String(e));\n if (attempt === maxAttempts - 1) {\n return { status: \"error\", recordCount: 0, errors: allErrors };\n }\n }\n }\n\n return { status: \"error\", recordCount: 0, errors: allErrors };\n },\n };\n }\n\n private async executeStage(stage: PipelineStage, stream: unknown[], ctx: JobContext, errors: string[], variables: Map<string, string | number | (string | number)[]> = new Map(), budgetCheck?: (dim: string, increment: number) => void, capCheck?: (op: CapEntry[\"op\"], path: string) => void, initialStream?: unknown[]): Promise<unknown[]> {\n switch (stage.kind) {\n case \"find\": {\n // Resolve template path from stream context (e.g. find /msgs/${data.messageId})\n let findPath = stage.path;\n if (findPath.includes(\"${\") && stream.length > 0) {\n const rec = (typeof stream[0] === \"object\" && stream[0] !== null ? stream[0] : {}) as Record<string, unknown>;\n findPath = resolveTemplatePath(findPath, rec);\n }\n\n // Runtime @caps enforcement (script-declared caps)\n if (capCheck) capCheck(\"read\", findPath);\n const capPath = findPath.split(\"/\").slice(0, 3).join(\"/\");\n if (ctx.caps.size > 0 && !ctx.caps.has(capPath) && !ctx.caps.has(\"*\")) {\n throw new Error(`Permission denied: cannot read '${findPath}'`);\n }\n try {\n const query = stage.query ? this.resolveQueryVars(stage.query, variables) : undefined;\n let result = await ctx.world.read(findPath, query);\n // Fallback: if world.read ignores query, apply in-memory filter\n if (query && result.length > 0) {\n result = result.filter((item) => {\n try {\n return this.evaluateWhere(\n { kind: \"where\", left: query!.field, op: query!.op, right: query!.value },\n item,\n );\n } catch {\n return false;\n }\n });\n }\n return result;\n } catch {\n return []; // non-existent path → empty stream\n }\n }\n\n case \"where\": {\n // Resolve $variable references in where clause\n const resolvedStage = this.resolveWhereVars(stage, variables);\n return stream.filter((item) => {\n try {\n return this.evaluateWhere(resolvedStage, item);\n } catch {\n return false; // missing field → skip\n }\n });\n }\n\n case \"map\": {\n // System fields that map cannot overwrite (identity fields from AFS nodes)\n const IMMUTABLE_FIELDS = [\"path\", \"kind\"];\n\n const preserveSystemFields = (original: unknown, mapped: Record<string, unknown>): Record<string, unknown> => {\n if (typeof original === \"object\" && original !== null) {\n for (const field of IMMUTABLE_FIELDS) {\n if (field in (original as Record<string, unknown>)) {\n mapped[field] = (original as Record<string, unknown>)[field];\n }\n }\n }\n return mapped;\n };\n\n // Initial stream record for field access fallback (trigger event context)\n const initialRec = initialStream?.[0] ?? undefined;\n\n if (stage.exprMappings) {\n return stream.map((item) => {\n const result: Record<string, unknown> = {};\n for (const [key, expr] of Object.entries(stage.exprMappings!)) {\n result[key] = this.evaluateExpression(expr, item, variables, initialRec);\n }\n return preserveSystemFields(item, result);\n });\n }\n if (stage.expression) {\n return stream.map((item) => this.evaluateExpression(stage.expression!, item, variables, initialRec));\n }\n if (stage.mappings) {\n return stream.map((item) => {\n const result: Record<string, unknown> = {};\n for (const [key, field] of Object.entries(stage.mappings!)) {\n result[key] = this.resolveField(item, field);\n }\n return preserveSystemFields(item, result);\n });\n }\n return stream.map((item) => this.resolveField(item, stage.field));\n }\n\n case \"save\": {\n // Runtime @caps enforcement (script-declared caps)\n if (capCheck) capCheck(\"write\", stage.path);\n const capPath = stage.path.split(\"/\").slice(0, 3).join(\"/\");\n if (ctx.caps.size > 0 && !ctx.caps.has(capPath) && !ctx.caps.has(\"*\")) {\n errors.push(`Permission denied: cannot write '${stage.path}'`);\n return stream;\n }\n ctx.world.write(stage.path, stream);\n return [];\n }\n\n case \"publish\": {\n // Runtime @caps enforcement (script-declared caps)\n if (capCheck) capCheck(\"write\", stage.path);\n const capPath = stage.path.split(\"/\").slice(0, 3).join(\"/\");\n if (ctx.caps.size > 0 && !ctx.caps.has(capPath) && !ctx.caps.has(\"*\")) {\n errors.push(`Permission denied: cannot publish '${stage.path}'`);\n return stream;\n }\n ctx.world.publish(stage.path, stream);\n return [];\n }\n\n case \"tee\": {\n // Runtime @caps enforcement (script-declared caps)\n if (capCheck) capCheck(\"write\", stage.path);\n try {\n ctx.world.write(stage.path, [...stream]);\n } catch (e: any) {\n errors.push(`tee side-write failed: ${e.message}`);\n // Main pipeline continues\n }\n return stream;\n }\n\n case \"fanout\": {\n return await this.executeFanout(stage, stream, ctx, errors, variables, budgetCheck, capCheck, initialStream);\n }\n\n case \"output\": {\n if (stage.expression) {\n // Expression mode: evaluate per stream item, emit each result as text\n for (const item of stream) {\n const val = this.evaluateExpression(stage.expression, item, variables);\n const text = val == null ? \"\" : String(val);\n ctx.logger.log(\"output\", \"output\", { message: text, streamSize: stream.length });\n safeOutput(ctx, text, { jobName: this._currentJobName, stageIndex: this._currentStageIndex });\n }\n } else {\n ctx.logger.log(\"output\", \"output\", { message: stage.message, streamSize: stream.length });\n safeOutput(ctx, stage.message, { jobName: this._currentJobName, stageIndex: this._currentStageIndex });\n }\n return stream; // pass-through\n }\n\n case \"input\": {\n ctx.logger.log(\"input\", \"prompt\", { prompt: stage.prompt });\n const response = ctx.world.input\n ? await ctx.world.input(stage.prompt)\n : \"\";\n return [{ prompt: stage.prompt, response }];\n }\n\n case \"count\": {\n return [{ count: stream.length }];\n }\n\n case \"group-by\": {\n const groups = new Map<unknown, unknown[]>();\n for (const item of stream) {\n const key = this.resolveField(item, stage.field);\n if (!groups.has(key)) groups.set(key, []);\n groups.get(key)!.push(item);\n }\n return Array.from(groups.entries()).map(([key, items]) => ({ key, items }));\n }\n\n case \"route\": {\n // Dispatch items to target jobs based on field value\n const buckets = new Map<string, unknown[]>();\n for (const item of stream) {\n const val = String(this.resolveField(item, stage.field) ?? \"\");\n const branch = stage.branches.find(b => b.value === val);\n const targetJob = branch ? branch.targetJob : stage.fallback;\n if (targetJob) {\n if (!buckets.has(targetJob)) buckets.set(targetJob, []);\n buckets.get(targetJob)!.push(item);\n }\n // If no match and no fallback, item is dropped (silently)\n }\n // Execute each target job with its bucket as initial stream\n for (const [jobName, items] of buckets) {\n const compiled = this._jobMap.get(jobName);\n if (!compiled) {\n errors.push(`Route target job '${jobName}' not found`);\n continue;\n }\n await compiled.execute(ctx, items);\n }\n return []; // route is terminal\n }\n\n case \"lookup\": {\n // Left join: read lookup source, build index by joinKey, merge into stream items\n const lookupData = await ctx.world.read(stage.path);\n const index = new Map<string, unknown>();\n for (const item of lookupData) {\n const key = String(this.resolveField(item, stage.joinKey) ?? \"\");\n if (!index.has(key)) index.set(key, item);\n }\n return stream.map((item) => {\n const key = String(this.resolveField(item, stage.joinKey) ?? \"\");\n const match = index.get(key);\n if (match && typeof match === \"object\" && match !== null && typeof item === \"object\" && item !== null) {\n return { ...match, ...item }; // item fields take precedence\n }\n return item; // LEFT JOIN: unmatched items preserved\n });\n }\n\n case \"action\": {\n if (!ctx.world.exec) {\n throw new Error(`WorldInterface.exec not available — cannot execute action '${stage.path}'`);\n }\n\n const hasParams = stage.params && Object.keys(stage.params).length > 0;\n const hasTemplatePath = stage.path.includes(\"${\");\n\n if (stage.relative) {\n // Per-record relative action: resolve path from each record\n const results: unknown[] = [];\n for (const record of stream) {\n // Pre-check budget before each execution\n if (budgetCheck) budgetCheck(\"actions\", 1);\n if (typeof record !== \"object\" || record === null || !(\"path\" in record)) {\n throw new Error(`Relative action '${stage.path}' requires records with a 'path' field`);\n }\n const recordPath = String((record as Record<string, unknown>).path);\n const fullPath = recordPath + \"/.actions/\" + stage.path;\n // Runtime caps enforcement: verify resolved path against @caps (glob-aware)\n if (capCheck) capCheck(\"exec\", fullPath);\n const capPath = fullPath.split(\"/\").slice(0, 3).join(\"/\");\n if (ctx.caps.size > 0 && !ctx.caps.has(capPath) && !ctx.caps.has(\"*\")) {\n throw new Error(`Permission denied: cannot exec '${fullPath}'`);\n }\n const rec = record as Record<string, unknown>;\n // New merge model: if inline params exist, resolve templates and pass ONLY params (no stream merge)\n const resolvedParams = hasParams ? resolveActionParams(stage.params as Record<string, unknown>, rec) : undefined;\n const input = hasParams ? [] : [record];\n const result = await ctx.world.exec(fullPath, input, resolvedParams);\n if (result != null) {\n if (Array.isArray(result)) results.push(...result);\n else results.push(result);\n }\n }\n return results;\n }\n\n // Absolute action — with inline params or template path: per-record execution\n if (hasParams || hasTemplatePath) {\n const results: unknown[] = [];\n const records = stream.length > 0 ? stream : [{}];\n // Path templates resolve from initial stream (trigger event / job context)\n // Params templates resolve from current stream record\n const initialRec = (initialStream && initialStream.length > 0\n && typeof initialStream[0] === \"object\" && initialStream[0] !== null)\n ? initialStream[0] as Record<string, unknown>\n : undefined;\n for (const record of records) {\n if (budgetCheck) budgetCheck(\"actions\", 1);\n const rec = (typeof record === \"object\" && record !== null ? record : {}) as Record<string, unknown>;\n // Path: prefer initial stream record (event context), fall back to current stream record\n const pathRec = initialRec ?? rec;\n const resolvedPath = hasTemplatePath ? resolveTemplatePath(stage.path, pathRec) : stage.path;\n // Caps check on resolved path\n if (capCheck) capCheck(\"exec\", resolvedPath);\n const capPath = resolvedPath.split(\"/\").slice(0, 3).join(\"/\");\n if (ctx.caps.size > 0 && !ctx.caps.has(capPath) && !ctx.caps.has(\"*\")) {\n throw new Error(`Permission denied: cannot exec '${resolvedPath}'`);\n }\n const resolvedParams = hasParams ? resolveActionParams(stage.params as Record<string, unknown>, rec) : undefined;\n const input = hasParams ? [] : [record];\n const result = await ctx.world.exec(resolvedPath, input, resolvedParams);\n if (result != null) {\n if (Array.isArray(result)) results.push(...result);\n else results.push(result);\n }\n }\n return results;\n }\n\n // No params, no template path — passthrough (backward compatible)\n // Runtime @caps enforcement (script-declared caps)\n if (capCheck) capCheck(\"exec\", stage.path);\n const capPath = stage.path.split(\"/\").slice(0, 3).join(\"/\");\n if (ctx.caps.size > 0 && !ctx.caps.has(capPath) && !ctx.caps.has(\"*\")) {\n throw new Error(`Permission denied: cannot exec '${stage.path}'`);\n }\n const result = await ctx.world.exec(stage.path, stream, undefined);\n if (result == null) return [];\n if (!Array.isArray(result)) return [result];\n return result;\n }\n\n default:\n throw new Error(`Unknown stage kind: ${(stage as any).kind}`);\n }\n }\n\n private resolveQueryVars(query: QueryCondition, variables: Map<string, string | number | (string | number)[]>): QueryCondition {\n // For `in` with $variable reference\n if (query.op === \"in\" && typeof query.value === \"string\" && /^\\$[a-zA-Z_]\\w*$/.test(query.value)) {\n const varName = query.value.slice(1);\n if (!variables.has(varName)) {\n throw new Error(`Undefined variable: $${varName}`);\n }\n const val = variables.get(varName)!;\n const value = Array.isArray(val) ? val : [val];\n return { ...query, value };\n }\n if (typeof query.value === \"string\" && /^\\$[a-zA-Z_]\\w*$/.test(query.value)) {\n const varName = query.value.slice(1);\n if (!variables.has(varName)) {\n throw new Error(`Undefined variable: $${varName}`);\n }\n return { ...query, value: variables.get(varName)! };\n }\n return query;\n }\n\n private resolveWhereVars(clause: WhereClause, variables: Map<string, string | number | (string | number)[]>): WhereClause {\n // For `in` operator with $variable reference: resolve to array or wrap single value\n if (clause.op === \"in\" && typeof clause.right === \"string\" && /^\\$[a-zA-Z_]\\w*$/.test(clause.right)) {\n const varName = clause.right.slice(1);\n if (!variables.has(varName)) {\n throw new Error(`Undefined variable: $${varName}`);\n }\n const val = variables.get(varName)!;\n // If the resolved value is an array, use it directly; otherwise wrap as single-element array\n const right = Array.isArray(val) ? val : [val];\n return { ...clause, right };\n }\n // Only resolve $varName pattern ($ followed by identifier chars only)\n if (typeof clause.right === \"string\" && /^\\$[a-zA-Z_]\\w*$/.test(clause.right)) {\n const varName = clause.right.slice(1);\n if (!variables.has(varName)) {\n throw new Error(`Undefined variable: $${varName}`);\n }\n return { ...clause, right: variables.get(varName)! };\n }\n return clause;\n }\n\n private evaluateWhere(clause: WhereClause, item: unknown): boolean {\n const left = this.resolveField(item, clause.left);\n const right = clause.right;\n\n switch (clause.op) {\n case \"==\": return strictEqual(left, right);\n case \"!=\": return !strictEqual(left, right);\n case \"in\": {\n // right should be an array after resolveWhereVars; if not, wrap as single-element array\n const values = Array.isArray(right) ? right : [right];\n return values.some(v => strictEqual(left, v));\n }\n case \">\":\n case \"<\":\n case \">=\":\n case \"<=\": {\n const l = Number(left);\n const r = Number(right);\n // NaN or Infinity in comparisons → reject (safety: non-finite values should not pass guards)\n if (!Number.isFinite(l) || !Number.isFinite(r)) return false;\n if (clause.op === \">\") return l > r;\n if (clause.op === \"<\") return l < r;\n if (clause.op === \">=\") return l >= r;\n return l <= r;\n }\n default: return false;\n }\n }\n\n private resolveField(item: unknown, field: string): unknown {\n const parts = field.split(\".\");\n let current: any = item;\n for (const part of parts) {\n if (current == null) return undefined;\n if (typeof current !== \"object\" || !Object.hasOwn(current, part)) return undefined;\n current = current[part];\n }\n return current;\n }\n\n private evaluateExpression(expr: Expression, item: unknown, variables: Map<string, string | number | (string | number)[]>, fallbackItem?: unknown): unknown {\n switch (expr.kind) {\n case \"literal\":\n return expr.value;\n case \"field_access\": {\n const value = this.resolveField(item, expr.path);\n // Fallback: if the top-level field is not in the current record,\n // try the initial stream record (trigger event context).\n // This allows `data.replyTo` to resolve from the trigger event\n // even after an action stage replaces the stream.\n if (value === undefined && fallbackItem != null) {\n const topField = expr.path.split(\".\")[0];\n if (typeof item !== \"object\" || item === null || !Object.hasOwn(item as object, topField!)) {\n return this.resolveField(fallbackItem, expr.path);\n }\n }\n return value;\n }\n case \"var_ref\": {\n if (!variables.has(expr.name)) {\n throw new Error(`Undefined variable: $${expr.name}`);\n }\n return variables.get(expr.name)!;\n }\n case \"binary\": {\n const left = this.evaluateExpression(expr.left, item, variables, fallbackItem);\n const right = this.evaluateExpression(expr.right, item, variables, fallbackItem);\n switch (expr.op) {\n case \"+\":\n // String concat if either side is string\n if (typeof left === \"string\" || typeof right === \"string\") {\n return String(left ?? \"\") + String(right ?? \"\");\n }\n return Number(left) + Number(right);\n case \"-\":\n return Number(left) - Number(right);\n case \"*\":\n return Number(left) * Number(right);\n case \"/\":\n return Number(left) / Number(right);\n default:\n throw new Error(`Unknown operator: ${(expr as any).op}`);\n }\n }\n case \"array_literal\": {\n return expr.elements.map((el) => this.evaluateExpression(el, item, variables, fallbackItem));\n }\n case \"object_literal\": {\n const obj: Record<string, unknown> = {};\n for (const [key, valExpr] of Object.entries(expr.properties)) {\n obj[key] = this.evaluateExpression(valExpr, item, variables, fallbackItem);\n }\n return obj;\n }\n default:\n throw new Error(`Unknown expression kind: ${(expr as any).kind}`);\n }\n }\n\n private async executeFanout(stage: FanoutExpression, stream: unknown[], ctx: JobContext, errors: string[], variables: Map<string, string | number | (string | number)[]> = new Map(), budgetCheck?: (dim: string, increment: number) => void, capCheck?: (op: CapEntry[\"op\"], path: string) => void, initialStream?: unknown[]): Promise<unknown[]> {\n const results: unknown[][] = [];\n for (const branch of stage.branches) {\n let branchStream = [...stream];\n try {\n for (const branchStage of branch) {\n branchStream = await this.executeStage(branchStage, branchStream, ctx, errors, variables, budgetCheck, capCheck, initialStream);\n }\n results.push(branchStream);\n } catch (e: any) {\n errors.push(`fanout branch failed: ${e.message}`);\n }\n }\n // Return merged results from all successful branches\n return results.flat();\n }\n}\n"],"mappings":"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"}
|
package/dist/parser.cjs
CHANGED
|
@@ -446,7 +446,7 @@ var AshParser = class AshParser {
|
|
|
446
446
|
const exprMappings = Object.create(null);
|
|
447
447
|
const seenExprKeys = /* @__PURE__ */ new Set();
|
|
448
448
|
while (!this.isAtEnd() && this.peek().type !== "RBRACE") {
|
|
449
|
-
const keyToken = this.
|
|
449
|
+
const keyToken = this.expectKey("Expected key in map expression");
|
|
450
450
|
if (seenExprKeys.has(keyToken.value)) throw new Error(`Duplicate map key '${keyToken.value}' at line ${keyToken.line}, column ${keyToken.column}`);
|
|
451
451
|
seenExprKeys.add(keyToken.value);
|
|
452
452
|
this.expect("COLON", "Expected ':' after key in map expression");
|
|
@@ -569,7 +569,7 @@ var AshParser = class AshParser {
|
|
|
569
569
|
this.skipNewlines();
|
|
570
570
|
const properties = {};
|
|
571
571
|
while (!this.isAtEnd() && this.peek().type !== "RBRACE") {
|
|
572
|
-
const keyToken = this.
|
|
572
|
+
const keyToken = this.expectKey("Expected property name in object literal");
|
|
573
573
|
this.expect("COLON", "Expected ':' after property name");
|
|
574
574
|
properties[keyToken.value] = this.parseExpression();
|
|
575
575
|
this.skipNewlines();
|
|
@@ -790,6 +790,36 @@ var AshParser = class AshParser {
|
|
|
790
790
|
advance() {
|
|
791
791
|
return this.tokens[this.pos++];
|
|
792
792
|
}
|
|
793
|
+
/** Keywords that are valid as object/map keys (all ASH keywords). */
|
|
794
|
+
static KEYWORD_TYPES = new Set([
|
|
795
|
+
"JOB",
|
|
796
|
+
"FIND",
|
|
797
|
+
"WHERE",
|
|
798
|
+
"MAP",
|
|
799
|
+
"COUNT",
|
|
800
|
+
"SAVE",
|
|
801
|
+
"PUBLISH",
|
|
802
|
+
"TEE",
|
|
803
|
+
"FANOUT",
|
|
804
|
+
"ACTION",
|
|
805
|
+
"LET",
|
|
806
|
+
"PARAM",
|
|
807
|
+
"OUTPUT",
|
|
808
|
+
"ON",
|
|
809
|
+
"IN",
|
|
810
|
+
"EXEC",
|
|
811
|
+
"DELETE"
|
|
812
|
+
]);
|
|
813
|
+
/**
|
|
814
|
+
* Expect an identifier or keyword token to use as an object/map key.
|
|
815
|
+
* Keywords like `job`, `action`, `find` etc. are valid key names.
|
|
816
|
+
*/
|
|
817
|
+
expectKey(message) {
|
|
818
|
+
if (this.isAtEnd()) throw new Error(message + " (unexpected EOF)");
|
|
819
|
+
const t = this.peek();
|
|
820
|
+
if (t.type === "IDENTIFIER" || AshParser.KEYWORD_TYPES.has(t.type)) return this.advance();
|
|
821
|
+
throw new Error(`${message}, got ${t.type} at line ${t.line}, column ${t.column}`);
|
|
822
|
+
}
|
|
793
823
|
expect(type, message) {
|
|
794
824
|
if (this.isAtEnd()) throw new Error(message + " (unexpected EOF)");
|
|
795
825
|
const t = this.peek();
|
package/dist/parser.d.cts
CHANGED
|
@@ -31,6 +31,13 @@ declare class AshParser {
|
|
|
31
31
|
private parseJsonValue;
|
|
32
32
|
private peek;
|
|
33
33
|
private advance;
|
|
34
|
+
/** Keywords that are valid as object/map keys (all ASH keywords). */
|
|
35
|
+
private static readonly KEYWORD_TYPES;
|
|
36
|
+
/**
|
|
37
|
+
* Expect an identifier or keyword token to use as an object/map key.
|
|
38
|
+
* Keywords like `job`, `action`, `find` etc. are valid key names.
|
|
39
|
+
*/
|
|
40
|
+
private expectKey;
|
|
34
41
|
private expect;
|
|
35
42
|
private isAtEnd;
|
|
36
43
|
private skipNewlines;
|
package/dist/parser.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parser.d.cts","names":[],"sources":["../src/parser.ts"],"mappings":";;;;cAca,SAAA;EAAA,QACH,MAAA;EAAA,QACA,GAAA;EAAA,QAEA,QAAA;EAAA,QACA,UAAA;EAAA,wBACgB,iBAAA;EAExB,KAAA,CAAM,MAAA,EAAQ,KAAA,KAAU,OAAA;EAAA,QA+ChB,UAAA;EAAA,wBAqCgB,iBAAA;EAAA,QAEhB,QAAA;EAAA,QAuCA,gBAAA;EAAA,QAkBA,gBAAA;EAAA,QA+BA,QAAA;EAAA,QAuEA,aAAA;EAAA,QA2BA,UAAA;EAAA,QAqFA,UAAA;EAAA,QA+EA,gBAAA;EAAA,QAWA,YAAA;EAAA,QAuFA,eAAA;EAAA,QAUA,SAAA;EAAA,QAUA,WAAA;EAAA,QAmFA,WAAA;EAAA,QA+DA,UAAA;EAAA,QAmDA,WAAA;EAAA,QAeA,WAAA;EA/TA;EAAA,QA4VA,cAAA;EAAA,QAmEA,IAAA;EAAA,QAIA,OAAA;EAAA,
|
|
1
|
+
{"version":3,"file":"parser.d.cts","names":[],"sources":["../src/parser.ts"],"mappings":";;;;cAca,SAAA;EAAA,QACH,MAAA;EAAA,QACA,GAAA;EAAA,QAEA,QAAA;EAAA,QACA,UAAA;EAAA,wBACgB,iBAAA;EAExB,KAAA,CAAM,MAAA,EAAQ,KAAA,KAAU,OAAA;EAAA,QA+ChB,UAAA;EAAA,wBAqCgB,iBAAA;EAAA,QAEhB,QAAA;EAAA,QAuCA,gBAAA;EAAA,QAkBA,gBAAA;EAAA,QA+BA,QAAA;EAAA,QAuEA,aAAA;EAAA,QA2BA,UAAA;EAAA,QAqFA,UAAA;EAAA,QA+EA,gBAAA;EAAA,QAWA,YAAA;EAAA,QAuFA,eAAA;EAAA,QAUA,SAAA;EAAA,QAUA,WAAA;EAAA,QAmFA,WAAA;EAAA,QA+DA,UAAA;EAAA,QAmDA,WAAA;EAAA,QAeA,WAAA;EA/TA;EAAA,QA4VA,cAAA;EAAA,QAmEA,IAAA;EAAA,QAIA,OAAA;EArOA;EAAA,wBA0OgB,aAAA;EAxHhB;;;;EAAA,QAiIA,SAAA;EAAA,QASA,MAAA;EAAA,QASA,OAAA;EAAA,QAIA,YAAA;AAAA"}
|
package/dist/parser.d.mts
CHANGED
|
@@ -31,6 +31,13 @@ declare class AshParser {
|
|
|
31
31
|
private parseJsonValue;
|
|
32
32
|
private peek;
|
|
33
33
|
private advance;
|
|
34
|
+
/** Keywords that are valid as object/map keys (all ASH keywords). */
|
|
35
|
+
private static readonly KEYWORD_TYPES;
|
|
36
|
+
/**
|
|
37
|
+
* Expect an identifier or keyword token to use as an object/map key.
|
|
38
|
+
* Keywords like `job`, `action`, `find` etc. are valid key names.
|
|
39
|
+
*/
|
|
40
|
+
private expectKey;
|
|
34
41
|
private expect;
|
|
35
42
|
private isAtEnd;
|
|
36
43
|
private skipNewlines;
|
package/dist/parser.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parser.d.mts","names":[],"sources":["../src/parser.ts"],"mappings":";;;;cAca,SAAA;EAAA,QACH,MAAA;EAAA,QACA,GAAA;EAAA,QAEA,QAAA;EAAA,QACA,UAAA;EAAA,wBACgB,iBAAA;EAExB,KAAA,CAAM,MAAA,EAAQ,KAAA,KAAU,OAAA;EAAA,QA+ChB,UAAA;EAAA,wBAqCgB,iBAAA;EAAA,QAEhB,QAAA;EAAA,QAuCA,gBAAA;EAAA,QAkBA,gBAAA;EAAA,QA+BA,QAAA;EAAA,QAuEA,aAAA;EAAA,QA2BA,UAAA;EAAA,QAqFA,UAAA;EAAA,QA+EA,gBAAA;EAAA,QAWA,YAAA;EAAA,QAuFA,eAAA;EAAA,QAUA,SAAA;EAAA,QAUA,WAAA;EAAA,QAmFA,WAAA;EAAA,QA+DA,UAAA;EAAA,QAmDA,WAAA;EAAA,QAeA,WAAA;EA/TA;EAAA,QA4VA,cAAA;EAAA,QAmEA,IAAA;EAAA,QAIA,OAAA;EAAA,
|
|
1
|
+
{"version":3,"file":"parser.d.mts","names":[],"sources":["../src/parser.ts"],"mappings":";;;;cAca,SAAA;EAAA,QACH,MAAA;EAAA,QACA,GAAA;EAAA,QAEA,QAAA;EAAA,QACA,UAAA;EAAA,wBACgB,iBAAA;EAExB,KAAA,CAAM,MAAA,EAAQ,KAAA,KAAU,OAAA;EAAA,QA+ChB,UAAA;EAAA,wBAqCgB,iBAAA;EAAA,QAEhB,QAAA;EAAA,QAuCA,gBAAA;EAAA,QAkBA,gBAAA;EAAA,QA+BA,QAAA;EAAA,QAuEA,aAAA;EAAA,QA2BA,UAAA;EAAA,QAqFA,UAAA;EAAA,QA+EA,gBAAA;EAAA,QAWA,YAAA;EAAA,QAuFA,eAAA;EAAA,QAUA,SAAA;EAAA,QAUA,WAAA;EAAA,QAmFA,WAAA;EAAA,QA+DA,UAAA;EAAA,QAmDA,WAAA;EAAA,QAeA,WAAA;EA/TA;EAAA,QA4VA,cAAA;EAAA,QAmEA,IAAA;EAAA,QAIA,OAAA;EArOA;EAAA,wBA0OgB,aAAA;EAxHhB;;;;EAAA,QAiIA,SAAA;EAAA,QASA,MAAA;EAAA,QASA,OAAA;EAAA,QAIA,YAAA;AAAA"}
|
package/dist/parser.mjs
CHANGED
|
@@ -445,7 +445,7 @@ var AshParser = class AshParser {
|
|
|
445
445
|
const exprMappings = Object.create(null);
|
|
446
446
|
const seenExprKeys = /* @__PURE__ */ new Set();
|
|
447
447
|
while (!this.isAtEnd() && this.peek().type !== "RBRACE") {
|
|
448
|
-
const keyToken = this.
|
|
448
|
+
const keyToken = this.expectKey("Expected key in map expression");
|
|
449
449
|
if (seenExprKeys.has(keyToken.value)) throw new Error(`Duplicate map key '${keyToken.value}' at line ${keyToken.line}, column ${keyToken.column}`);
|
|
450
450
|
seenExprKeys.add(keyToken.value);
|
|
451
451
|
this.expect("COLON", "Expected ':' after key in map expression");
|
|
@@ -568,7 +568,7 @@ var AshParser = class AshParser {
|
|
|
568
568
|
this.skipNewlines();
|
|
569
569
|
const properties = {};
|
|
570
570
|
while (!this.isAtEnd() && this.peek().type !== "RBRACE") {
|
|
571
|
-
const keyToken = this.
|
|
571
|
+
const keyToken = this.expectKey("Expected property name in object literal");
|
|
572
572
|
this.expect("COLON", "Expected ':' after property name");
|
|
573
573
|
properties[keyToken.value] = this.parseExpression();
|
|
574
574
|
this.skipNewlines();
|
|
@@ -789,6 +789,36 @@ var AshParser = class AshParser {
|
|
|
789
789
|
advance() {
|
|
790
790
|
return this.tokens[this.pos++];
|
|
791
791
|
}
|
|
792
|
+
/** Keywords that are valid as object/map keys (all ASH keywords). */
|
|
793
|
+
static KEYWORD_TYPES = new Set([
|
|
794
|
+
"JOB",
|
|
795
|
+
"FIND",
|
|
796
|
+
"WHERE",
|
|
797
|
+
"MAP",
|
|
798
|
+
"COUNT",
|
|
799
|
+
"SAVE",
|
|
800
|
+
"PUBLISH",
|
|
801
|
+
"TEE",
|
|
802
|
+
"FANOUT",
|
|
803
|
+
"ACTION",
|
|
804
|
+
"LET",
|
|
805
|
+
"PARAM",
|
|
806
|
+
"OUTPUT",
|
|
807
|
+
"ON",
|
|
808
|
+
"IN",
|
|
809
|
+
"EXEC",
|
|
810
|
+
"DELETE"
|
|
811
|
+
]);
|
|
812
|
+
/**
|
|
813
|
+
* Expect an identifier or keyword token to use as an object/map key.
|
|
814
|
+
* Keywords like `job`, `action`, `find` etc. are valid key names.
|
|
815
|
+
*/
|
|
816
|
+
expectKey(message) {
|
|
817
|
+
if (this.isAtEnd()) throw new Error(message + " (unexpected EOF)");
|
|
818
|
+
const t = this.peek();
|
|
819
|
+
if (t.type === "IDENTIFIER" || AshParser.KEYWORD_TYPES.has(t.type)) return this.advance();
|
|
820
|
+
throw new Error(`${message}, got ${t.type} at line ${t.line}, column ${t.column}`);
|
|
821
|
+
}
|
|
792
822
|
expect(type, message) {
|
|
793
823
|
if (this.isAtEnd()) throw new Error(message + " (unexpected EOF)");
|
|
794
824
|
const t = this.peek();
|
package/dist/parser.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parser.mjs","names":[],"sources":["../src/parser.ts"],"sourcesContent":["import type { Token, TokenType } from \"./lexer.js\";\nimport type { Program, JobDeclaration, PipelineStage, Annotation, WhereClause, QueryCondition, TopLevelStatement, LetStatement, CountExpression, GroupByExpression, ActionExpression, Expression, MapExpression, RouteExpression, RouteBranch, LookupExpression, ParamDeclaration, TriggerDeclaration } from \"./ast.js\";\n\n/** Annotation names that are script-level: propagate to all jobs when declared before any statement. */\nconst SCRIPT_LEVEL_ANNOTATIONS = new Set([\"caps\", \"budget\"]);\n\n/** Merge script-level annotations with job-specific ones. Job overrides script-level by name. */\nfunction mergeAnnotations(script: Annotation[], job: Annotation[]): Annotation[] {\n if (script.length === 0) return job;\n if (job.length === 0) return [...script];\n const jobNames = new Set(job.map(a => a.name));\n return [...script.filter(a => !jobNames.has(a.name)), ...job];\n}\n\nexport class AshParser {\n private tokens: Token[] = [];\n private pos = 0;\n\n private letNames = new Set<string>();\n private paramNames = new Set<string>();\n private static readonly RESERVED_KEYWORDS = new Set([\"job\", \"find\", \"where\", \"map\", \"save\", \"publish\", \"tee\", \"fanout\", \"input\", \"output\", \"let\", \"action\", \"route\", \"lookup\", \"param\", \"on\", \"in\"]);\n\n parse(tokens: Token[]): Program {\n this.tokens = tokens;\n this.pos = 0;\n this.letNames = new Set();\n this.paramNames = new Set();\n const statements: TopLevelStatement[] = [];\n\n this.skipNewlines();\n\n // Collect initial annotations (before any statement).\n // Split into script-level (caps, budget → propagate to all jobs) and first-job-specific.\n const initialAnnotations = this.parseAnnotations();\n const scriptAnnotations = initialAnnotations.filter(a => SCRIPT_LEVEL_ANNOTATIONS.has(a.name));\n const firstJobOnly = initialAnnotations.filter(a => !SCRIPT_LEVEL_ANNOTATIONS.has(a.name));\n let firstStatement = true;\n\n while (!this.isAtEnd()) {\n const jobAnnotations = this.parseAnnotations();\n if (this.isAtEnd()) break;\n\n const t = this.peek();\n if (t.type === \"JOB\") {\n const extra = firstStatement ? [...firstJobOnly, ...jobAnnotations] : jobAnnotations;\n const merged = mergeAnnotations(scriptAnnotations, extra);\n firstStatement = false;\n statements.push(this.parseJob(merged));\n } else if (t.type === \"OUTPUT\" && jobAnnotations.length === 0) {\n firstStatement = false;\n this.advance(); // output\n const msg = this.expect(\"STRING\", \"Expected string after 'output'\");\n statements.push({ kind: \"output\", message: msg.value });\n } else if (t.type === \"LET\" && jobAnnotations.length === 0) {\n firstStatement = false;\n statements.push(this.parseLet());\n } else if (t.type === \"PARAM\" && jobAnnotations.length === 0) {\n firstStatement = false;\n statements.push(this.parseParam());\n } else {\n throw new Error(`Expected 'job', 'output', 'let', or 'param' at top level, got ${t.type} at line ${t.line}, column ${t.column}`);\n }\n this.skipNewlines();\n }\n\n const jobs = statements.filter((s): s is JobDeclaration => s.kind === \"job\");\n return { statements, jobs };\n }\n\n private parseParam(): ParamDeclaration {\n const paramToken = this.advance(); // param\n if (this.isAtEnd()) {\n throw new Error(`Expected parameter name after 'param' at line ${paramToken.line}, column ${paramToken.column}`);\n }\n const nameToken = this.peek();\n if (nameToken.type !== \"IDENTIFIER\") {\n throw new Error(`Cannot use reserved keyword '${nameToken.value}' as param name at line ${nameToken.line}, column ${nameToken.column}`);\n }\n this.advance();\n if (AshParser.RESERVED_KEYWORDS.has(nameToken.value)) {\n throw new Error(`Cannot use reserved keyword '${nameToken.value}' as param name at line ${nameToken.line}, column ${nameToken.column}`);\n }\n if (this.paramNames.has(nameToken.value)) {\n throw new Error(`Duplicate param name '${nameToken.value}' at line ${nameToken.line}, column ${nameToken.column}`);\n }\n if (this.letNames.has(nameToken.value)) {\n throw new Error(`Param '${nameToken.value}' conflicts with existing let variable at line ${nameToken.line}, column ${nameToken.column}`);\n }\n this.expect(\"ASSIGN\", \"Expected '=' after param name\");\n const valToken = this.advance();\n let defaultValue: string | number;\n if (valToken.type === \"NUMBER\") {\n defaultValue = parseFloat(valToken.value);\n } else if (valToken.type === \"STRING\") {\n defaultValue = valToken.value;\n } else if (valToken.type === \"PATH\") {\n defaultValue = valToken.value;\n } else if (valToken.type === \"IDENTIFIER\") {\n defaultValue = valToken.value;\n } else {\n throw new Error(`Expected default value after '=' at line ${valToken.line}, column ${valToken.column}`);\n }\n this.paramNames.add(nameToken.value);\n return { kind: \"param\", name: nameToken.value, defaultValue };\n }\n\n private static readonly PIPELINE_STARTERS = new Set([\"FIND\", \"ACTION\", \"LOOKUP\", \"INPUT\"]);\n\n private parseLet(): LetStatement {\n const letToken = this.advance(); // let\n if (this.isAtEnd() || this.peek().type !== \"IDENTIFIER\") {\n throw new Error(`Expected variable name after 'let' at line ${letToken.line}, column ${letToken.column}`);\n }\n const nameToken = this.advance();\n if (AshParser.RESERVED_KEYWORDS.has(nameToken.value)) {\n throw new Error(`Cannot use reserved keyword '${nameToken.value}' as variable name at line ${nameToken.line}, column ${nameToken.column}`);\n }\n if (this.letNames.has(nameToken.value)) {\n throw new Error(`Duplicate variable name '${nameToken.value}' at line ${nameToken.line}, column ${nameToken.column}`);\n }\n if (this.paramNames.has(nameToken.value)) {\n throw new Error(`Let variable '${nameToken.value}' conflicts with existing param at line ${nameToken.line}, column ${nameToken.column}`);\n }\n this.expect(\"ASSIGN\", \"Expected '=' after variable name\");\n\n // Check if the value is a pipeline (starts with find, action, etc.)\n if (!this.isAtEnd() && AshParser.PIPELINE_STARTERS.has(this.peek().type)) {\n const pipeline = this.parseLetPipeline();\n this.letNames.add(nameToken.value);\n return { kind: \"let\", name: nameToken.value, value: 0, pipeline };\n }\n\n const valToken = this.advance();\n let value: string | number;\n if (valToken.type === \"NUMBER\") {\n value = parseFloat(valToken.value);\n } else if (valToken.type === \"STRING\") {\n value = valToken.value;\n } else if (valToken.type === \"IDENTIFIER\") {\n value = valToken.value;\n } else {\n throw new Error(`Expected value after '=' at line ${valToken.line}, column ${valToken.column}`);\n }\n this.letNames.add(nameToken.value);\n return { kind: \"let\", name: nameToken.value, value };\n }\n\n private parseLetPipeline(): PipelineStage[] {\n // Parse pipeline stages until NEWLINE, EOF, or JOB/LET/OUTPUT (top-level)\n const stages: PipelineStage[] = [];\n while (!this.isAtEnd()) {\n const t = this.peek();\n // Stop at newline or top-level keywords\n if (t.type === \"NEWLINE\" || t.type === \"JOB\" || t.type === \"LET\" || t.type === \"OUTPUT\" || t.type === \"AT\") break;\n\n if (t.type === \"PIPE\") {\n this.advance(); // |\n continue;\n }\n\n stages.push(this.parseStage());\n }\n return stages;\n }\n\n private parseAnnotations(): Annotation[] {\n const annotations: Annotation[] = [];\n while (!this.isAtEnd() && this.peek().type === \"AT\") {\n const at = this.advance(); // @\n if (this.isAtEnd() || this.peek().type !== \"IDENTIFIER\") {\n throw new Error(`Expected annotation name after '@' at line ${at.line}, column ${at.column}`);\n }\n const nameToken = this.advance();\n const args: string[] = [];\n\n if (!this.isAtEnd() && this.peek().type === \"LPAREN\") {\n this.advance(); // (\n while (!this.isAtEnd() && this.peek().type !== \"RPAREN\") {\n const arg = this.advance();\n args.push(arg.value);\n if (!this.isAtEnd() && this.peek().type === \"COMMA\") {\n this.advance();\n }\n }\n if (this.isAtEnd()) {\n throw new Error(`Unclosed annotation parenthesis at line ${at.line}, column ${at.column}`);\n }\n this.advance(); // )\n }\n\n annotations.push({ name: nameToken.value, args, line: at.line, column: at.column });\n this.skipNewlines();\n }\n return annotations;\n }\n\n private parseJob(annotations: Annotation[]): JobDeclaration {\n this.advance(); // 'job'\n this.skipNewlines();\n\n if (this.isAtEnd()) {\n throw new Error(\"Expected job name\");\n }\n const nameToken = this.advance();\n if (AshParser.RESERVED_KEYWORDS.has(nameToken.value)) {\n throw new Error(`Cannot use reserved keyword '${nameToken.value}' as job name at line ${nameToken.line}, column ${nameToken.column}`);\n }\n this.skipNewlines();\n\n // Optional trigger: `on /path:event` or `on cron(\"expr\")`\n let trigger: TriggerDeclaration | undefined;\n if (!this.isAtEnd() && this.peek().type === \"ON\") {\n const onToken = this.advance(); // on\n\n if (!this.isAtEnd() && this.peek().type === \"IDENTIFIER\" && this.peek().value === \"cron\") {\n // Cron trigger: on cron(\"*/5 * * * *\")\n this.advance(); // cron\n if (this.isAtEnd() || this.peek().type !== \"LPAREN\") {\n throw new Error(`Expected '(' after 'cron' at line ${onToken.line}, column ${onToken.column}`);\n }\n this.advance(); // (\n if (this.isAtEnd() || this.peek().type !== \"STRING\") {\n throw new Error(`Expected cron expression string after 'cron(' at line ${onToken.line}, column ${onToken.column}`);\n }\n const exprToken = this.advance();\n if (this.isAtEnd() || this.peek().type !== \"RPAREN\") {\n throw new Error(`Expected ')' after cron expression at line ${onToken.line}, column ${onToken.column}`);\n }\n this.advance(); // )\n trigger = { kind: \"cron\", expression: exprToken.value };\n } else {\n // Event trigger: on /path:event\n if (this.isAtEnd() || this.peek().type !== \"PATH\") {\n throw new Error(`Expected path after 'on' at line ${onToken.line}, column ${onToken.column}`);\n }\n const pathToken = this.advance();\n if (this.isAtEnd() || this.peek().type !== \"COLON\") {\n throw new Error(`Expected ':event' after trigger path at line ${pathToken.line}, column ${pathToken.column}`);\n }\n this.advance(); // :\n if (this.isAtEnd() || this.peek().type !== \"IDENTIFIER\") {\n throw new Error(`Expected event name after ':' at line ${pathToken.line}, column ${pathToken.column}`);\n }\n const eventToken = this.advance();\n trigger = { kind: \"event\", path: pathToken.value, event: eventToken.value };\n }\n this.skipNewlines();\n }\n\n if (this.isAtEnd() || this.peek().type !== \"LBRACE\") {\n const t = this.isAtEnd() ? nameToken : this.peek();\n throw new Error(`Expected '{' after job name at line ${t.line}, column ${t.column}`);\n }\n this.advance(); // {\n this.skipNewlines();\n\n const pipeline = this.parsePipeline();\n this.skipNewlines();\n\n if (this.isAtEnd() || this.peek().type !== \"RBRACE\") {\n throw new Error(\"Expected '}' to close job body\");\n }\n this.advance(); // }\n\n return { kind: \"job\", name: nameToken.value, annotations, pipeline, trigger };\n }\n\n private parsePipeline(): PipelineStage[] {\n const stages: PipelineStage[] = [];\n\n while (!this.isAtEnd() && this.peek().type !== \"RBRACE\") {\n if (this.peek().type === \"PIPE\") {\n if (stages.length === 0) {\n const t = this.peek();\n throw new Error(`Unexpected PIPE at line ${t.line}, column ${t.column}`);\n }\n this.advance(); // |\n this.skipNewlines();\n if (this.isAtEnd() || this.peek().type === \"RBRACE\") {\n throw new Error(\"Unexpected end after pipe operator\");\n }\n }\n\n this.skipNewlines();\n if (this.isAtEnd() || this.peek().type === \"RBRACE\") break;\n\n const stage = this.parseStage();\n stages.push(stage);\n this.skipNewlines();\n }\n\n return stages;\n }\n\n private parseStage(): PipelineStage {\n const t = this.peek();\n\n switch (t.type) {\n case \"FIND\": {\n this.advance();\n const path = this.expect(\"PATH\", \"Expected path after 'find'\");\n // Check for inline where: `find /path where condition`\n let query: QueryCondition | undefined;\n if (!this.isAtEnd() && this.peek().type === \"WHERE\") {\n this.advance(); // consume WHERE\n const where = this.parseWhere();\n query = { field: where.left, op: where.op, value: where.right };\n }\n return { kind: \"find\", path: path.value, query };\n }\n case \"WHERE\": {\n this.advance();\n return this.parseWhere();\n }\n case \"MAP\": {\n this.advance();\n return this.parseMapBody();\n }\n case \"SAVE\": {\n this.advance();\n const path = this.expect(\"PATH\", \"Expected path after 'save'\");\n return { kind: \"save\", path: path.value };\n }\n case \"PUBLISH\": {\n this.advance();\n const path = this.expect(\"PATH\", \"Expected path after 'publish'\");\n return { kind: \"publish\", path: path.value };\n }\n case \"TEE\": {\n this.advance();\n const path = this.expect(\"PATH\", \"Expected path after 'tee'\");\n return { kind: \"tee\", path: path.value };\n }\n case \"FANOUT\": {\n this.advance();\n return this.parseFanout();\n }\n case \"OUTPUT\": {\n this.advance();\n // Try parsing as expression (supports field access, binary, string literals)\n const expr = this.parseExpression();\n if (expr.kind === \"literal\" && typeof expr.value === \"string\") {\n // Backward compatible: string literal → use message field\n return { kind: \"output\", message: expr.value };\n }\n // Expression mode: evaluate per stream item at runtime\n return { kind: \"output\", message: \"\", expression: expr };\n }\n case \"INPUT\": {\n this.advance();\n const prompt = this.expect(\"STRING\", \"Expected string after 'input'\");\n return { kind: \"input\", prompt: prompt.value };\n }\n case \"COUNT\": {\n this.advance();\n return { kind: \"count\" } as CountExpression;\n }\n case \"GROUP_BY\": {\n this.advance();\n if (this.isAtEnd() || this.peek().type === \"PIPE\" || this.peek().type === \"RBRACE\" || this.peek().type === \"NEWLINE\") {\n throw new Error(\"Expected field name after 'group-by'\");\n }\n const field = this.parseFieldAccess();\n return { kind: \"group-by\", field } as GroupByExpression;\n }\n case \"ACTION\": {\n return this.parseAction();\n }\n case \"ROUTE\": {\n return this.parseRoute();\n }\n case \"LOOKUP\": {\n return this.parseLookup();\n }\n default:\n throw new Error(`Unexpected token ${t.type} \"${t.value}\" at line ${t.line}, column ${t.column}`);\n }\n }\n\n private parseWhere(): WhereClause {\n const left = this.parseFieldAccess();\n const opToken = this.advance();\n\n // Handle `in` operator: where field in [val1, val2, ...] or where field in $var\n if (opToken.type === \"IN\") {\n // $variable reference\n if (!this.isAtEnd() && this.peek().type === \"DOLLAR\") {\n this.advance(); // $\n const varName = this.advance();\n return { kind: \"where\", left, op: \"in\", right: \"$\" + varName.value };\n }\n // Array literal\n if (this.isAtEnd() || this.peek().type !== \"LBRACKET\") {\n throw new Error(`Expected '[' or '$variable' after 'in' at line ${opToken.line}, column ${opToken.column}`);\n }\n this.advance(); // [\n this.skipNewlines();\n const values: (string | number)[] = [];\n while (!this.isAtEnd() && this.peek().type !== \"RBRACKET\") {\n const valToken = this.advance();\n if (valToken.type === \"NUMBER\") {\n values.push(parseFloat(valToken.value));\n } else if (valToken.type === \"STRING\") {\n values.push(valToken.value);\n } else if (valToken.type === \"IDENTIFIER\") {\n values.push(valToken.value);\n } else {\n throw new Error(`Expected string, number, or identifier in 'in' list at line ${valToken.line}, column ${valToken.column}`);\n }\n this.skipNewlines();\n if (!this.isAtEnd() && this.peek().type === \"COMMA\") {\n this.advance(); // ,\n this.skipNewlines();\n }\n }\n if (this.isAtEnd()) {\n throw new Error(`Expected ']' to close 'in' list at line ${opToken.line}, column ${opToken.column}`);\n }\n this.advance(); // ]\n return { kind: \"where\", left, op: \"in\", right: values };\n }\n\n const opMap: Record<string, WhereClause[\"op\"]> = {\n \"==\": \"==\", \"!=\": \"!=\", \">\": \">\", \"<\": \"<\", \">=\": \">=\", \"<=\": \"<=\",\n };\n const op = opMap[opToken.value];\n if (!op) {\n throw new Error(`Expected comparison operator, got ${opToken.type} at line ${opToken.line}, column ${opToken.column}`);\n }\n\n let right: string | number;\n // Check for $variable reference\n if (!this.isAtEnd() && this.peek().type === \"DOLLAR\") {\n this.advance(); // $\n const varName = this.advance();\n right = \"$\" + varName.value;\n } else {\n const rightToken = this.advance();\n if (rightToken.type === \"NUMBER\") {\n right = parseFloat(rightToken.value);\n } else if (rightToken.type === \"STRING\") {\n right = rightToken.value;\n } else if (rightToken.type === \"IDENTIFIER\" || rightToken.type === \"PATH\") {\n let val = rightToken.value;\n while (!this.isAtEnd() && this.peek().type === \"DOT\") {\n this.advance();\n const next = this.advance();\n val += \".\" + next.value;\n }\n right = val;\n } else {\n right = rightToken.value;\n }\n }\n\n return { kind: \"where\", left, op, right };\n }\n\n private parseFieldAccess(): string {\n const first = this.advance();\n let field = first.value;\n while (!this.isAtEnd() && this.peek().type === \"DOT\") {\n this.advance(); // .\n const next = this.advance();\n field += \".\" + next.value;\n }\n return field;\n }\n\n private parseMapBody(): MapExpression {\n // map without braces: either simple field or expression\n if (this.isAtEnd() || this.peek().type === \"PIPE\" || this.peek().type === \"RBRACE\" || this.peek().type === \"NEWLINE\") {\n throw new Error(\"Expected field or expression after 'map'\");\n }\n\n if (this.peek().type !== \"LBRACE\") {\n // map field or map expr (no braces)\n // Try to parse as expression; if it's just a field access, use backward-compat field mode\n const expr = this.parseExpression();\n if (expr.kind === \"field_access\") {\n return { kind: \"map\", field: expr.path };\n }\n return { kind: \"map\", field: \"\", expression: expr };\n }\n\n // map { ... }\n this.advance(); // {\n this.skipNewlines();\n\n // Detect mode: peek ahead to see if first pair uses COLON (expression) or not (legacy)\n if (this.isAtEnd() || this.peek().type === \"RBRACE\") {\n this.advance(); // }\n return { kind: \"map\", field: \"\" };\n }\n\n // Save position to peek ahead\n const savedPos = this.pos;\n // Skip the first key token\n this.advance();\n const hasColon = !this.isAtEnd() && this.peek().type === \"COLON\";\n this.pos = savedPos; // restore\n\n if (hasColon) {\n // Expression mode: map { key: expr, ... }\n // Use Object.create(null) to prevent __proto__ pollution\n const exprMappings: Record<string, Expression> = Object.create(null);\n const seenExprKeys = new Set<string>();\n while (!this.isAtEnd() && this.peek().type !== \"RBRACE\") {\n const keyToken = this.expect(\"IDENTIFIER\", \"Expected key in map expression\");\n if (seenExprKeys.has(keyToken.value)) {\n throw new Error(`Duplicate map key '${keyToken.value}' at line ${keyToken.line}, column ${keyToken.column}`);\n }\n seenExprKeys.add(keyToken.value);\n this.expect(\"COLON\", \"Expected ':' after key in map expression\");\n const expr = this.parseExpression();\n exprMappings[keyToken.value] = expr;\n this.skipNewlines();\n if (!this.isAtEnd() && this.peek().type === \"COMMA\") {\n this.advance();\n this.skipNewlines();\n }\n }\n if (this.isAtEnd()) throw new Error(\"Expected '}' to close map expression\");\n this.advance(); // }\n return { kind: \"map\", field: \"\", exprMappings };\n }\n\n // Legacy mode: map { outputKey inputField, outputKey inputField }\n // Use Object.create(null) to prevent __proto__ pollution\n const mappings: Record<string, string> = Object.create(null);\n const seenMapKeys = new Set<string>();\n while (!this.isAtEnd() && this.peek().type !== \"RBRACE\") {\n const key = this.advance();\n if (seenMapKeys.has(key.value)) {\n throw new Error(`Duplicate map key '${key.value}' at line ${key.line}, column ${key.column}`);\n }\n seenMapKeys.add(key.value);\n const field = this.advance();\n mappings[key.value] = field.value;\n this.skipNewlines();\n if (!this.isAtEnd() && this.peek().type === \"COMMA\") {\n this.advance();\n this.skipNewlines();\n }\n }\n if (this.isAtEnd()) throw new Error(\"Expected '}' to close map object\");\n this.advance(); // }\n const firstKey = Object.keys(mappings)[0] ?? \"\";\n return { kind: \"map\", field: firstKey, mappings };\n }\n\n // ── Expression parsing (recursive descent with precedence) ──\n // expr = term (('+' | '-') term)*\n // term = factor (('*' | '/') factor)*\n // factor = '(' expr ')' | $var | literal | fieldAccess\n\n private parseExpression(): Expression {\n let left = this.parseTerm();\n while (!this.isAtEnd() && (this.peek().type === \"PLUS\" || this.peek().type === \"MINUS\")) {\n const opToken = this.advance();\n const right = this.parseTerm();\n left = { kind: \"binary\", op: opToken.value as \"+\" | \"-\", left, right };\n }\n return left;\n }\n\n private parseTerm(): Expression {\n let left = this.parseFactor();\n while (!this.isAtEnd() && (this.peek().type === \"STAR\" || this.peek().type === \"SLASH\")) {\n const opToken = this.advance();\n const right = this.parseFactor();\n left = { kind: \"binary\", op: opToken.value as \"*\" | \"/\", left, right };\n }\n return left;\n }\n\n private parseFactor(): Expression {\n if (this.isAtEnd()) {\n throw new Error(\"Expected expression\");\n }\n const t = this.peek();\n\n // Parenthesized expression\n if (t.type === \"LPAREN\") {\n this.advance(); // (\n const expr = this.parseExpression();\n this.expect(\"RPAREN\", \"Expected ')' after expression\");\n return expr;\n }\n\n // Variable reference: $name\n if (t.type === \"DOLLAR\") {\n this.advance(); // $\n const nameToken = this.expect(\"IDENTIFIER\", \"Expected variable name after '$'\");\n return { kind: \"var_ref\", name: nameToken.value };\n }\n\n // String literal\n if (t.type === \"STRING\") {\n this.advance();\n return { kind: \"literal\", value: t.value };\n }\n\n // Number literal\n if (t.type === \"NUMBER\") {\n this.advance();\n return { kind: \"literal\", value: parseFloat(t.value) };\n }\n\n // Array literal: [expr, expr, ...]\n if (t.type === \"LBRACKET\") {\n this.advance(); // [\n this.skipNewlines();\n const elements: Expression[] = [];\n while (!this.isAtEnd() && this.peek().type !== \"RBRACKET\") {\n elements.push(this.parseExpression());\n this.skipNewlines();\n if (!this.isAtEnd() && this.peek().type === \"COMMA\") {\n this.advance(); // ,\n this.skipNewlines();\n }\n }\n this.expect(\"RBRACKET\", \"Expected ']' after array literal\");\n return { kind: \"array_literal\", elements };\n }\n\n // Object literal: { key: expr, key: expr, ... }\n if (t.type === \"LBRACE\") {\n this.advance(); // {\n this.skipNewlines();\n const properties: Record<string, Expression> = {};\n while (!this.isAtEnd() && this.peek().type !== \"RBRACE\") {\n const keyToken = this.expect(\"IDENTIFIER\", \"Expected property name in object literal\");\n this.expect(\"COLON\", \"Expected ':' after property name\");\n properties[keyToken.value] = this.parseExpression();\n this.skipNewlines();\n if (!this.isAtEnd() && this.peek().type === \"COMMA\") {\n this.advance(); // ,\n this.skipNewlines();\n }\n }\n this.expect(\"RBRACE\", \"Expected '}' after object literal\");\n return { kind: \"object_literal\", properties };\n }\n\n // Field access: identifier (possibly dotted)\n if (t.type === \"IDENTIFIER\") {\n let field = this.advance().value;\n while (!this.isAtEnd() && this.peek().type === \"DOT\") {\n this.advance(); // .\n const next = this.advance();\n field += \".\" + next.value;\n }\n return { kind: \"field_access\", path: field };\n }\n\n throw new Error(`Unexpected token in expression: ${t.type} \"${t.value}\" at line ${t.line}, column ${t.column}`);\n }\n\n private parseAction(): ActionExpression {\n const actionToken = this.advance(); // action\n if (this.isAtEnd()) {\n throw new Error(`Expected path or action name after 'action' at line ${actionToken.line}, column ${actionToken.column}`);\n }\n\n const nextToken = this.peek();\n let path: string;\n let relative: boolean | undefined;\n\n if (nextToken.type === \"PATH\") {\n // Absolute action: action /tesla/.actions/honk\n path = this.advance().value;\n } else if (nextToken.type === \"IDENTIFIER\") {\n // Relative action: action turn_off\n path = this.advance().value;\n relative = true;\n } else {\n throw new Error(`Expected path or action name after 'action' at line ${actionToken.line}, column ${actionToken.column}`);\n }\n\n let params: Record<string, unknown> | undefined;\n\n // Optional params: { key: value, ... }\n if (!this.isAtEnd() && this.peek().type === \"LBRACE\") {\n this.advance(); // {\n params = {};\n this.skipNewlines();\n while (!this.isAtEnd() && this.peek().type !== \"RBRACE\") {\n const keyToken = this.expect(\"IDENTIFIER\", \"Expected parameter name in action params\");\n this.expect(\"COLON\", \"Expected ':' after parameter name\");\n if (this.isAtEnd()) {\n throw new Error(`Expected value after ':' at line ${keyToken.line}, column ${keyToken.column}`);\n }\n // Check for json() wrapper\n if (this.peek().type === \"IDENTIFIER\" && this.peek().value === \"json\") {\n const jsonToken = this.advance(); // consume \"json\"\n this.expect(\"LPAREN\", `Expected '(' after json at line ${jsonToken.line}, column ${jsonToken.column}`);\n params[keyToken.value] = this.parseJsonValue();\n this.expect(\"RPAREN\", \"Expected ')' to close json()\");\n } else {\n const valToken = this.advance();\n if (valToken.type === \"STRING\") {\n params[keyToken.value] = valToken.value;\n } else if (valToken.type === \"NUMBER\") {\n params[keyToken.value] = parseFloat(valToken.value);\n } else {\n throw new Error(`Expected string or number value for parameter '${keyToken.value}' at line ${valToken.line}, column ${valToken.column}`);\n }\n }\n this.skipNewlines();\n if (!this.isAtEnd() && this.peek().type === \"COMMA\") {\n this.advance();\n this.skipNewlines();\n }\n }\n if (this.isAtEnd()) throw new Error(\"Expected '}' to close action params\");\n this.advance(); // }\n }\n\n return { kind: \"action\", path, relative, params };\n }\n\n private parseRoute(): RouteExpression {\n const routeToken = this.advance(); // route\n if (this.isAtEnd() || (this.peek().type !== \"IDENTIFIER\" && this.peek().type !== \"DOT\")) {\n throw new Error(`Expected field name after 'route' at line ${routeToken.line}, column ${routeToken.column}`);\n }\n const field = this.parseFieldAccess();\n this.expect(\"LBRACE\", \"Expected '{' after route field\");\n this.skipNewlines();\n\n const branches: RouteBranch[] = [];\n let fallback: string | undefined;\n\n while (!this.isAtEnd() && this.peek().type !== \"RBRACE\") {\n // Each branch: \"value\" -> job target OR _ -> job target\n let value: string;\n if (this.peek().type === \"STRING\") {\n value = this.advance().value;\n } else if (this.peek().type === \"IDENTIFIER\" && this.peek().value === \"_\") {\n value = \"_\";\n this.advance();\n } else {\n throw new Error(`Expected string value or '_' in route branch at line ${this.peek().line}, column ${this.peek().column}`);\n }\n\n this.expect(\"ARROW\", \"Expected '->' in route branch\");\n this.expect(\"JOB\", \"Expected 'job' keyword in route branch target\");\n const targetToken = this.advance(); // job name\n\n if (value === \"_\") {\n fallback = targetToken.value;\n } else {\n branches.push({ value, targetJob: targetToken.value });\n }\n\n this.skipNewlines();\n if (!this.isAtEnd() && this.peek().type === \"COMMA\") {\n this.advance();\n this.skipNewlines();\n }\n }\n\n if (branches.length === 0 && !fallback) {\n throw new Error(`Route must have at least one branch at line ${routeToken.line}, column ${routeToken.column}`);\n }\n\n if (this.isAtEnd()) throw new Error(\"Expected '}' to close route\");\n this.advance(); // }\n\n return { kind: \"route\", field, branches, fallback };\n }\n\n private parseLookup(): LookupExpression {\n const lookupToken = this.advance(); // lookup\n if (this.isAtEnd() || this.peek().type !== \"PATH\") {\n throw new Error(`Expected path after 'lookup' at line ${lookupToken.line}, column ${lookupToken.column}`);\n }\n const pathToken = this.advance();\n // Expect \"on\" keyword\n if (this.isAtEnd() || this.peek().type !== \"ON\") {\n throw new Error(`Expected 'on' keyword after lookup path at line ${lookupToken.line}, column ${lookupToken.column}`);\n }\n this.advance(); // on\n const joinKey = this.parseFieldAccess();\n return { kind: \"lookup\", path: pathToken.value, joinKey };\n }\n\n private parseFanout(): PipelineStage {\n this.expect(\"LBRACE\", \"Expected '{' after 'fanout'\");\n const branches: PipelineStage[][] = [];\n\n this.skipNewlines();\n while (!this.isAtEnd() && this.peek().type !== \"RBRACE\") {\n // Each branch is a pipeline until COMMA or RBRACE\n const branch: PipelineStage[] = [];\n while (!this.isAtEnd() && this.peek().type !== \"COMMA\" && this.peek().type !== \"RBRACE\" && this.peek().type !== \"NEWLINE\") {\n if (this.peek().type === \"PIPE\") {\n this.advance();\n }\n branch.push(this.parseStage());\n }\n branches.push(branch);\n this.skipNewlines();\n if (!this.isAtEnd() && this.peek().type === \"COMMA\") {\n this.advance();\n this.skipNewlines();\n }\n }\n\n if (this.isAtEnd()) throw new Error(\"Expected '}' to close fanout\");\n this.advance(); // }\n\n return { kind: \"fanout\", branches };\n }\n\n /** Recursive descent JSON value parser using existing lexer tokens. */\n private parseJsonValue(): unknown {\n if (this.isAtEnd()) throw new Error(\"Expected JSON value (unexpected EOF)\");\n const t = this.peek();\n\n // Object: { ... }\n if (t.type === \"LBRACE\") {\n this.advance(); // {\n const obj: Record<string, unknown> = {};\n this.skipNewlines();\n while (!this.isAtEnd() && this.peek().type !== \"RBRACE\") {\n const keyToken = this.advance();\n if (keyToken.type !== \"STRING\" && keyToken.type !== \"IDENTIFIER\") {\n throw new Error(`Expected string key in JSON object at line ${keyToken.line}, column ${keyToken.column}`);\n }\n this.expect(\"COLON\", \"Expected ':' after key in JSON object\");\n obj[keyToken.value] = this.parseJsonValue();\n this.skipNewlines();\n if (!this.isAtEnd() && this.peek().type === \"COMMA\") {\n this.advance();\n this.skipNewlines();\n }\n }\n if (this.isAtEnd()) throw new Error(\"Expected '}' to close JSON object\");\n this.advance(); // }\n return obj;\n }\n\n // Array: [ ... ]\n if (t.type === \"LBRACKET\") {\n this.advance(); // [\n const arr: unknown[] = [];\n this.skipNewlines();\n while (!this.isAtEnd() && this.peek().type !== \"RBRACKET\") {\n arr.push(this.parseJsonValue());\n this.skipNewlines();\n if (!this.isAtEnd() && this.peek().type === \"COMMA\") {\n this.advance();\n this.skipNewlines();\n }\n }\n if (this.isAtEnd()) throw new Error(\"Expected ']' to close JSON array\");\n this.advance(); // ]\n return arr;\n }\n\n // String\n if (t.type === \"STRING\") {\n this.advance();\n return t.value;\n }\n\n // Number\n if (t.type === \"NUMBER\") {\n this.advance();\n return parseFloat(t.value);\n }\n\n // Boolean / null: true, false, null are lexed as IDENTIFIER\n if (t.type === \"IDENTIFIER\") {\n if (t.value === \"true\") { this.advance(); return true; }\n if (t.value === \"false\") { this.advance(); return false; }\n if (t.value === \"null\") { this.advance(); return null; }\n }\n\n throw new Error(`Unexpected token in json(): ${t.type} \"${t.value}\" at line ${t.line}, column ${t.column}`);\n }\n\n private peek(): Token {\n return this.tokens[this.pos];\n }\n\n private advance(): Token {\n return this.tokens[this.pos++];\n }\n\n private expect(type: TokenType, message: string): Token {\n if (this.isAtEnd()) throw new Error(message + \" (unexpected EOF)\");\n const t = this.peek();\n if (t.type !== type) {\n throw new Error(`${message}, got ${t.type} at line ${t.line}, column ${t.column}`);\n }\n return this.advance();\n }\n\n private isAtEnd(): boolean {\n return this.pos >= this.tokens.length || this.tokens[this.pos].type === \"EOF\";\n }\n\n private skipNewlines(): void {\n while (!this.isAtEnd() && this.peek().type === \"NEWLINE\") {\n this.pos++;\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"parser.mjs","names":[],"sources":["../src/parser.ts"],"sourcesContent":["import type { Token, TokenType } from \"./lexer.js\";\nimport type { Program, JobDeclaration, PipelineStage, Annotation, WhereClause, QueryCondition, TopLevelStatement, LetStatement, CountExpression, GroupByExpression, ActionExpression, Expression, MapExpression, RouteExpression, RouteBranch, LookupExpression, ParamDeclaration, TriggerDeclaration } from \"./ast.js\";\n\n/** Annotation names that are script-level: propagate to all jobs when declared before any statement. */\nconst SCRIPT_LEVEL_ANNOTATIONS = new Set([\"caps\", \"budget\"]);\n\n/** Merge script-level annotations with job-specific ones. Job overrides script-level by name. */\nfunction mergeAnnotations(script: Annotation[], job: Annotation[]): Annotation[] {\n if (script.length === 0) return job;\n if (job.length === 0) return [...script];\n const jobNames = new Set(job.map(a => a.name));\n return [...script.filter(a => !jobNames.has(a.name)), ...job];\n}\n\nexport class AshParser {\n private tokens: Token[] = [];\n private pos = 0;\n\n private letNames = new Set<string>();\n private paramNames = new Set<string>();\n private static readonly RESERVED_KEYWORDS = new Set([\"job\", \"find\", \"where\", \"map\", \"save\", \"publish\", \"tee\", \"fanout\", \"input\", \"output\", \"let\", \"action\", \"route\", \"lookup\", \"param\", \"on\", \"in\"]);\n\n parse(tokens: Token[]): Program {\n this.tokens = tokens;\n this.pos = 0;\n this.letNames = new Set();\n this.paramNames = new Set();\n const statements: TopLevelStatement[] = [];\n\n this.skipNewlines();\n\n // Collect initial annotations (before any statement).\n // Split into script-level (caps, budget → propagate to all jobs) and first-job-specific.\n const initialAnnotations = this.parseAnnotations();\n const scriptAnnotations = initialAnnotations.filter(a => SCRIPT_LEVEL_ANNOTATIONS.has(a.name));\n const firstJobOnly = initialAnnotations.filter(a => !SCRIPT_LEVEL_ANNOTATIONS.has(a.name));\n let firstStatement = true;\n\n while (!this.isAtEnd()) {\n const jobAnnotations = this.parseAnnotations();\n if (this.isAtEnd()) break;\n\n const t = this.peek();\n if (t.type === \"JOB\") {\n const extra = firstStatement ? [...firstJobOnly, ...jobAnnotations] : jobAnnotations;\n const merged = mergeAnnotations(scriptAnnotations, extra);\n firstStatement = false;\n statements.push(this.parseJob(merged));\n } else if (t.type === \"OUTPUT\" && jobAnnotations.length === 0) {\n firstStatement = false;\n this.advance(); // output\n const msg = this.expect(\"STRING\", \"Expected string after 'output'\");\n statements.push({ kind: \"output\", message: msg.value });\n } else if (t.type === \"LET\" && jobAnnotations.length === 0) {\n firstStatement = false;\n statements.push(this.parseLet());\n } else if (t.type === \"PARAM\" && jobAnnotations.length === 0) {\n firstStatement = false;\n statements.push(this.parseParam());\n } else {\n throw new Error(`Expected 'job', 'output', 'let', or 'param' at top level, got ${t.type} at line ${t.line}, column ${t.column}`);\n }\n this.skipNewlines();\n }\n\n const jobs = statements.filter((s): s is JobDeclaration => s.kind === \"job\");\n return { statements, jobs };\n }\n\n private parseParam(): ParamDeclaration {\n const paramToken = this.advance(); // param\n if (this.isAtEnd()) {\n throw new Error(`Expected parameter name after 'param' at line ${paramToken.line}, column ${paramToken.column}`);\n }\n const nameToken = this.peek();\n if (nameToken.type !== \"IDENTIFIER\") {\n throw new Error(`Cannot use reserved keyword '${nameToken.value}' as param name at line ${nameToken.line}, column ${nameToken.column}`);\n }\n this.advance();\n if (AshParser.RESERVED_KEYWORDS.has(nameToken.value)) {\n throw new Error(`Cannot use reserved keyword '${nameToken.value}' as param name at line ${nameToken.line}, column ${nameToken.column}`);\n }\n if (this.paramNames.has(nameToken.value)) {\n throw new Error(`Duplicate param name '${nameToken.value}' at line ${nameToken.line}, column ${nameToken.column}`);\n }\n if (this.letNames.has(nameToken.value)) {\n throw new Error(`Param '${nameToken.value}' conflicts with existing let variable at line ${nameToken.line}, column ${nameToken.column}`);\n }\n this.expect(\"ASSIGN\", \"Expected '=' after param name\");\n const valToken = this.advance();\n let defaultValue: string | number;\n if (valToken.type === \"NUMBER\") {\n defaultValue = parseFloat(valToken.value);\n } else if (valToken.type === \"STRING\") {\n defaultValue = valToken.value;\n } else if (valToken.type === \"PATH\") {\n defaultValue = valToken.value;\n } else if (valToken.type === \"IDENTIFIER\") {\n defaultValue = valToken.value;\n } else {\n throw new Error(`Expected default value after '=' at line ${valToken.line}, column ${valToken.column}`);\n }\n this.paramNames.add(nameToken.value);\n return { kind: \"param\", name: nameToken.value, defaultValue };\n }\n\n private static readonly PIPELINE_STARTERS = new Set([\"FIND\", \"ACTION\", \"LOOKUP\", \"INPUT\"]);\n\n private parseLet(): LetStatement {\n const letToken = this.advance(); // let\n if (this.isAtEnd() || this.peek().type !== \"IDENTIFIER\") {\n throw new Error(`Expected variable name after 'let' at line ${letToken.line}, column ${letToken.column}`);\n }\n const nameToken = this.advance();\n if (AshParser.RESERVED_KEYWORDS.has(nameToken.value)) {\n throw new Error(`Cannot use reserved keyword '${nameToken.value}' as variable name at line ${nameToken.line}, column ${nameToken.column}`);\n }\n if (this.letNames.has(nameToken.value)) {\n throw new Error(`Duplicate variable name '${nameToken.value}' at line ${nameToken.line}, column ${nameToken.column}`);\n }\n if (this.paramNames.has(nameToken.value)) {\n throw new Error(`Let variable '${nameToken.value}' conflicts with existing param at line ${nameToken.line}, column ${nameToken.column}`);\n }\n this.expect(\"ASSIGN\", \"Expected '=' after variable name\");\n\n // Check if the value is a pipeline (starts with find, action, etc.)\n if (!this.isAtEnd() && AshParser.PIPELINE_STARTERS.has(this.peek().type)) {\n const pipeline = this.parseLetPipeline();\n this.letNames.add(nameToken.value);\n return { kind: \"let\", name: nameToken.value, value: 0, pipeline };\n }\n\n const valToken = this.advance();\n let value: string | number;\n if (valToken.type === \"NUMBER\") {\n value = parseFloat(valToken.value);\n } else if (valToken.type === \"STRING\") {\n value = valToken.value;\n } else if (valToken.type === \"IDENTIFIER\") {\n value = valToken.value;\n } else {\n throw new Error(`Expected value after '=' at line ${valToken.line}, column ${valToken.column}`);\n }\n this.letNames.add(nameToken.value);\n return { kind: \"let\", name: nameToken.value, value };\n }\n\n private parseLetPipeline(): PipelineStage[] {\n // Parse pipeline stages until NEWLINE, EOF, or JOB/LET/OUTPUT (top-level)\n const stages: PipelineStage[] = [];\n while (!this.isAtEnd()) {\n const t = this.peek();\n // Stop at newline or top-level keywords\n if (t.type === \"NEWLINE\" || t.type === \"JOB\" || t.type === \"LET\" || t.type === \"OUTPUT\" || t.type === \"AT\") break;\n\n if (t.type === \"PIPE\") {\n this.advance(); // |\n continue;\n }\n\n stages.push(this.parseStage());\n }\n return stages;\n }\n\n private parseAnnotations(): Annotation[] {\n const annotations: Annotation[] = [];\n while (!this.isAtEnd() && this.peek().type === \"AT\") {\n const at = this.advance(); // @\n if (this.isAtEnd() || this.peek().type !== \"IDENTIFIER\") {\n throw new Error(`Expected annotation name after '@' at line ${at.line}, column ${at.column}`);\n }\n const nameToken = this.advance();\n const args: string[] = [];\n\n if (!this.isAtEnd() && this.peek().type === \"LPAREN\") {\n this.advance(); // (\n while (!this.isAtEnd() && this.peek().type !== \"RPAREN\") {\n const arg = this.advance();\n args.push(arg.value);\n if (!this.isAtEnd() && this.peek().type === \"COMMA\") {\n this.advance();\n }\n }\n if (this.isAtEnd()) {\n throw new Error(`Unclosed annotation parenthesis at line ${at.line}, column ${at.column}`);\n }\n this.advance(); // )\n }\n\n annotations.push({ name: nameToken.value, args, line: at.line, column: at.column });\n this.skipNewlines();\n }\n return annotations;\n }\n\n private parseJob(annotations: Annotation[]): JobDeclaration {\n this.advance(); // 'job'\n this.skipNewlines();\n\n if (this.isAtEnd()) {\n throw new Error(\"Expected job name\");\n }\n const nameToken = this.advance();\n if (AshParser.RESERVED_KEYWORDS.has(nameToken.value)) {\n throw new Error(`Cannot use reserved keyword '${nameToken.value}' as job name at line ${nameToken.line}, column ${nameToken.column}`);\n }\n this.skipNewlines();\n\n // Optional trigger: `on /path:event` or `on cron(\"expr\")`\n let trigger: TriggerDeclaration | undefined;\n if (!this.isAtEnd() && this.peek().type === \"ON\") {\n const onToken = this.advance(); // on\n\n if (!this.isAtEnd() && this.peek().type === \"IDENTIFIER\" && this.peek().value === \"cron\") {\n // Cron trigger: on cron(\"*/5 * * * *\")\n this.advance(); // cron\n if (this.isAtEnd() || this.peek().type !== \"LPAREN\") {\n throw new Error(`Expected '(' after 'cron' at line ${onToken.line}, column ${onToken.column}`);\n }\n this.advance(); // (\n if (this.isAtEnd() || this.peek().type !== \"STRING\") {\n throw new Error(`Expected cron expression string after 'cron(' at line ${onToken.line}, column ${onToken.column}`);\n }\n const exprToken = this.advance();\n if (this.isAtEnd() || this.peek().type !== \"RPAREN\") {\n throw new Error(`Expected ')' after cron expression at line ${onToken.line}, column ${onToken.column}`);\n }\n this.advance(); // )\n trigger = { kind: \"cron\", expression: exprToken.value };\n } else {\n // Event trigger: on /path:event\n if (this.isAtEnd() || this.peek().type !== \"PATH\") {\n throw new Error(`Expected path after 'on' at line ${onToken.line}, column ${onToken.column}`);\n }\n const pathToken = this.advance();\n if (this.isAtEnd() || this.peek().type !== \"COLON\") {\n throw new Error(`Expected ':event' after trigger path at line ${pathToken.line}, column ${pathToken.column}`);\n }\n this.advance(); // :\n if (this.isAtEnd() || this.peek().type !== \"IDENTIFIER\") {\n throw new Error(`Expected event name after ':' at line ${pathToken.line}, column ${pathToken.column}`);\n }\n const eventToken = this.advance();\n trigger = { kind: \"event\", path: pathToken.value, event: eventToken.value };\n }\n this.skipNewlines();\n }\n\n if (this.isAtEnd() || this.peek().type !== \"LBRACE\") {\n const t = this.isAtEnd() ? nameToken : this.peek();\n throw new Error(`Expected '{' after job name at line ${t.line}, column ${t.column}`);\n }\n this.advance(); // {\n this.skipNewlines();\n\n const pipeline = this.parsePipeline();\n this.skipNewlines();\n\n if (this.isAtEnd() || this.peek().type !== \"RBRACE\") {\n throw new Error(\"Expected '}' to close job body\");\n }\n this.advance(); // }\n\n return { kind: \"job\", name: nameToken.value, annotations, pipeline, trigger };\n }\n\n private parsePipeline(): PipelineStage[] {\n const stages: PipelineStage[] = [];\n\n while (!this.isAtEnd() && this.peek().type !== \"RBRACE\") {\n if (this.peek().type === \"PIPE\") {\n if (stages.length === 0) {\n const t = this.peek();\n throw new Error(`Unexpected PIPE at line ${t.line}, column ${t.column}`);\n }\n this.advance(); // |\n this.skipNewlines();\n if (this.isAtEnd() || this.peek().type === \"RBRACE\") {\n throw new Error(\"Unexpected end after pipe operator\");\n }\n }\n\n this.skipNewlines();\n if (this.isAtEnd() || this.peek().type === \"RBRACE\") break;\n\n const stage = this.parseStage();\n stages.push(stage);\n this.skipNewlines();\n }\n\n return stages;\n }\n\n private parseStage(): PipelineStage {\n const t = this.peek();\n\n switch (t.type) {\n case \"FIND\": {\n this.advance();\n const path = this.expect(\"PATH\", \"Expected path after 'find'\");\n // Check for inline where: `find /path where condition`\n let query: QueryCondition | undefined;\n if (!this.isAtEnd() && this.peek().type === \"WHERE\") {\n this.advance(); // consume WHERE\n const where = this.parseWhere();\n query = { field: where.left, op: where.op, value: where.right };\n }\n return { kind: \"find\", path: path.value, query };\n }\n case \"WHERE\": {\n this.advance();\n return this.parseWhere();\n }\n case \"MAP\": {\n this.advance();\n return this.parseMapBody();\n }\n case \"SAVE\": {\n this.advance();\n const path = this.expect(\"PATH\", \"Expected path after 'save'\");\n return { kind: \"save\", path: path.value };\n }\n case \"PUBLISH\": {\n this.advance();\n const path = this.expect(\"PATH\", \"Expected path after 'publish'\");\n return { kind: \"publish\", path: path.value };\n }\n case \"TEE\": {\n this.advance();\n const path = this.expect(\"PATH\", \"Expected path after 'tee'\");\n return { kind: \"tee\", path: path.value };\n }\n case \"FANOUT\": {\n this.advance();\n return this.parseFanout();\n }\n case \"OUTPUT\": {\n this.advance();\n // Try parsing as expression (supports field access, binary, string literals)\n const expr = this.parseExpression();\n if (expr.kind === \"literal\" && typeof expr.value === \"string\") {\n // Backward compatible: string literal → use message field\n return { kind: \"output\", message: expr.value };\n }\n // Expression mode: evaluate per stream item at runtime\n return { kind: \"output\", message: \"\", expression: expr };\n }\n case \"INPUT\": {\n this.advance();\n const prompt = this.expect(\"STRING\", \"Expected string after 'input'\");\n return { kind: \"input\", prompt: prompt.value };\n }\n case \"COUNT\": {\n this.advance();\n return { kind: \"count\" } as CountExpression;\n }\n case \"GROUP_BY\": {\n this.advance();\n if (this.isAtEnd() || this.peek().type === \"PIPE\" || this.peek().type === \"RBRACE\" || this.peek().type === \"NEWLINE\") {\n throw new Error(\"Expected field name after 'group-by'\");\n }\n const field = this.parseFieldAccess();\n return { kind: \"group-by\", field } as GroupByExpression;\n }\n case \"ACTION\": {\n return this.parseAction();\n }\n case \"ROUTE\": {\n return this.parseRoute();\n }\n case \"LOOKUP\": {\n return this.parseLookup();\n }\n default:\n throw new Error(`Unexpected token ${t.type} \"${t.value}\" at line ${t.line}, column ${t.column}`);\n }\n }\n\n private parseWhere(): WhereClause {\n const left = this.parseFieldAccess();\n const opToken = this.advance();\n\n // Handle `in` operator: where field in [val1, val2, ...] or where field in $var\n if (opToken.type === \"IN\") {\n // $variable reference\n if (!this.isAtEnd() && this.peek().type === \"DOLLAR\") {\n this.advance(); // $\n const varName = this.advance();\n return { kind: \"where\", left, op: \"in\", right: \"$\" + varName.value };\n }\n // Array literal\n if (this.isAtEnd() || this.peek().type !== \"LBRACKET\") {\n throw new Error(`Expected '[' or '$variable' after 'in' at line ${opToken.line}, column ${opToken.column}`);\n }\n this.advance(); // [\n this.skipNewlines();\n const values: (string | number)[] = [];\n while (!this.isAtEnd() && this.peek().type !== \"RBRACKET\") {\n const valToken = this.advance();\n if (valToken.type === \"NUMBER\") {\n values.push(parseFloat(valToken.value));\n } else if (valToken.type === \"STRING\") {\n values.push(valToken.value);\n } else if (valToken.type === \"IDENTIFIER\") {\n values.push(valToken.value);\n } else {\n throw new Error(`Expected string, number, or identifier in 'in' list at line ${valToken.line}, column ${valToken.column}`);\n }\n this.skipNewlines();\n if (!this.isAtEnd() && this.peek().type === \"COMMA\") {\n this.advance(); // ,\n this.skipNewlines();\n }\n }\n if (this.isAtEnd()) {\n throw new Error(`Expected ']' to close 'in' list at line ${opToken.line}, column ${opToken.column}`);\n }\n this.advance(); // ]\n return { kind: \"where\", left, op: \"in\", right: values };\n }\n\n const opMap: Record<string, WhereClause[\"op\"]> = {\n \"==\": \"==\", \"!=\": \"!=\", \">\": \">\", \"<\": \"<\", \">=\": \">=\", \"<=\": \"<=\",\n };\n const op = opMap[opToken.value];\n if (!op) {\n throw new Error(`Expected comparison operator, got ${opToken.type} at line ${opToken.line}, column ${opToken.column}`);\n }\n\n let right: string | number;\n // Check for $variable reference\n if (!this.isAtEnd() && this.peek().type === \"DOLLAR\") {\n this.advance(); // $\n const varName = this.advance();\n right = \"$\" + varName.value;\n } else {\n const rightToken = this.advance();\n if (rightToken.type === \"NUMBER\") {\n right = parseFloat(rightToken.value);\n } else if (rightToken.type === \"STRING\") {\n right = rightToken.value;\n } else if (rightToken.type === \"IDENTIFIER\" || rightToken.type === \"PATH\") {\n let val = rightToken.value;\n while (!this.isAtEnd() && this.peek().type === \"DOT\") {\n this.advance();\n const next = this.advance();\n val += \".\" + next.value;\n }\n right = val;\n } else {\n right = rightToken.value;\n }\n }\n\n return { kind: \"where\", left, op, right };\n }\n\n private parseFieldAccess(): string {\n const first = this.advance();\n let field = first.value;\n while (!this.isAtEnd() && this.peek().type === \"DOT\") {\n this.advance(); // .\n const next = this.advance();\n field += \".\" + next.value;\n }\n return field;\n }\n\n private parseMapBody(): MapExpression {\n // map without braces: either simple field or expression\n if (this.isAtEnd() || this.peek().type === \"PIPE\" || this.peek().type === \"RBRACE\" || this.peek().type === \"NEWLINE\") {\n throw new Error(\"Expected field or expression after 'map'\");\n }\n\n if (this.peek().type !== \"LBRACE\") {\n // map field or map expr (no braces)\n // Try to parse as expression; if it's just a field access, use backward-compat field mode\n const expr = this.parseExpression();\n if (expr.kind === \"field_access\") {\n return { kind: \"map\", field: expr.path };\n }\n return { kind: \"map\", field: \"\", expression: expr };\n }\n\n // map { ... }\n this.advance(); // {\n this.skipNewlines();\n\n // Detect mode: peek ahead to see if first pair uses COLON (expression) or not (legacy)\n if (this.isAtEnd() || this.peek().type === \"RBRACE\") {\n this.advance(); // }\n return { kind: \"map\", field: \"\" };\n }\n\n // Save position to peek ahead\n const savedPos = this.pos;\n // Skip the first key token\n this.advance();\n const hasColon = !this.isAtEnd() && this.peek().type === \"COLON\";\n this.pos = savedPos; // restore\n\n if (hasColon) {\n // Expression mode: map { key: expr, ... }\n // Use Object.create(null) to prevent __proto__ pollution\n const exprMappings: Record<string, Expression> = Object.create(null);\n const seenExprKeys = new Set<string>();\n while (!this.isAtEnd() && this.peek().type !== \"RBRACE\") {\n const keyToken = this.expectKey(\"Expected key in map expression\");\n if (seenExprKeys.has(keyToken.value)) {\n throw new Error(`Duplicate map key '${keyToken.value}' at line ${keyToken.line}, column ${keyToken.column}`);\n }\n seenExprKeys.add(keyToken.value);\n this.expect(\"COLON\", \"Expected ':' after key in map expression\");\n const expr = this.parseExpression();\n exprMappings[keyToken.value] = expr;\n this.skipNewlines();\n if (!this.isAtEnd() && this.peek().type === \"COMMA\") {\n this.advance();\n this.skipNewlines();\n }\n }\n if (this.isAtEnd()) throw new Error(\"Expected '}' to close map expression\");\n this.advance(); // }\n return { kind: \"map\", field: \"\", exprMappings };\n }\n\n // Legacy mode: map { outputKey inputField, outputKey inputField }\n // Use Object.create(null) to prevent __proto__ pollution\n const mappings: Record<string, string> = Object.create(null);\n const seenMapKeys = new Set<string>();\n while (!this.isAtEnd() && this.peek().type !== \"RBRACE\") {\n const key = this.advance();\n if (seenMapKeys.has(key.value)) {\n throw new Error(`Duplicate map key '${key.value}' at line ${key.line}, column ${key.column}`);\n }\n seenMapKeys.add(key.value);\n const field = this.advance();\n mappings[key.value] = field.value;\n this.skipNewlines();\n if (!this.isAtEnd() && this.peek().type === \"COMMA\") {\n this.advance();\n this.skipNewlines();\n }\n }\n if (this.isAtEnd()) throw new Error(\"Expected '}' to close map object\");\n this.advance(); // }\n const firstKey = Object.keys(mappings)[0] ?? \"\";\n return { kind: \"map\", field: firstKey, mappings };\n }\n\n // ── Expression parsing (recursive descent with precedence) ──\n // expr = term (('+' | '-') term)*\n // term = factor (('*' | '/') factor)*\n // factor = '(' expr ')' | $var | literal | fieldAccess\n\n private parseExpression(): Expression {\n let left = this.parseTerm();\n while (!this.isAtEnd() && (this.peek().type === \"PLUS\" || this.peek().type === \"MINUS\")) {\n const opToken = this.advance();\n const right = this.parseTerm();\n left = { kind: \"binary\", op: opToken.value as \"+\" | \"-\", left, right };\n }\n return left;\n }\n\n private parseTerm(): Expression {\n let left = this.parseFactor();\n while (!this.isAtEnd() && (this.peek().type === \"STAR\" || this.peek().type === \"SLASH\")) {\n const opToken = this.advance();\n const right = this.parseFactor();\n left = { kind: \"binary\", op: opToken.value as \"*\" | \"/\", left, right };\n }\n return left;\n }\n\n private parseFactor(): Expression {\n if (this.isAtEnd()) {\n throw new Error(\"Expected expression\");\n }\n const t = this.peek();\n\n // Parenthesized expression\n if (t.type === \"LPAREN\") {\n this.advance(); // (\n const expr = this.parseExpression();\n this.expect(\"RPAREN\", \"Expected ')' after expression\");\n return expr;\n }\n\n // Variable reference: $name\n if (t.type === \"DOLLAR\") {\n this.advance(); // $\n const nameToken = this.expect(\"IDENTIFIER\", \"Expected variable name after '$'\");\n return { kind: \"var_ref\", name: nameToken.value };\n }\n\n // String literal\n if (t.type === \"STRING\") {\n this.advance();\n return { kind: \"literal\", value: t.value };\n }\n\n // Number literal\n if (t.type === \"NUMBER\") {\n this.advance();\n return { kind: \"literal\", value: parseFloat(t.value) };\n }\n\n // Array literal: [expr, expr, ...]\n if (t.type === \"LBRACKET\") {\n this.advance(); // [\n this.skipNewlines();\n const elements: Expression[] = [];\n while (!this.isAtEnd() && this.peek().type !== \"RBRACKET\") {\n elements.push(this.parseExpression());\n this.skipNewlines();\n if (!this.isAtEnd() && this.peek().type === \"COMMA\") {\n this.advance(); // ,\n this.skipNewlines();\n }\n }\n this.expect(\"RBRACKET\", \"Expected ']' after array literal\");\n return { kind: \"array_literal\", elements };\n }\n\n // Object literal: { key: expr, key: expr, ... }\n if (t.type === \"LBRACE\") {\n this.advance(); // {\n this.skipNewlines();\n const properties: Record<string, Expression> = {};\n while (!this.isAtEnd() && this.peek().type !== \"RBRACE\") {\n const keyToken = this.expectKey(\"Expected property name in object literal\");\n this.expect(\"COLON\", \"Expected ':' after property name\");\n properties[keyToken.value] = this.parseExpression();\n this.skipNewlines();\n if (!this.isAtEnd() && this.peek().type === \"COMMA\") {\n this.advance(); // ,\n this.skipNewlines();\n }\n }\n this.expect(\"RBRACE\", \"Expected '}' after object literal\");\n return { kind: \"object_literal\", properties };\n }\n\n // Field access: identifier (possibly dotted)\n if (t.type === \"IDENTIFIER\") {\n let field = this.advance().value;\n while (!this.isAtEnd() && this.peek().type === \"DOT\") {\n this.advance(); // .\n const next = this.advance();\n field += \".\" + next.value;\n }\n return { kind: \"field_access\", path: field };\n }\n\n throw new Error(`Unexpected token in expression: ${t.type} \"${t.value}\" at line ${t.line}, column ${t.column}`);\n }\n\n private parseAction(): ActionExpression {\n const actionToken = this.advance(); // action\n if (this.isAtEnd()) {\n throw new Error(`Expected path or action name after 'action' at line ${actionToken.line}, column ${actionToken.column}`);\n }\n\n const nextToken = this.peek();\n let path: string;\n let relative: boolean | undefined;\n\n if (nextToken.type === \"PATH\") {\n // Absolute action: action /tesla/.actions/honk\n path = this.advance().value;\n } else if (nextToken.type === \"IDENTIFIER\") {\n // Relative action: action turn_off\n path = this.advance().value;\n relative = true;\n } else {\n throw new Error(`Expected path or action name after 'action' at line ${actionToken.line}, column ${actionToken.column}`);\n }\n\n let params: Record<string, unknown> | undefined;\n\n // Optional params: { key: value, ... }\n if (!this.isAtEnd() && this.peek().type === \"LBRACE\") {\n this.advance(); // {\n params = {};\n this.skipNewlines();\n while (!this.isAtEnd() && this.peek().type !== \"RBRACE\") {\n const keyToken = this.expect(\"IDENTIFIER\", \"Expected parameter name in action params\");\n this.expect(\"COLON\", \"Expected ':' after parameter name\");\n if (this.isAtEnd()) {\n throw new Error(`Expected value after ':' at line ${keyToken.line}, column ${keyToken.column}`);\n }\n // Check for json() wrapper\n if (this.peek().type === \"IDENTIFIER\" && this.peek().value === \"json\") {\n const jsonToken = this.advance(); // consume \"json\"\n this.expect(\"LPAREN\", `Expected '(' after json at line ${jsonToken.line}, column ${jsonToken.column}`);\n params[keyToken.value] = this.parseJsonValue();\n this.expect(\"RPAREN\", \"Expected ')' to close json()\");\n } else {\n const valToken = this.advance();\n if (valToken.type === \"STRING\") {\n params[keyToken.value] = valToken.value;\n } else if (valToken.type === \"NUMBER\") {\n params[keyToken.value] = parseFloat(valToken.value);\n } else {\n throw new Error(`Expected string or number value for parameter '${keyToken.value}' at line ${valToken.line}, column ${valToken.column}`);\n }\n }\n this.skipNewlines();\n if (!this.isAtEnd() && this.peek().type === \"COMMA\") {\n this.advance();\n this.skipNewlines();\n }\n }\n if (this.isAtEnd()) throw new Error(\"Expected '}' to close action params\");\n this.advance(); // }\n }\n\n return { kind: \"action\", path, relative, params };\n }\n\n private parseRoute(): RouteExpression {\n const routeToken = this.advance(); // route\n if (this.isAtEnd() || (this.peek().type !== \"IDENTIFIER\" && this.peek().type !== \"DOT\")) {\n throw new Error(`Expected field name after 'route' at line ${routeToken.line}, column ${routeToken.column}`);\n }\n const field = this.parseFieldAccess();\n this.expect(\"LBRACE\", \"Expected '{' after route field\");\n this.skipNewlines();\n\n const branches: RouteBranch[] = [];\n let fallback: string | undefined;\n\n while (!this.isAtEnd() && this.peek().type !== \"RBRACE\") {\n // Each branch: \"value\" -> job target OR _ -> job target\n let value: string;\n if (this.peek().type === \"STRING\") {\n value = this.advance().value;\n } else if (this.peek().type === \"IDENTIFIER\" && this.peek().value === \"_\") {\n value = \"_\";\n this.advance();\n } else {\n throw new Error(`Expected string value or '_' in route branch at line ${this.peek().line}, column ${this.peek().column}`);\n }\n\n this.expect(\"ARROW\", \"Expected '->' in route branch\");\n this.expect(\"JOB\", \"Expected 'job' keyword in route branch target\");\n const targetToken = this.advance(); // job name\n\n if (value === \"_\") {\n fallback = targetToken.value;\n } else {\n branches.push({ value, targetJob: targetToken.value });\n }\n\n this.skipNewlines();\n if (!this.isAtEnd() && this.peek().type === \"COMMA\") {\n this.advance();\n this.skipNewlines();\n }\n }\n\n if (branches.length === 0 && !fallback) {\n throw new Error(`Route must have at least one branch at line ${routeToken.line}, column ${routeToken.column}`);\n }\n\n if (this.isAtEnd()) throw new Error(\"Expected '}' to close route\");\n this.advance(); // }\n\n return { kind: \"route\", field, branches, fallback };\n }\n\n private parseLookup(): LookupExpression {\n const lookupToken = this.advance(); // lookup\n if (this.isAtEnd() || this.peek().type !== \"PATH\") {\n throw new Error(`Expected path after 'lookup' at line ${lookupToken.line}, column ${lookupToken.column}`);\n }\n const pathToken = this.advance();\n // Expect \"on\" keyword\n if (this.isAtEnd() || this.peek().type !== \"ON\") {\n throw new Error(`Expected 'on' keyword after lookup path at line ${lookupToken.line}, column ${lookupToken.column}`);\n }\n this.advance(); // on\n const joinKey = this.parseFieldAccess();\n return { kind: \"lookup\", path: pathToken.value, joinKey };\n }\n\n private parseFanout(): PipelineStage {\n this.expect(\"LBRACE\", \"Expected '{' after 'fanout'\");\n const branches: PipelineStage[][] = [];\n\n this.skipNewlines();\n while (!this.isAtEnd() && this.peek().type !== \"RBRACE\") {\n // Each branch is a pipeline until COMMA or RBRACE\n const branch: PipelineStage[] = [];\n while (!this.isAtEnd() && this.peek().type !== \"COMMA\" && this.peek().type !== \"RBRACE\" && this.peek().type !== \"NEWLINE\") {\n if (this.peek().type === \"PIPE\") {\n this.advance();\n }\n branch.push(this.parseStage());\n }\n branches.push(branch);\n this.skipNewlines();\n if (!this.isAtEnd() && this.peek().type === \"COMMA\") {\n this.advance();\n this.skipNewlines();\n }\n }\n\n if (this.isAtEnd()) throw new Error(\"Expected '}' to close fanout\");\n this.advance(); // }\n\n return { kind: \"fanout\", branches };\n }\n\n /** Recursive descent JSON value parser using existing lexer tokens. */\n private parseJsonValue(): unknown {\n if (this.isAtEnd()) throw new Error(\"Expected JSON value (unexpected EOF)\");\n const t = this.peek();\n\n // Object: { ... }\n if (t.type === \"LBRACE\") {\n this.advance(); // {\n const obj: Record<string, unknown> = {};\n this.skipNewlines();\n while (!this.isAtEnd() && this.peek().type !== \"RBRACE\") {\n const keyToken = this.advance();\n if (keyToken.type !== \"STRING\" && keyToken.type !== \"IDENTIFIER\") {\n throw new Error(`Expected string key in JSON object at line ${keyToken.line}, column ${keyToken.column}`);\n }\n this.expect(\"COLON\", \"Expected ':' after key in JSON object\");\n obj[keyToken.value] = this.parseJsonValue();\n this.skipNewlines();\n if (!this.isAtEnd() && this.peek().type === \"COMMA\") {\n this.advance();\n this.skipNewlines();\n }\n }\n if (this.isAtEnd()) throw new Error(\"Expected '}' to close JSON object\");\n this.advance(); // }\n return obj;\n }\n\n // Array: [ ... ]\n if (t.type === \"LBRACKET\") {\n this.advance(); // [\n const arr: unknown[] = [];\n this.skipNewlines();\n while (!this.isAtEnd() && this.peek().type !== \"RBRACKET\") {\n arr.push(this.parseJsonValue());\n this.skipNewlines();\n if (!this.isAtEnd() && this.peek().type === \"COMMA\") {\n this.advance();\n this.skipNewlines();\n }\n }\n if (this.isAtEnd()) throw new Error(\"Expected ']' to close JSON array\");\n this.advance(); // ]\n return arr;\n }\n\n // String\n if (t.type === \"STRING\") {\n this.advance();\n return t.value;\n }\n\n // Number\n if (t.type === \"NUMBER\") {\n this.advance();\n return parseFloat(t.value);\n }\n\n // Boolean / null: true, false, null are lexed as IDENTIFIER\n if (t.type === \"IDENTIFIER\") {\n if (t.value === \"true\") { this.advance(); return true; }\n if (t.value === \"false\") { this.advance(); return false; }\n if (t.value === \"null\") { this.advance(); return null; }\n }\n\n throw new Error(`Unexpected token in json(): ${t.type} \"${t.value}\" at line ${t.line}, column ${t.column}`);\n }\n\n private peek(): Token {\n return this.tokens[this.pos];\n }\n\n private advance(): Token {\n return this.tokens[this.pos++];\n }\n\n /** Keywords that are valid as object/map keys (all ASH keywords). */\n private static readonly KEYWORD_TYPES: ReadonlySet<string> = new Set([\n \"JOB\", \"FIND\", \"WHERE\", \"MAP\", \"COUNT\", \"SAVE\", \"PUBLISH\", \"TEE\", \"FANOUT\",\n \"ACTION\", \"LET\", \"PARAM\", \"OUTPUT\", \"ON\", \"IN\", \"EXEC\", \"DELETE\",\n ]);\n\n /**\n * Expect an identifier or keyword token to use as an object/map key.\n * Keywords like `job`, `action`, `find` etc. are valid key names.\n */\n private expectKey(message: string): Token {\n if (this.isAtEnd()) throw new Error(message + \" (unexpected EOF)\");\n const t = this.peek();\n if (t.type === \"IDENTIFIER\" || AshParser.KEYWORD_TYPES.has(t.type)) {\n return this.advance();\n }\n throw new Error(`${message}, got ${t.type} at line ${t.line}, column ${t.column}`);\n }\n\n private expect(type: TokenType, message: string): Token {\n if (this.isAtEnd()) throw new Error(message + \" (unexpected EOF)\");\n const t = this.peek();\n if (t.type !== type) {\n throw new Error(`${message}, got ${t.type} at line ${t.line}, column ${t.column}`);\n }\n return this.advance();\n }\n\n private isAtEnd(): boolean {\n return this.pos >= this.tokens.length || this.tokens[this.pos].type === \"EOF\";\n }\n\n private skipNewlines(): void {\n while (!this.isAtEnd() && this.peek().type === \"NEWLINE\") {\n this.pos++;\n }\n }\n}\n"],"mappings":"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"}
|