@aigne/ash 0.0.2-beta.0 → 0.0.2-beta.1

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/ast.d.cts CHANGED
@@ -7,8 +7,8 @@ interface Annotation {
7
7
  }
8
8
  interface QueryCondition {
9
9
  field: string;
10
- op: "==" | "!=" | ">" | "<" | ">=" | "<=";
11
- value: string | number;
10
+ op: "==" | "!=" | ">" | "<" | ">=" | "<=" | "in";
11
+ value: string | number | (string | number)[];
12
12
  }
13
13
  interface FindExpression {
14
14
  kind: "find";
@@ -18,8 +18,8 @@ interface FindExpression {
18
18
  interface WhereClause {
19
19
  kind: "where";
20
20
  left: string;
21
- op: "==" | "!=" | ">" | "<" | ">=" | "<=";
22
- right: string | number;
21
+ op: "==" | "!=" | ">" | "<" | ">=" | "<=" | "in";
22
+ right: string | number | (string | number)[];
23
23
  }
24
24
  interface BinaryExpression {
25
25
  kind: "binary";
package/dist/ast.d.mts CHANGED
@@ -7,8 +7,8 @@ interface Annotation {
7
7
  }
8
8
  interface QueryCondition {
9
9
  field: string;
10
- op: "==" | "!=" | ">" | "<" | ">=" | "<=";
11
- value: string | number;
10
+ op: "==" | "!=" | ">" | "<" | ">=" | "<=" | "in";
11
+ value: string | number | (string | number)[];
12
12
  }
13
13
  interface FindExpression {
14
14
  kind: "find";
@@ -18,8 +18,8 @@ interface FindExpression {
18
18
  interface WhereClause {
19
19
  kind: "where";
20
20
  left: string;
21
- op: "==" | "!=" | ">" | "<" | ">=" | "<=";
22
- right: string | number;
21
+ op: "==" | "!=" | ">" | "<" | ">=" | "<=" | "in";
22
+ right: string | number | (string | number)[];
23
23
  }
24
24
  interface BinaryExpression {
25
25
  kind: "binary";
package/dist/compiler.cjs CHANGED
@@ -707,6 +707,16 @@ var AshCompiler = class {
707
707
  }
708
708
  }
709
709
  resolveQueryVars(query, variables) {
710
+ if (query.op === "in" && typeof query.value === "string" && /^\$[a-zA-Z_]\w*$/.test(query.value)) {
711
+ const varName = query.value.slice(1);
712
+ if (!variables.has(varName)) throw new Error(`Undefined variable: $${varName}`);
713
+ const val = variables.get(varName);
714
+ const value = Array.isArray(val) ? val : [val];
715
+ return {
716
+ ...query,
717
+ value
718
+ };
719
+ }
710
720
  if (typeof query.value === "string" && /^\$[a-zA-Z_]\w*$/.test(query.value)) {
711
721
  const varName = query.value.slice(1);
712
722
  if (!variables.has(varName)) throw new Error(`Undefined variable: $${varName}`);
@@ -718,6 +728,16 @@ var AshCompiler = class {
718
728
  return query;
719
729
  }
720
730
  resolveWhereVars(clause, variables) {
731
+ if (clause.op === "in" && typeof clause.right === "string" && /^\$[a-zA-Z_]\w*$/.test(clause.right)) {
732
+ const varName = clause.right.slice(1);
733
+ if (!variables.has(varName)) throw new Error(`Undefined variable: $${varName}`);
734
+ const val = variables.get(varName);
735
+ const right = Array.isArray(val) ? val : [val];
736
+ return {
737
+ ...clause,
738
+ right
739
+ };
740
+ }
721
741
  if (typeof clause.right === "string" && /^\$[a-zA-Z_]\w*$/.test(clause.right)) {
722
742
  const varName = clause.right.slice(1);
723
743
  if (!variables.has(varName)) throw new Error(`Undefined variable: $${varName}`);
@@ -734,6 +754,7 @@ var AshCompiler = class {
734
754
  switch (clause.op) {
735
755
  case "==": return strictEqual(left, right);
736
756
  case "!=": return !strictEqual(left, right);
757
+ case "in": return (Array.isArray(right) ? right : [right]).some((v) => strictEqual(left, v));
737
758
  case ">":
738
759
  case "<":
739
760
  case ">=":
@@ -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,QA+MM,YAAA;EAAA,QA2SN,gBAAA;EAAA,QAWA,gBAAA;EAAA,QAYA,aAAA;EAAA,QAwBA,YAAA;EAAA,QAWA,kBAAA;EAAA,QA+CM,aAAA;AAAA"}
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,QA+MM,YAAA;EAAA,QA2SN,gBAAA;EAAA,QAqBA,gBAAA;EAAA,QAuBA,aAAA;EAAA,QA6BA,YAAA;EAAA,QAWA,kBAAA;EAAA,QA+CM,aAAA;AAAA"}
@@ -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,QA+MM,YAAA;EAAA,QA2SN,gBAAA;EAAA,QAWA,gBAAA;EAAA,QAYA,aAAA;EAAA,QAwBA,YAAA;EAAA,QAWA,kBAAA;EAAA,QA+CM,aAAA;AAAA"}
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,QA+MM,YAAA;EAAA,QA2SN,gBAAA;EAAA,QAqBA,gBAAA;EAAA,QAuBA,aAAA;EAAA,QA6BA,YAAA;EAAA,QAWA,kBAAA;EAAA,QA+CM,aAAA;AAAA"}
package/dist/compiler.mjs CHANGED
@@ -707,6 +707,16 @@ var AshCompiler = class {
707
707
  }
708
708
  }
709
709
  resolveQueryVars(query, variables) {
710
+ if (query.op === "in" && typeof query.value === "string" && /^\$[a-zA-Z_]\w*$/.test(query.value)) {
711
+ const varName = query.value.slice(1);
712
+ if (!variables.has(varName)) throw new Error(`Undefined variable: $${varName}`);
713
+ const val = variables.get(varName);
714
+ const value = Array.isArray(val) ? val : [val];
715
+ return {
716
+ ...query,
717
+ value
718
+ };
719
+ }
710
720
  if (typeof query.value === "string" && /^\$[a-zA-Z_]\w*$/.test(query.value)) {
711
721
  const varName = query.value.slice(1);
712
722
  if (!variables.has(varName)) throw new Error(`Undefined variable: $${varName}`);
@@ -718,6 +728,16 @@ var AshCompiler = class {
718
728
  return query;
719
729
  }
720
730
  resolveWhereVars(clause, variables) {
731
+ if (clause.op === "in" && typeof clause.right === "string" && /^\$[a-zA-Z_]\w*$/.test(clause.right)) {
732
+ const varName = clause.right.slice(1);
733
+ if (!variables.has(varName)) throw new Error(`Undefined variable: $${varName}`);
734
+ const val = variables.get(varName);
735
+ const right = Array.isArray(val) ? val : [val];
736
+ return {
737
+ ...clause,
738
+ right
739
+ };
740
+ }
721
741
  if (typeof clause.right === "string" && /^\$[a-zA-Z_]\w*$/.test(clause.right)) {
722
742
  const varName = clause.right.slice(1);
723
743
  if (!variables.has(varName)) throw new Error(`Undefined variable: $${varName}`);
@@ -734,6 +754,7 @@ var AshCompiler = class {
734
754
  switch (clause.op) {
735
755
  case "==": return strictEqual(left, right);
736
756
  case "!=": return !strictEqual(left, right);
757
+ case "in": return (Array.isArray(right) ? right : [right]).some((v) => strictEqual(left, v));
737
758
  case ">":
738
759
  case "<":
739
760
  case ">=":
@@ -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>; // 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>();\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>(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>, 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> = 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 runtimeVars.set(rtLet.name, 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> = 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>): QueryCondition {\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>): WhereClause {\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 \">\":\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>): 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> = 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>; // 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>();\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>(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>, 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> = 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 runtimeVars.set(rtLet.name, 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> = 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>): 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>): 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>): 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> = 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/lexer.cjs CHANGED
@@ -17,7 +17,8 @@ const KEYWORDS = {
17
17
  route: "ROUTE",
18
18
  lookup: "LOOKUP",
19
19
  param: "PARAM",
20
- on: "ON"
20
+ on: "ON",
21
+ in: "IN"
21
22
  };
22
23
  var AshLexer = class {
23
24
  tokenize(source) {
package/dist/lexer.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  //#region src/lexer.d.ts
2
- type TokenType = "JOB" | "FIND" | "WHERE" | "MAP" | "SAVE" | "PUBLISH" | "TEE" | "FANOUT" | "INPUT" | "OUTPUT" | "ACTION" | "ROUTE" | "LOOKUP" | "ARROW" | "PLUS" | "MINUS" | "STAR" | "SLASH" | "PIPE" | "ASSIGN" | "DOT" | "COMMA" | "COLON" | "LPAREN" | "RPAREN" | "LBRACKET" | "RBRACKET" | "LBRACE" | "RBRACE" | "IDENTIFIER" | "STRING" | "NUMBER" | "PATH" | "AT" | "GT" | "LT" | "GTE" | "LTE" | "EQ" | "NEQ" | "LET" | "PARAM" | "ON" | "DOLLAR" | "COUNT" | "GROUP_BY" | "NEWLINE" | "EOF";
2
+ type TokenType = "JOB" | "FIND" | "WHERE" | "MAP" | "SAVE" | "PUBLISH" | "TEE" | "FANOUT" | "INPUT" | "OUTPUT" | "ACTION" | "ROUTE" | "LOOKUP" | "ARROW" | "IN" | "PLUS" | "MINUS" | "STAR" | "SLASH" | "PIPE" | "ASSIGN" | "DOT" | "COMMA" | "COLON" | "LPAREN" | "RPAREN" | "LBRACKET" | "RBRACKET" | "LBRACE" | "RBRACE" | "IDENTIFIER" | "STRING" | "NUMBER" | "PATH" | "AT" | "GT" | "LT" | "GTE" | "LTE" | "EQ" | "NEQ" | "LET" | "PARAM" | "ON" | "DOLLAR" | "COUNT" | "GROUP_BY" | "NEWLINE" | "EOF";
3
3
  interface Token {
4
4
  type: TokenType;
5
5
  value: string;
@@ -1 +1 @@
1
- {"version":3,"file":"lexer.d.cts","names":[],"sources":["../src/lexer.ts"],"mappings":";KAAY,SAAA;AAAA,UAWK,KAAA;EACf,IAAA,EAAM,SAAA;EACN,KAAA;EACA,IAAA;EACA,MAAA;AAAA;AAAA,cAuBW,QAAA;EACX,QAAA,CAAS,MAAA,WAAiB,KAAA;AAAA"}
1
+ {"version":3,"file":"lexer.d.cts","names":[],"sources":["../src/lexer.ts"],"mappings":";KAAY,SAAA;AAAA,UAWK,KAAA;EACf,IAAA,EAAM,SAAA;EACN,KAAA;EACA,IAAA;EACA,MAAA;AAAA;AAAA,cAwBW,QAAA;EACX,QAAA,CAAS,MAAA,WAAiB,KAAA;AAAA"}
package/dist/lexer.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  //#region src/lexer.d.ts
2
- type TokenType = "JOB" | "FIND" | "WHERE" | "MAP" | "SAVE" | "PUBLISH" | "TEE" | "FANOUT" | "INPUT" | "OUTPUT" | "ACTION" | "ROUTE" | "LOOKUP" | "ARROW" | "PLUS" | "MINUS" | "STAR" | "SLASH" | "PIPE" | "ASSIGN" | "DOT" | "COMMA" | "COLON" | "LPAREN" | "RPAREN" | "LBRACKET" | "RBRACKET" | "LBRACE" | "RBRACE" | "IDENTIFIER" | "STRING" | "NUMBER" | "PATH" | "AT" | "GT" | "LT" | "GTE" | "LTE" | "EQ" | "NEQ" | "LET" | "PARAM" | "ON" | "DOLLAR" | "COUNT" | "GROUP_BY" | "NEWLINE" | "EOF";
2
+ type TokenType = "JOB" | "FIND" | "WHERE" | "MAP" | "SAVE" | "PUBLISH" | "TEE" | "FANOUT" | "INPUT" | "OUTPUT" | "ACTION" | "ROUTE" | "LOOKUP" | "ARROW" | "IN" | "PLUS" | "MINUS" | "STAR" | "SLASH" | "PIPE" | "ASSIGN" | "DOT" | "COMMA" | "COLON" | "LPAREN" | "RPAREN" | "LBRACKET" | "RBRACKET" | "LBRACE" | "RBRACE" | "IDENTIFIER" | "STRING" | "NUMBER" | "PATH" | "AT" | "GT" | "LT" | "GTE" | "LTE" | "EQ" | "NEQ" | "LET" | "PARAM" | "ON" | "DOLLAR" | "COUNT" | "GROUP_BY" | "NEWLINE" | "EOF";
3
3
  interface Token {
4
4
  type: TokenType;
5
5
  value: string;
@@ -1 +1 @@
1
- {"version":3,"file":"lexer.d.mts","names":[],"sources":["../src/lexer.ts"],"mappings":";KAAY,SAAA;AAAA,UAWK,KAAA;EACf,IAAA,EAAM,SAAA;EACN,KAAA;EACA,IAAA;EACA,MAAA;AAAA;AAAA,cAuBW,QAAA;EACX,QAAA,CAAS,MAAA,WAAiB,KAAA;AAAA"}
1
+ {"version":3,"file":"lexer.d.mts","names":[],"sources":["../src/lexer.ts"],"mappings":";KAAY,SAAA;AAAA,UAWK,KAAA;EACf,IAAA,EAAM,SAAA;EACN,KAAA;EACA,IAAA;EACA,MAAA;AAAA;AAAA,cAwBW,QAAA;EACX,QAAA,CAAS,MAAA,WAAiB,KAAA;AAAA"}
package/dist/lexer.mjs CHANGED
@@ -16,7 +16,8 @@ const KEYWORDS = {
16
16
  route: "ROUTE",
17
17
  lookup: "LOOKUP",
18
18
  param: "PARAM",
19
- on: "ON"
19
+ on: "ON",
20
+ in: "IN"
20
21
  };
21
22
  var AshLexer = class {
22
23
  tokenize(source) {
@@ -1 +1 @@
1
- {"version":3,"file":"lexer.mjs","names":[],"sources":["../src/lexer.ts"],"sourcesContent":["export type TokenType =\n | \"JOB\" | \"FIND\" | \"WHERE\" | \"MAP\" | \"SAVE\" | \"PUBLISH\" | \"TEE\" | \"FANOUT\" | \"INPUT\" | \"OUTPUT\"\n | \"ACTION\" | \"ROUTE\" | \"LOOKUP\" | \"ARROW\"\n | \"PLUS\" | \"MINUS\" | \"STAR\" | \"SLASH\"\n | \"PIPE\" | \"ASSIGN\" | \"DOT\" | \"COMMA\" | \"COLON\"\n | \"LPAREN\" | \"RPAREN\" | \"LBRACKET\" | \"RBRACKET\" | \"LBRACE\" | \"RBRACE\"\n | \"IDENTIFIER\" | \"STRING\" | \"NUMBER\" | \"PATH\" | \"AT\"\n | \"GT\" | \"LT\" | \"GTE\" | \"LTE\" | \"EQ\" | \"NEQ\"\n | \"LET\" | \"PARAM\" | \"ON\" | \"DOLLAR\" | \"COUNT\" | \"GROUP_BY\"\n | \"NEWLINE\" | \"EOF\";\n\nexport interface Token {\n type: TokenType;\n value: string;\n line: number;\n column: number;\n}\n\nconst KEYWORDS: Record<string, TokenType> = {\n job: \"JOB\",\n find: \"FIND\",\n where: \"WHERE\",\n map: \"MAP\",\n save: \"SAVE\",\n publish: \"PUBLISH\",\n tee: \"TEE\",\n fanout: \"FANOUT\",\n input: \"INPUT\",\n output: \"OUTPUT\",\n let: \"LET\",\n count: \"COUNT\",\n action: \"ACTION\",\n route: \"ROUTE\",\n lookup: \"LOOKUP\",\n param: \"PARAM\",\n on: \"ON\",\n};\n\nexport class AshLexer {\n tokenize(source: string): Token[] {\n const tokens: Token[] = [];\n let pos = 0;\n let line = 1;\n let col = 1;\n\n while (pos < source.length) {\n const ch = source[pos];\n\n // Newline\n if (ch === \"\\n\" || ch === \"\\r\") {\n if (ch === \"\\r\" && source[pos + 1] === \"\\n\") pos++;\n tokens.push({ type: \"NEWLINE\", value: \"\\\\n\", line, column: col });\n pos++;\n line++;\n col = 1;\n continue;\n }\n\n // Whitespace (skip)\n if (ch === \" \" || ch === \"\\t\") {\n pos++;\n col++;\n continue;\n }\n\n // Comment: # to end of line\n if (ch === \"#\") {\n while (pos < source.length && source[pos] !== \"\\n\" && source[pos] !== \"\\r\") {\n pos++;\n col++;\n }\n continue;\n }\n\n // String literal\n if (ch === '\"') {\n const startCol = col;\n pos++; col++;\n let value = \"\";\n while (pos < source.length && source[pos] !== '\"') {\n if (source[pos] === \"\\\\\") {\n pos++; col++;\n if (pos >= source.length) break;\n const escaped = source[pos];\n if (escaped === '\"') value += '\"';\n else if (escaped === \"\\\\\") value += \"\\\\\";\n else if (escaped === \"n\") value += \"\\n\";\n else if (escaped === \"t\") value += \"\\t\";\n else if (escaped === \"$\") value += \"\\\\$\"; // preserve for template escape detection\n else value += escaped;\n } else {\n if (source[pos] === \"\\n\") {\n throw new Error(`Unterminated string at line ${line}, column ${startCol}`);\n }\n value += source[pos];\n }\n pos++; col++;\n }\n if (pos >= source.length) {\n throw new Error(`Unterminated string at line ${line}, column ${startCol}`);\n }\n pos++; col++; // closing quote\n tokens.push({ type: \"STRING\", value, line, column: startCol });\n continue;\n }\n\n // Number\n if (ch >= \"0\" && ch <= \"9\") {\n const startCol = col;\n let num = \"\";\n while (pos < source.length && ((source[pos] >= \"0\" && source[pos] <= \"9\") || source[pos] === \".\")) {\n num += source[pos];\n pos++; col++;\n }\n tokens.push({ type: \"NUMBER\", value: num, line, column: startCol });\n continue;\n }\n\n // Path or SLASH: `/` followed by a letter, `.`, `_`, or `/` starts a PATH; otherwise SLASH\n if (ch === \"/\") {\n const next = source[pos + 1];\n if (next !== undefined && ((next >= \"a\" && next <= \"z\") || (next >= \"A\" && next <= \"Z\") || next === \"_\" || next === \".\" || next === \"/\")) {\n const startCol = col;\n let path = \"\";\n while (pos < source.length && source[pos] !== \" \" && source[pos] !== \"\\t\" && source[pos] !== \"\\n\" && source[pos] !== \"\\r\" && source[pos] !== \"|\" && source[pos] !== \"}\" && source[pos] !== \")\" && source[pos] !== \",\" && source[pos] !== \":\") {\n // Handle ${...} template blocks atomically — don't stop at } inside template\n if (source[pos] === \"$\" && pos + 1 < source.length && source[pos + 1] === \"{\") {\n path += source[pos]; pos++; col++; // $\n path += source[pos]; pos++; col++; // {\n while (pos < source.length && source[pos] !== \"}\") {\n path += source[pos]; pos++; col++;\n }\n if (pos < source.length) {\n path += source[pos]; pos++; col++; // closing }\n }\n continue;\n }\n path += source[pos];\n pos++; col++;\n }\n tokens.push({ type: \"PATH\", value: path, line, column: startCol });\n continue;\n }\n tokens.push({ type: \"SLASH\", value: \"/\", line, column: col }); pos++; col++; continue;\n }\n\n // Identifier / keyword\n if ((ch >= \"a\" && ch <= \"z\") || (ch >= \"A\" && ch <= \"Z\") || ch === \"_\") {\n const startCol = col;\n let ident = \"\";\n while (pos < source.length && ((source[pos] >= \"a\" && source[pos] <= \"z\") || (source[pos] >= \"A\" && source[pos] <= \"Z\") || (source[pos] >= \"0\" && source[pos] <= \"9\") || source[pos] === \"_\")) {\n ident += source[pos];\n pos++; col++;\n }\n // Handle compound keyword: group-by\n if (ident === \"group\" && pos < source.length && source[pos] === \"-\") {\n const rest = source.slice(pos + 1, pos + 3);\n if (rest === \"by\") {\n pos += 3; col += 3;\n tokens.push({ type: \"GROUP_BY\", value: \"group-by\", line, column: startCol });\n continue;\n }\n }\n const kw = Object.hasOwn(KEYWORDS, ident) ? KEYWORDS[ident] : undefined;\n tokens.push({ type: kw ?? \"IDENTIFIER\", value: ident, line, column: startCol });\n continue;\n }\n\n // Operators and punctuation\n // Arithmetic operators\n if (ch === \"+\") { tokens.push({ type: \"PLUS\", value: \"+\", line, column: col }); pos++; col++; continue; }\n if (ch === \"-\") {\n if (source[pos + 1] === \">\") {\n tokens.push({ type: \"ARROW\", value: \"->\", line, column: col }); pos += 2; col += 2; continue;\n }\n tokens.push({ type: \"MINUS\", value: \"-\", line, column: col }); pos++; col++; continue;\n }\n if (ch === \"*\") { tokens.push({ type: \"STAR\", value: \"*\", line, column: col }); pos++; col++; continue; }\n\n if (ch === \"|\") { tokens.push({ type: \"PIPE\", value: \"|\", line, column: col }); pos++; col++; continue; }\n if (ch === \"=\") {\n if (source[pos + 1] === \"=\") {\n tokens.push({ type: \"EQ\", value: \"==\", line, column: col }); pos += 2; col += 2; continue;\n }\n tokens.push({ type: \"ASSIGN\", value: \"=\", line, column: col }); pos++; col++; continue;\n }\n if (ch === \"!\") {\n if (source[pos + 1] === \"=\") {\n tokens.push({ type: \"NEQ\", value: \"!=\", line, column: col }); pos += 2; col += 2; continue;\n }\n }\n if (ch === \">\") {\n if (source[pos + 1] === \"=\") {\n tokens.push({ type: \"GTE\", value: \">=\", line, column: col }); pos += 2; col += 2; continue;\n }\n tokens.push({ type: \"GT\", value: \">\", line, column: col }); pos++; col++; continue;\n }\n if (ch === \"<\") {\n if (source[pos + 1] === \"=\") {\n tokens.push({ type: \"LTE\", value: \"<=\", line, column: col }); pos += 2; col += 2; continue;\n }\n tokens.push({ type: \"LT\", value: \"<\", line, column: col }); pos++; col++; continue;\n }\n if (ch === \".\") { tokens.push({ type: \"DOT\", value: \".\", line, column: col }); pos++; col++; continue; }\n if (ch === \",\") { tokens.push({ type: \"COMMA\", value: \",\", line, column: col }); pos++; col++; continue; }\n if (ch === \"(\") { tokens.push({ type: \"LPAREN\", value: \"(\", line, column: col }); pos++; col++; continue; }\n if (ch === \")\") { tokens.push({ type: \"RPAREN\", value: \")\", line, column: col }); pos++; col++; continue; }\n if (ch === \"[\") { tokens.push({ type: \"LBRACKET\", value: \"[\", line, column: col }); pos++; col++; continue; }\n if (ch === \"]\") { tokens.push({ type: \"RBRACKET\", value: \"]\", line, column: col }); pos++; col++; continue; }\n if (ch === \"{\") { tokens.push({ type: \"LBRACE\", value: \"{\", line, column: col }); pos++; col++; continue; }\n if (ch === \"}\") { tokens.push({ type: \"RBRACE\", value: \"}\", line, column: col }); pos++; col++; continue; }\n if (ch === \"@\") { tokens.push({ type: \"AT\", value: \"@\", line, column: col }); pos++; col++; continue; }\n if (ch === \"$\") { tokens.push({ type: \"DOLLAR\", value: \"$\", line, column: col }); pos++; col++; continue; }\n if (ch === \":\") { tokens.push({ type: \"COLON\", value: \":\", line, column: col }); pos++; col++; continue; }\n\n throw new Error(`Unrecognized character '${ch}' at line ${line}, column ${col}`);\n }\n\n tokens.push({ type: \"EOF\", value: \"\", line, column: col });\n return tokens;\n }\n}\n"],"mappings":";AAkBA,MAAM,WAAsC;CAC1C,KAAK;CACL,MAAM;CACN,OAAO;CACP,KAAK;CACL,MAAM;CACN,SAAS;CACT,KAAK;CACL,QAAQ;CACR,OAAO;CACP,QAAQ;CACR,KAAK;CACL,OAAO;CACP,QAAQ;CACR,OAAO;CACP,QAAQ;CACR,OAAO;CACP,IAAI;CACL;AAED,IAAa,WAAb,MAAsB;CACpB,SAAS,QAAyB;EAChC,MAAM,SAAkB,EAAE;EAC1B,IAAI,MAAM;EACV,IAAI,OAAO;EACX,IAAI,MAAM;AAEV,SAAO,MAAM,OAAO,QAAQ;GAC1B,MAAM,KAAK,OAAO;AAGlB,OAAI,OAAO,QAAQ,OAAO,MAAM;AAC9B,QAAI,OAAO,QAAQ,OAAO,MAAM,OAAO,KAAM;AAC7C,WAAO,KAAK;KAAE,MAAM;KAAW,OAAO;KAAO;KAAM,QAAQ;KAAK,CAAC;AACjE;AACA;AACA,UAAM;AACN;;AAIF,OAAI,OAAO,OAAO,OAAO,KAAM;AAC7B;AACA;AACA;;AAIF,OAAI,OAAO,KAAK;AACd,WAAO,MAAM,OAAO,UAAU,OAAO,SAAS,QAAQ,OAAO,SAAS,MAAM;AAC1E;AACA;;AAEF;;AAIF,OAAI,OAAO,MAAK;IACd,MAAM,WAAW;AACjB;AAAO;IACP,IAAI,QAAQ;AACZ,WAAO,MAAM,OAAO,UAAU,OAAO,SAAS,MAAK;AACjD,SAAI,OAAO,SAAS,MAAM;AACxB;AAAO;AACP,UAAI,OAAO,OAAO,OAAQ;MAC1B,MAAM,UAAU,OAAO;AACvB,UAAI,YAAY,KAAK,UAAS;eACrB,YAAY,KAAM,UAAS;eAC3B,YAAY,IAAK,UAAS;eAC1B,YAAY,IAAK,UAAS;eAC1B,YAAY,IAAK,UAAS;UAC9B,UAAS;YACT;AACL,UAAI,OAAO,SAAS,KAClB,OAAM,IAAI,MAAM,+BAA+B,KAAK,WAAW,WAAW;AAE5E,eAAS,OAAO;;AAElB;AAAO;;AAET,QAAI,OAAO,OAAO,OAChB,OAAM,IAAI,MAAM,+BAA+B,KAAK,WAAW,WAAW;AAE5E;AAAO;AACP,WAAO,KAAK;KAAE,MAAM;KAAU;KAAO;KAAM,QAAQ;KAAU,CAAC;AAC9D;;AAIF,OAAI,MAAM,OAAO,MAAM,KAAK;IAC1B,MAAM,WAAW;IACjB,IAAI,MAAM;AACV,WAAO,MAAM,OAAO,WAAY,OAAO,QAAQ,OAAO,OAAO,QAAQ,OAAQ,OAAO,SAAS,MAAM;AACjG,YAAO,OAAO;AACd;AAAO;;AAET,WAAO,KAAK;KAAE,MAAM;KAAU,OAAO;KAAK;KAAM,QAAQ;KAAU,CAAC;AACnE;;AAIF,OAAI,OAAO,KAAK;IACd,MAAM,OAAO,OAAO,MAAM;AAC1B,QAAI,SAAS,WAAe,QAAQ,OAAO,QAAQ,OAAS,QAAQ,OAAO,QAAQ,OAAQ,SAAS,OAAO,SAAS,OAAO,SAAS,MAAM;KACxI,MAAM,WAAW;KACjB,IAAI,OAAO;AACX,YAAO,MAAM,OAAO,UAAU,OAAO,SAAS,OAAO,OAAO,SAAS,OAAQ,OAAO,SAAS,QAAQ,OAAO,SAAS,QAAQ,OAAO,SAAS,OAAO,OAAO,SAAS,OAAO,OAAO,SAAS,OAAO,OAAO,SAAS,OAAO,OAAO,SAAS,KAAK;AAE5O,UAAI,OAAO,SAAS,OAAO,MAAM,IAAI,OAAO,UAAU,OAAO,MAAM,OAAO,KAAK;AAC7E,eAAQ,OAAO;AAAM;AAAO;AAC5B,eAAQ,OAAO;AAAM;AAAO;AAC5B,cAAO,MAAM,OAAO,UAAU,OAAO,SAAS,KAAK;AACjD,gBAAQ,OAAO;AAAM;AAAO;;AAE9B,WAAI,MAAM,OAAO,QAAQ;AACvB,gBAAQ,OAAO;AAAM;AAAO;;AAE9B;;AAEF,cAAQ,OAAO;AACf;AAAO;;AAET,YAAO,KAAK;MAAE,MAAM;MAAQ,OAAO;MAAM;MAAM,QAAQ;MAAU,CAAC;AAClE;;AAEF,WAAO,KAAK;KAAE,MAAM;KAAS,OAAO;KAAK;KAAM,QAAQ;KAAK,CAAC;AAAE;AAAO;AAAO;;AAI/E,OAAK,MAAM,OAAO,MAAM,OAAS,MAAM,OAAO,MAAM,OAAQ,OAAO,KAAK;IACtE,MAAM,WAAW;IACjB,IAAI,QAAQ;AACZ,WAAO,MAAM,OAAO,WAAY,OAAO,QAAQ,OAAO,OAAO,QAAQ,OAAS,OAAO,QAAQ,OAAO,OAAO,QAAQ,OAAS,OAAO,QAAQ,OAAO,OAAO,QAAQ,OAAQ,OAAO,SAAS,MAAM;AAC7L,cAAS,OAAO;AAChB;AAAO;;AAGT,QAAI,UAAU,WAAW,MAAM,OAAO,UAAU,OAAO,SAAS,KAE9D;SADa,OAAO,MAAM,MAAM,GAAG,MAAM,EAAE,KAC9B,MAAM;AACjB,aAAO;AAAG,aAAO;AACjB,aAAO,KAAK;OAAE,MAAM;OAAY,OAAO;OAAY;OAAM,QAAQ;OAAU,CAAC;AAC5E;;;IAGJ,MAAM,KAAK,OAAO,OAAO,UAAU,MAAM,GAAG,SAAS,SAAS;AAC9D,WAAO,KAAK;KAAE,MAAM,MAAM;KAAc,OAAO;KAAO;KAAM,QAAQ;KAAU,CAAC;AAC/E;;AAKF,OAAI,OAAO,KAAK;AAAE,WAAO,KAAK;KAAE,MAAM;KAAQ,OAAO;KAAK;KAAM,QAAQ;KAAK,CAAC;AAAE;AAAO;AAAO;;AAC9F,OAAI,OAAO,KAAK;AACd,QAAI,OAAO,MAAM,OAAO,KAAK;AAC3B,YAAO,KAAK;MAAE,MAAM;MAAS,OAAO;MAAM;MAAM,QAAQ;MAAK,CAAC;AAAE,YAAO;AAAG,YAAO;AAAG;;AAEtF,WAAO,KAAK;KAAE,MAAM;KAAS,OAAO;KAAK;KAAM,QAAQ;KAAK,CAAC;AAAE;AAAO;AAAO;;AAE/E,OAAI,OAAO,KAAK;AAAE,WAAO,KAAK;KAAE,MAAM;KAAQ,OAAO;KAAK;KAAM,QAAQ;KAAK,CAAC;AAAE;AAAO;AAAO;;AAE9F,OAAI,OAAO,KAAK;AAAE,WAAO,KAAK;KAAE,MAAM;KAAQ,OAAO;KAAK;KAAM,QAAQ;KAAK,CAAC;AAAE;AAAO;AAAO;;AAC9F,OAAI,OAAO,KAAK;AACd,QAAI,OAAO,MAAM,OAAO,KAAK;AAC3B,YAAO,KAAK;MAAE,MAAM;MAAM,OAAO;MAAM;MAAM,QAAQ;MAAK,CAAC;AAAE,YAAO;AAAG,YAAO;AAAG;;AAEnF,WAAO,KAAK;KAAE,MAAM;KAAU,OAAO;KAAK;KAAM,QAAQ;KAAK,CAAC;AAAE;AAAO;AAAO;;AAEhF,OAAI,OAAO,KACT;QAAI,OAAO,MAAM,OAAO,KAAK;AAC3B,YAAO,KAAK;MAAE,MAAM;MAAO,OAAO;MAAM;MAAM,QAAQ;MAAK,CAAC;AAAE,YAAO;AAAG,YAAO;AAAG;;;AAGtF,OAAI,OAAO,KAAK;AACd,QAAI,OAAO,MAAM,OAAO,KAAK;AAC3B,YAAO,KAAK;MAAE,MAAM;MAAO,OAAO;MAAM;MAAM,QAAQ;MAAK,CAAC;AAAE,YAAO;AAAG,YAAO;AAAG;;AAEpF,WAAO,KAAK;KAAE,MAAM;KAAM,OAAO;KAAK;KAAM,QAAQ;KAAK,CAAC;AAAE;AAAO;AAAO;;AAE5E,OAAI,OAAO,KAAK;AACd,QAAI,OAAO,MAAM,OAAO,KAAK;AAC3B,YAAO,KAAK;MAAE,MAAM;MAAO,OAAO;MAAM;MAAM,QAAQ;MAAK,CAAC;AAAE,YAAO;AAAG,YAAO;AAAG;;AAEpF,WAAO,KAAK;KAAE,MAAM;KAAM,OAAO;KAAK;KAAM,QAAQ;KAAK,CAAC;AAAE;AAAO;AAAO;;AAE5E,OAAI,OAAO,KAAK;AAAE,WAAO,KAAK;KAAE,MAAM;KAAO,OAAO;KAAK;KAAM,QAAQ;KAAK,CAAC;AAAE;AAAO;AAAO;;AAC7F,OAAI,OAAO,KAAK;AAAE,WAAO,KAAK;KAAE,MAAM;KAAS,OAAO;KAAK;KAAM,QAAQ;KAAK,CAAC;AAAE;AAAO;AAAO;;AAC/F,OAAI,OAAO,KAAK;AAAE,WAAO,KAAK;KAAE,MAAM;KAAU,OAAO;KAAK;KAAM,QAAQ;KAAK,CAAC;AAAE;AAAO;AAAO;;AAChG,OAAI,OAAO,KAAK;AAAE,WAAO,KAAK;KAAE,MAAM;KAAU,OAAO;KAAK;KAAM,QAAQ;KAAK,CAAC;AAAE;AAAO;AAAO;;AAChG,OAAI,OAAO,KAAK;AAAE,WAAO,KAAK;KAAE,MAAM;KAAY,OAAO;KAAK;KAAM,QAAQ;KAAK,CAAC;AAAE;AAAO;AAAO;;AAClG,OAAI,OAAO,KAAK;AAAE,WAAO,KAAK;KAAE,MAAM;KAAY,OAAO;KAAK;KAAM,QAAQ;KAAK,CAAC;AAAE;AAAO;AAAO;;AAClG,OAAI,OAAO,KAAK;AAAE,WAAO,KAAK;KAAE,MAAM;KAAU,OAAO;KAAK;KAAM,QAAQ;KAAK,CAAC;AAAE;AAAO;AAAO;;AAChG,OAAI,OAAO,KAAK;AAAE,WAAO,KAAK;KAAE,MAAM;KAAU,OAAO;KAAK;KAAM,QAAQ;KAAK,CAAC;AAAE;AAAO;AAAO;;AAChG,OAAI,OAAO,KAAK;AAAE,WAAO,KAAK;KAAE,MAAM;KAAM,OAAO;KAAK;KAAM,QAAQ;KAAK,CAAC;AAAE;AAAO;AAAO;;AAC5F,OAAI,OAAO,KAAK;AAAE,WAAO,KAAK;KAAE,MAAM;KAAU,OAAO;KAAK;KAAM,QAAQ;KAAK,CAAC;AAAE;AAAO;AAAO;;AAChG,OAAI,OAAO,KAAK;AAAE,WAAO,KAAK;KAAE,MAAM;KAAS,OAAO;KAAK;KAAM,QAAQ;KAAK,CAAC;AAAE;AAAO;AAAO;;AAE/F,SAAM,IAAI,MAAM,2BAA2B,GAAG,YAAY,KAAK,WAAW,MAAM;;AAGlF,SAAO,KAAK;GAAE,MAAM;GAAO,OAAO;GAAI;GAAM,QAAQ;GAAK,CAAC;AAC1D,SAAO"}
1
+ {"version":3,"file":"lexer.mjs","names":[],"sources":["../src/lexer.ts"],"sourcesContent":["export type TokenType =\n | \"JOB\" | \"FIND\" | \"WHERE\" | \"MAP\" | \"SAVE\" | \"PUBLISH\" | \"TEE\" | \"FANOUT\" | \"INPUT\" | \"OUTPUT\"\n | \"ACTION\" | \"ROUTE\" | \"LOOKUP\" | \"ARROW\" | \"IN\"\n | \"PLUS\" | \"MINUS\" | \"STAR\" | \"SLASH\"\n | \"PIPE\" | \"ASSIGN\" | \"DOT\" | \"COMMA\" | \"COLON\"\n | \"LPAREN\" | \"RPAREN\" | \"LBRACKET\" | \"RBRACKET\" | \"LBRACE\" | \"RBRACE\"\n | \"IDENTIFIER\" | \"STRING\" | \"NUMBER\" | \"PATH\" | \"AT\"\n | \"GT\" | \"LT\" | \"GTE\" | \"LTE\" | \"EQ\" | \"NEQ\"\n | \"LET\" | \"PARAM\" | \"ON\" | \"DOLLAR\" | \"COUNT\" | \"GROUP_BY\"\n | \"NEWLINE\" | \"EOF\";\n\nexport interface Token {\n type: TokenType;\n value: string;\n line: number;\n column: number;\n}\n\nconst KEYWORDS: Record<string, TokenType> = {\n job: \"JOB\",\n find: \"FIND\",\n where: \"WHERE\",\n map: \"MAP\",\n save: \"SAVE\",\n publish: \"PUBLISH\",\n tee: \"TEE\",\n fanout: \"FANOUT\",\n input: \"INPUT\",\n output: \"OUTPUT\",\n let: \"LET\",\n count: \"COUNT\",\n action: \"ACTION\",\n route: \"ROUTE\",\n lookup: \"LOOKUP\",\n param: \"PARAM\",\n on: \"ON\",\n in: \"IN\",\n};\n\nexport class AshLexer {\n tokenize(source: string): Token[] {\n const tokens: Token[] = [];\n let pos = 0;\n let line = 1;\n let col = 1;\n\n while (pos < source.length) {\n const ch = source[pos];\n\n // Newline\n if (ch === \"\\n\" || ch === \"\\r\") {\n if (ch === \"\\r\" && source[pos + 1] === \"\\n\") pos++;\n tokens.push({ type: \"NEWLINE\", value: \"\\\\n\", line, column: col });\n pos++;\n line++;\n col = 1;\n continue;\n }\n\n // Whitespace (skip)\n if (ch === \" \" || ch === \"\\t\") {\n pos++;\n col++;\n continue;\n }\n\n // Comment: # to end of line\n if (ch === \"#\") {\n while (pos < source.length && source[pos] !== \"\\n\" && source[pos] !== \"\\r\") {\n pos++;\n col++;\n }\n continue;\n }\n\n // String literal\n if (ch === '\"') {\n const startCol = col;\n pos++; col++;\n let value = \"\";\n while (pos < source.length && source[pos] !== '\"') {\n if (source[pos] === \"\\\\\") {\n pos++; col++;\n if (pos >= source.length) break;\n const escaped = source[pos];\n if (escaped === '\"') value += '\"';\n else if (escaped === \"\\\\\") value += \"\\\\\";\n else if (escaped === \"n\") value += \"\\n\";\n else if (escaped === \"t\") value += \"\\t\";\n else if (escaped === \"$\") value += \"\\\\$\"; // preserve for template escape detection\n else value += escaped;\n } else {\n if (source[pos] === \"\\n\") {\n throw new Error(`Unterminated string at line ${line}, column ${startCol}`);\n }\n value += source[pos];\n }\n pos++; col++;\n }\n if (pos >= source.length) {\n throw new Error(`Unterminated string at line ${line}, column ${startCol}`);\n }\n pos++; col++; // closing quote\n tokens.push({ type: \"STRING\", value, line, column: startCol });\n continue;\n }\n\n // Number\n if (ch >= \"0\" && ch <= \"9\") {\n const startCol = col;\n let num = \"\";\n while (pos < source.length && ((source[pos] >= \"0\" && source[pos] <= \"9\") || source[pos] === \".\")) {\n num += source[pos];\n pos++; col++;\n }\n tokens.push({ type: \"NUMBER\", value: num, line, column: startCol });\n continue;\n }\n\n // Path or SLASH: `/` followed by a letter, `.`, `_`, or `/` starts a PATH; otherwise SLASH\n if (ch === \"/\") {\n const next = source[pos + 1];\n if (next !== undefined && ((next >= \"a\" && next <= \"z\") || (next >= \"A\" && next <= \"Z\") || next === \"_\" || next === \".\" || next === \"/\")) {\n const startCol = col;\n let path = \"\";\n while (pos < source.length && source[pos] !== \" \" && source[pos] !== \"\\t\" && source[pos] !== \"\\n\" && source[pos] !== \"\\r\" && source[pos] !== \"|\" && source[pos] !== \"}\" && source[pos] !== \")\" && source[pos] !== \",\" && source[pos] !== \":\") {\n // Handle ${...} template blocks atomically — don't stop at } inside template\n if (source[pos] === \"$\" && pos + 1 < source.length && source[pos + 1] === \"{\") {\n path += source[pos]; pos++; col++; // $\n path += source[pos]; pos++; col++; // {\n while (pos < source.length && source[pos] !== \"}\") {\n path += source[pos]; pos++; col++;\n }\n if (pos < source.length) {\n path += source[pos]; pos++; col++; // closing }\n }\n continue;\n }\n path += source[pos];\n pos++; col++;\n }\n tokens.push({ type: \"PATH\", value: path, line, column: startCol });\n continue;\n }\n tokens.push({ type: \"SLASH\", value: \"/\", line, column: col }); pos++; col++; continue;\n }\n\n // Identifier / keyword\n if ((ch >= \"a\" && ch <= \"z\") || (ch >= \"A\" && ch <= \"Z\") || ch === \"_\") {\n const startCol = col;\n let ident = \"\";\n while (pos < source.length && ((source[pos] >= \"a\" && source[pos] <= \"z\") || (source[pos] >= \"A\" && source[pos] <= \"Z\") || (source[pos] >= \"0\" && source[pos] <= \"9\") || source[pos] === \"_\")) {\n ident += source[pos];\n pos++; col++;\n }\n // Handle compound keyword: group-by\n if (ident === \"group\" && pos < source.length && source[pos] === \"-\") {\n const rest = source.slice(pos + 1, pos + 3);\n if (rest === \"by\") {\n pos += 3; col += 3;\n tokens.push({ type: \"GROUP_BY\", value: \"group-by\", line, column: startCol });\n continue;\n }\n }\n const kw = Object.hasOwn(KEYWORDS, ident) ? KEYWORDS[ident] : undefined;\n tokens.push({ type: kw ?? \"IDENTIFIER\", value: ident, line, column: startCol });\n continue;\n }\n\n // Operators and punctuation\n // Arithmetic operators\n if (ch === \"+\") { tokens.push({ type: \"PLUS\", value: \"+\", line, column: col }); pos++; col++; continue; }\n if (ch === \"-\") {\n if (source[pos + 1] === \">\") {\n tokens.push({ type: \"ARROW\", value: \"->\", line, column: col }); pos += 2; col += 2; continue;\n }\n tokens.push({ type: \"MINUS\", value: \"-\", line, column: col }); pos++; col++; continue;\n }\n if (ch === \"*\") { tokens.push({ type: \"STAR\", value: \"*\", line, column: col }); pos++; col++; continue; }\n\n if (ch === \"|\") { tokens.push({ type: \"PIPE\", value: \"|\", line, column: col }); pos++; col++; continue; }\n if (ch === \"=\") {\n if (source[pos + 1] === \"=\") {\n tokens.push({ type: \"EQ\", value: \"==\", line, column: col }); pos += 2; col += 2; continue;\n }\n tokens.push({ type: \"ASSIGN\", value: \"=\", line, column: col }); pos++; col++; continue;\n }\n if (ch === \"!\") {\n if (source[pos + 1] === \"=\") {\n tokens.push({ type: \"NEQ\", value: \"!=\", line, column: col }); pos += 2; col += 2; continue;\n }\n }\n if (ch === \">\") {\n if (source[pos + 1] === \"=\") {\n tokens.push({ type: \"GTE\", value: \">=\", line, column: col }); pos += 2; col += 2; continue;\n }\n tokens.push({ type: \"GT\", value: \">\", line, column: col }); pos++; col++; continue;\n }\n if (ch === \"<\") {\n if (source[pos + 1] === \"=\") {\n tokens.push({ type: \"LTE\", value: \"<=\", line, column: col }); pos += 2; col += 2; continue;\n }\n tokens.push({ type: \"LT\", value: \"<\", line, column: col }); pos++; col++; continue;\n }\n if (ch === \".\") { tokens.push({ type: \"DOT\", value: \".\", line, column: col }); pos++; col++; continue; }\n if (ch === \",\") { tokens.push({ type: \"COMMA\", value: \",\", line, column: col }); pos++; col++; continue; }\n if (ch === \"(\") { tokens.push({ type: \"LPAREN\", value: \"(\", line, column: col }); pos++; col++; continue; }\n if (ch === \")\") { tokens.push({ type: \"RPAREN\", value: \")\", line, column: col }); pos++; col++; continue; }\n if (ch === \"[\") { tokens.push({ type: \"LBRACKET\", value: \"[\", line, column: col }); pos++; col++; continue; }\n if (ch === \"]\") { tokens.push({ type: \"RBRACKET\", value: \"]\", line, column: col }); pos++; col++; continue; }\n if (ch === \"{\") { tokens.push({ type: \"LBRACE\", value: \"{\", line, column: col }); pos++; col++; continue; }\n if (ch === \"}\") { tokens.push({ type: \"RBRACE\", value: \"}\", line, column: col }); pos++; col++; continue; }\n if (ch === \"@\") { tokens.push({ type: \"AT\", value: \"@\", line, column: col }); pos++; col++; continue; }\n if (ch === \"$\") { tokens.push({ type: \"DOLLAR\", value: \"$\", line, column: col }); pos++; col++; continue; }\n if (ch === \":\") { tokens.push({ type: \"COLON\", value: \":\", line, column: col }); pos++; col++; continue; }\n\n throw new Error(`Unrecognized character '${ch}' at line ${line}, column ${col}`);\n }\n\n tokens.push({ type: \"EOF\", value: \"\", line, column: col });\n return tokens;\n }\n}\n"],"mappings":"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"}
package/dist/parser.cjs CHANGED
@@ -30,7 +30,8 @@ var AshParser = class AshParser {
30
30
  "route",
31
31
  "lookup",
32
32
  "param",
33
- "on"
33
+ "on",
34
+ "in"
34
35
  ]);
35
36
  parse(tokens) {
36
37
  this.tokens = tokens;
@@ -336,6 +337,41 @@ var AshParser = class AshParser {
336
337
  parseWhere() {
337
338
  const left = this.parseFieldAccess();
338
339
  const opToken = this.advance();
340
+ if (opToken.type === "IN") {
341
+ if (!this.isAtEnd() && this.peek().type === "DOLLAR") {
342
+ this.advance();
343
+ return {
344
+ kind: "where",
345
+ left,
346
+ op: "in",
347
+ right: "$" + this.advance().value
348
+ };
349
+ }
350
+ if (this.isAtEnd() || this.peek().type !== "LBRACKET") throw new Error(`Expected '[' or '$variable' after 'in' at line ${opToken.line}, column ${opToken.column}`);
351
+ this.advance();
352
+ this.skipNewlines();
353
+ const values = [];
354
+ while (!this.isAtEnd() && this.peek().type !== "RBRACKET") {
355
+ const valToken = this.advance();
356
+ if (valToken.type === "NUMBER") values.push(parseFloat(valToken.value));
357
+ else if (valToken.type === "STRING") values.push(valToken.value);
358
+ else if (valToken.type === "IDENTIFIER") values.push(valToken.value);
359
+ else throw new Error(`Expected string, number, or identifier in 'in' list at line ${valToken.line}, column ${valToken.column}`);
360
+ this.skipNewlines();
361
+ if (!this.isAtEnd() && this.peek().type === "COMMA") {
362
+ this.advance();
363
+ this.skipNewlines();
364
+ }
365
+ }
366
+ if (this.isAtEnd()) throw new Error(`Expected ']' to close 'in' list at line ${opToken.line}, column ${opToken.column}`);
367
+ this.advance();
368
+ return {
369
+ kind: "where",
370
+ left,
371
+ op: "in",
372
+ right: values
373
+ };
374
+ }
339
375
  const op = {
340
376
  "==": "==",
341
377
  "!=": "!=",
@@ -512,10 +548,15 @@ var AshParser = class AshParser {
512
548
  }
513
549
  if (t.type === "LBRACKET") {
514
550
  this.advance();
551
+ this.skipNewlines();
515
552
  const elements = [];
516
553
  while (!this.isAtEnd() && this.peek().type !== "RBRACKET") {
517
554
  elements.push(this.parseExpression());
518
- if (!this.isAtEnd() && this.peek().type === "COMMA") this.advance();
555
+ this.skipNewlines();
556
+ if (!this.isAtEnd() && this.peek().type === "COMMA") {
557
+ this.advance();
558
+ this.skipNewlines();
559
+ }
519
560
  }
520
561
  this.expect("RBRACKET", "Expected ']' after array literal");
521
562
  return {
@@ -525,12 +566,17 @@ var AshParser = class AshParser {
525
566
  }
526
567
  if (t.type === "LBRACE") {
527
568
  this.advance();
569
+ this.skipNewlines();
528
570
  const properties = {};
529
571
  while (!this.isAtEnd() && this.peek().type !== "RBRACE") {
530
572
  const keyToken = this.expect("IDENTIFIER", "Expected property name in object literal");
531
573
  this.expect("COLON", "Expected ':' after property name");
532
574
  properties[keyToken.value] = this.parseExpression();
533
- if (!this.isAtEnd() && this.peek().type === "COMMA") this.advance();
575
+ this.skipNewlines();
576
+ if (!this.isAtEnd() && this.peek().type === "COMMA") {
577
+ this.advance();
578
+ this.skipNewlines();
579
+ }
534
580
  }
535
581
  this.expect("RBRACE", "Expected '}' after object literal");
536
582
  return {
@@ -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,QAuCA,gBAAA;EAAA,QAWA,YAAA;EAAA,QAuFA,eAAA;EAAA,QAUA,SAAA;EAAA,QAUA,WAAA;EAAA,QA6EA,WAAA;EAAA,QA+DA,UAAA;EAAA,QAmDA,WAAA;EAAA,QAeA,WAAA;EAzTA;EAAA,QAsVA,cAAA;EAAA,QAmEA,IAAA;EAAA,QAIA,OAAA;EAAA,QAIA,MAAA;EAAA,QASA,OAAA;EAAA,QAIA,YAAA;AAAA"}
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,QAIA,MAAA;EAAA,QASA,OAAA;EAAA,QAIA,YAAA;AAAA"}
@@ -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,QAuCA,gBAAA;EAAA,QAWA,YAAA;EAAA,QAuFA,eAAA;EAAA,QAUA,SAAA;EAAA,QAUA,WAAA;EAAA,QA6EA,WAAA;EAAA,QA+DA,UAAA;EAAA,QAmDA,WAAA;EAAA,QAeA,WAAA;EAzTA;EAAA,QAsVA,cAAA;EAAA,QAmEA,IAAA;EAAA,QAIA,OAAA;EAAA,QAIA,MAAA;EAAA,QASA,OAAA;EAAA,QAIA,YAAA;AAAA"}
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,QAIA,MAAA;EAAA,QASA,OAAA;EAAA,QAIA,YAAA;AAAA"}
package/dist/parser.mjs CHANGED
@@ -29,7 +29,8 @@ var AshParser = class AshParser {
29
29
  "route",
30
30
  "lookup",
31
31
  "param",
32
- "on"
32
+ "on",
33
+ "in"
33
34
  ]);
34
35
  parse(tokens) {
35
36
  this.tokens = tokens;
@@ -335,6 +336,41 @@ var AshParser = class AshParser {
335
336
  parseWhere() {
336
337
  const left = this.parseFieldAccess();
337
338
  const opToken = this.advance();
339
+ if (opToken.type === "IN") {
340
+ if (!this.isAtEnd() && this.peek().type === "DOLLAR") {
341
+ this.advance();
342
+ return {
343
+ kind: "where",
344
+ left,
345
+ op: "in",
346
+ right: "$" + this.advance().value
347
+ };
348
+ }
349
+ if (this.isAtEnd() || this.peek().type !== "LBRACKET") throw new Error(`Expected '[' or '$variable' after 'in' at line ${opToken.line}, column ${opToken.column}`);
350
+ this.advance();
351
+ this.skipNewlines();
352
+ const values = [];
353
+ while (!this.isAtEnd() && this.peek().type !== "RBRACKET") {
354
+ const valToken = this.advance();
355
+ if (valToken.type === "NUMBER") values.push(parseFloat(valToken.value));
356
+ else if (valToken.type === "STRING") values.push(valToken.value);
357
+ else if (valToken.type === "IDENTIFIER") values.push(valToken.value);
358
+ else throw new Error(`Expected string, number, or identifier in 'in' list at line ${valToken.line}, column ${valToken.column}`);
359
+ this.skipNewlines();
360
+ if (!this.isAtEnd() && this.peek().type === "COMMA") {
361
+ this.advance();
362
+ this.skipNewlines();
363
+ }
364
+ }
365
+ if (this.isAtEnd()) throw new Error(`Expected ']' to close 'in' list at line ${opToken.line}, column ${opToken.column}`);
366
+ this.advance();
367
+ return {
368
+ kind: "where",
369
+ left,
370
+ op: "in",
371
+ right: values
372
+ };
373
+ }
338
374
  const op = {
339
375
  "==": "==",
340
376
  "!=": "!=",
@@ -511,10 +547,15 @@ var AshParser = class AshParser {
511
547
  }
512
548
  if (t.type === "LBRACKET") {
513
549
  this.advance();
550
+ this.skipNewlines();
514
551
  const elements = [];
515
552
  while (!this.isAtEnd() && this.peek().type !== "RBRACKET") {
516
553
  elements.push(this.parseExpression());
517
- if (!this.isAtEnd() && this.peek().type === "COMMA") this.advance();
554
+ this.skipNewlines();
555
+ if (!this.isAtEnd() && this.peek().type === "COMMA") {
556
+ this.advance();
557
+ this.skipNewlines();
558
+ }
518
559
  }
519
560
  this.expect("RBRACKET", "Expected ']' after array literal");
520
561
  return {
@@ -524,12 +565,17 @@ var AshParser = class AshParser {
524
565
  }
525
566
  if (t.type === "LBRACE") {
526
567
  this.advance();
568
+ this.skipNewlines();
527
569
  const properties = {};
528
570
  while (!this.isAtEnd() && this.peek().type !== "RBRACE") {
529
571
  const keyToken = this.expect("IDENTIFIER", "Expected property name in object literal");
530
572
  this.expect("COLON", "Expected ':' after property name");
531
573
  properties[keyToken.value] = this.parseExpression();
532
- if (!this.isAtEnd() && this.peek().type === "COMMA") this.advance();
574
+ this.skipNewlines();
575
+ if (!this.isAtEnd() && this.peek().type === "COMMA") {
576
+ this.advance();
577
+ this.skipNewlines();
578
+ }
533
579
  }
534
580
  this.expect("RBRACE", "Expected '}' after object literal");
535
581
  return {
@@ -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\"]);\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 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 const elements: Expression[] = [];\n while (!this.isAtEnd() && this.peek().type !== \"RBRACKET\") {\n elements.push(this.parseExpression());\n if (!this.isAtEnd() && this.peek().type === \"COMMA\") {\n this.advance(); // ,\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 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 if (!this.isAtEnd() && this.peek().type === \"COMMA\") {\n this.advance(); // ,\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.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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aigne/ash",
3
- "version": "0.0.2-beta.0",
3
+ "version": "0.0.2-beta.1",
4
4
  "files": [
5
5
  "dist",
6
6
  "README.md"
@@ -21,12 +21,14 @@
21
21
  "./*": "./*"
22
22
  },
23
23
  "devDependencies": {
24
+ "esbuild": "^0.27.3",
24
25
  "npm-run-all": "^4.1.5",
25
26
  "rimraf": "^6.1.2",
26
27
  "tsdown": "0.20.0-beta.3"
27
28
  },
28
29
  "scripts": {
29
30
  "build": "tsdown",
31
+ "build:runtime": "node build-runtime.mjs",
30
32
  "check-types": "tsc --noEmit",
31
33
  "clean": "rimraf dist"
32
34
  }